빌드노트
다른 폴더에서 Compose를 실행해도 ./config가 바뀌지 않는 이유
다른 폴더에서 Compose를 실행해도 ./config가 예상과 다른 곳을 가리킬 때, 기존 실행 옵션의 config source와 실제 컨테이너 Mounts.Source를 비교한다. 직접 관찰한 경로·파일 결과를 바탕으로 --project-directory로 기준을 명시할지 판단한다.
다른 폴더로 이동해 docker compose -f ...를 실행했는데 컨테이너가 예상과 다른 설정을 읽는다면, 먼저 ./config가 어느 호스트 폴더로 해석됐는지 확인한다. 로컬 Compose 파일을 지정할 때 상대 bind 경로의 기본 기준은 첫 번째 -f 파일이 있는 폴더, 즉 기본 project directory다. 터미널에서 폴더만 옮겨도 이 기준은 바뀌지 않는다. Compose CLI의 경로 기준 (새 탭에서 열림)
조사할 파일은 현재 폴더의 config를 보고 추측하지 않는다. 실행 때와 같은 옵션으로 얻은 config의 source와 실제 컨테이너의 Mounts.Source를 비교해 고른다. 의도한 기준이 다르면 --project-directory로 명시한다.
지금 쓰는 명령에서 source를 확인한다
다음은 PowerShell과 Docker Compose가 설치된 환경에서 기존 서비스의 설정을 조회하는 예다. 문제가 난 명령을 실행했던 폴더와 환경에서 확인한다. D:\my-service\compose.yaml, 프로젝트 이름 my-service, 서비스 이름 app은 자신의 값으로 바꾼다. app은 Compose의 services 아래 키다.
$composeArgs = @('-p', 'my-service', '-f', 'D:\my-service\compose.yaml')
docker compose @composeArgs config app
$composeArgs에는 원래 사용한 옵션을 순서까지 그대로 옮긴다. 여러 -f, --env-file, --profile, 기존 --project-directory가 있었다면 함께 넣고, 원래 없던 -p를 새로 넣지는 않는다. @composeArgs는 배열의 항목을 각각 명령 인자로 전달하는 PowerShell 문법이다. 위 경로는 새 실습 폴더를 만들라는 뜻이 아니라 이미 쓰는 Compose 파일의 예시다.
출력의 해당 서비스 volumes에서 type: bind인 항목을 찾는다. target은 컨테이너 안의 목적지이고, source가 조사해야 할 호스트 경로다. 원본에 source: ./config가 있어도 여기서는 해석된 경로가 나온다. 경로 해석을 끄는 --no-path-resolution은 붙이지 않는다. 명령이 실패했다면 경로를 확인한 것이 아니므로 오류부터 해결한다. config의 역할과 옵션 (새 탭에서 열림)
이어서 설정을 잘못 읽는 기존 컨테이너를 조회한다. 아래 이름은 자신의 컨테이너 이름이나 ID로 바꾼다. 프로젝트 이름만으로 컨테이너 이름을 추측하지 말고 실제 대상을 사용한다.
$container = 'my-service-app-1'
docker inspect --type container --format '{{json .Mounts}}' $container
JSON 배열에서 앞의 target과 같은 Destination을 찾고, 그 항목의 Type이 bind인지 확인한 뒤 Source를 비교한다. 다른 목적지의 마운트나 Type: volume의 저장 경로를 비교하면 이 문제를 판단할 수 없다. RW: false라면 읽기 전용 마운트다. inspect의 JSON 출력 (새 탭에서 열림), Mounts 필드의 의미 (새 탭에서 열림)
config는 지금 입력한 옵션으로 엔진에 적용할 모델을 보여 준다. 기존 컨테이너가 그 모델로 만들어졌다는 증거는 아니다. 두 Source가 다르면 같은 프로젝트·서비스의 컨테이너인지, 생성할 때 쓴 파일과 옵션이 같은지, 생성 뒤 설정을 바꾸지 않았는지부터 확인한다. No such container라면 조회 대상 이름이나 연결한 엔진이 맞는지 확인해야 한다.
현재 폴더만 바꾼 실험에서는 경로가 그대로였다
이 차이를 확인하려고 Windows 11, Compose v5.5.1, Engine 29.8.0의 로컬 Docker Desktop Linux 엔진에서 합성 설정으로 별도 실행했다. ./config를 읽기 전용으로 연결하고 컨테이너 네트워크를 껐다. 서로 다른 값을 가진 세 호스트 폴더를 준비한 뒤, 같은 Compose 파일을 절대 경로의 -f로 지정했다.
- 현재 폴더가
project일 때:source와 실제Mounts.Source는project\config, 컨테이너 출력은FROM_PROJECT였다. - 현재 폴더만
runner로 바꿨을 때: 두 경로는 여전히project\config, 출력도FROM_PROJECT였다.runner\config에 둔FROM_RUNNER는 읽지 않았다. runner에서--project-directory를 별도explicit-base폴더로 지정했을 때: 두 경로가explicit-base\config로 바뀌었고, 출력은FROM_EXPLICIT_BASE였다.
위 경로는 관찰한 절대 경로에서 공통 실습 루트만 생략한 것이다. 세 경우 모두 실제 컨테이너의 목적지 파일을 읽었고, inspect에서 Type: bind, RW: false를 확인했다. 현재 폴더의 파일을 수정해도 읽는 값이 달라지지 않을 수 있다는 판단은 이 비교에서 얻었다.
의도한 기준을 옵션으로 고정한다
./config가 D:\intended-base\config를 뜻해야 한다면 기준 폴더는 그 상위인 D:\intended-base다. 앞에서 만든 $composeArgs를 이어 사용해 변경될 해석부터 확인한다.
$baseDir = 'D:\intended-base'
docker compose @composeArgs --project-directory $baseDir config app
기존 옵션에 이미 --project-directory가 있었다면 위처럼 추가하지 말고 그 값을 바꾼다. 결과의 bind source가 의도한 폴더인지 확인하고, 실제 컨테이너 생성 명령에도 같은 옵션을 사용한다. 이 조회만으로 기존 컨테이너의 마운트가 바뀌지는 않는다. 재생성한 뒤에는 실제 컨테이너를 다시 inspect해 확인한다. -p는 프로젝트 이름을 정하므로 경로 기준을 바꾸는 대용으로 쓸 수 없다.
--project-directory는 bind 하나만의 설정이 아니므로 다른 상대 경로의 해석도 함께 검토한다. 특정 bind 하나만 고정하려는 경우에는 그 source를 호스트 절대 경로로 쓰는 방법도 있다. 여러 -f를 병합한다면 각 파일의 폴더가 아니라 첫 번째 파일이 기본 경로 기준이라는 문서 규칙을 적용한다. 여러 Compose 파일의 경로 규칙 (새 탭에서 열림)
경로가 의도대로 일치하는데도 내용이 다르면, 이제 그 Source 안의 파일과 해당 Destination 아래에서 앱이 읽는 파일을 대조한다. 마운트 자체가 실패한다면 존재 여부와 파일 공유·권한을 확인한다. 원격 엔진에서는 bind source가 엔진 호스트의 경로이며, Docker Desktop은 VM을 통해 호스트 파일을 공유한다. bind mount의 호스트 제약 (새 탭에서 열림)
직접 실행한 범위는 로컬 파일 한 개의 경로 해석과 컨테이너 마운트·파일 읽기다. 위 PowerShell 조회도 격리된 컨테이너에 실제로 실행했다. 여러 파일 병합, Linux·macOS 호스트와 원격 엔진은 실행하지 않았다. -f -로 표준 입력에서 Compose를 읽으면 현재 폴더가 기준이라는 별도 문서 규칙이 있으며, 이 방식 역시 이번 관찰에는 포함하지 않았다.