빌드노트
Dockerfile의 cd는 다음 RUN까지 이어지지 않는다
Dockerfile의 cd가 다음 RUN에 이어지지 않아 파일을 못 찾을 때, pwd와 절대 경로 조회로 원인을 좁힌다. 한 RUN 안에서 이동할 경우와 이후 명령에 WORKDIR를 선언할 경우를 실제 빌드 결과로 구분한다.
Dockerfile에서 RUN cd /app는 성공했는데 다음 RUN ./build.sh가 파일을 못 찾는다면, 두 명령의 작업 디렉터리를 확인한다. cd는 그 RUN을 실행하는 셸의 현재 위치만 바꾼다. 한 번만 이동하려면 실행할 명령을 같은 RUN에 연결하고, 이후 명령도 그 위치에서 시작해야 한다면 WORKDIR /app를 선언한다.
실패하는 RUN에서 위치와 파일을 함께 확인한다
아래는 이미지 안의 /app/build.sh를 실행하려는 경우다. Linux 이미지에 /bin/sh, pwd, ls가 있고, 앞선 단계에서 스크립트를 준비했다는 전제다. 자신의 Dockerfile에서 실패하는 RUN ./build.sh를 잠시 다음 줄로 바꾼다. /app과 파일명은 이미지 안의 실제 경로로 바꾼다.
RUN pwd && ls -l /app/build.sh && ./build.sh
빌드 컨텍스트 폴더에서 docker build --progress=plain --no-cache -t cd-workdir-check:local .로 출력을 확인한다. 기본 파일명은 Dockerfile이며, 다른 파일을 쓰던 경우 기존 -f 지정도 유지한다. 태그는 다른 이미지와 겹치지 않는 실습용 이름으로 바꾼다. --progress=plain은 명령 출력을 읽기 위한 옵션이고, --no-cache는 진단용 RUN을 다시 실행하기 위한 옵션이다. 실행 중인 Linux Docker 엔진과 해당 베이스 이미지를 사용할 수 있어야 한다. Docker 빌드 옵션 (새 탭에서 열림)
전체 경로 조회는 성공하는데 pwd가 /app이 아닌 곳을 출력한다면, ./build.sh는 파일이 있는 폴더와 다른 곳을 기준으로 실행되고 있다. 조회부터 실패한다면 파일을 생성하거나 복사한 위치와 이름을 먼저 확인한다. pwd도 /app이고 파일도 보인다면, 이 글의 디렉터리 유지 문제만으로 실행 실패를 설명할 수는 없다.
이 진단 줄은 별도로 만든 FROM busybox:1.37.0 이미지에서도 실행했다. WORKDIR /에서 시작해 합성 스크립트를 /app/build.sh에 준비하고, 별도 RUN cd /app 뒤에 진단 줄을 넣었다. 출력은 /, 스크립트의 파일 정보, /bin/sh: ./build.sh: not found 순서였고 빌드는 종료 코드 1로 실패했다. 파일은 있었지만 상대 경로의 기준이 달랐다. 실제 앱의 빌드 스크립트를 실행한 결과는 아니다.
필요한 범위에 맞춰 고친다
그 명령 한 번만 /app에서 실행하면 된다면, 따로 둔 RUN cd /app와 RUN ./build.sh를 다음 한 줄로 바꾼다. &&로 연결하면 이동에 성공한 경우에만 스크립트를 실행한다.
RUN cd /app && ./build.sh
합성 스크립트로 확인한 이 수정은 성공했고, 스크립트 안의 pwd는 /app을 출력했다. 다만 이어지는 별도 RUN pwd는 다시 /였다. 같은 RUN 안에 연결한 명령까지만 이동한 위치를 쓰는 것이다.
뒤의 여러 RUN도 /app에서 시작해야 한다면, 파일을 준비한 뒤 실행 명령들 앞에 작업 디렉터리를 선언한다. 아래 마지막 줄은 그 위치에서 생성 파일을 읽는 확인용 명령이다. result.txt는 자신의 스크립트가 만드는 상대 경로의 파일명으로 바꾼다.
WORKDIR /app
RUN ./build.sh
RUN pwd && cat result.txt
같은 합성 스크립트가 result.txt에 synthetic-build를 쓰게 하고 실행하자, 스크립트 내부와 다음 RUN의 pwd가 모두 /app이었다. 마지막 읽기도 synthetic-build를 출력했고 빌드는 성공했다. 생성 파일은 /app/result.txt에 있었다. Docker 문서에 따르면 WORKDIR는 이후 RUN의 시작 위치를 정하고, 지정한 디렉터리가 없으면 만든다. 파일 자체를 준비하는 작업은 여전히 필요하다. WORKDIR 규칙 (새 탭에서 열림)
앞선 RUN의 작업이 전부 사라지는 것은 아니다. 위치만 비교한 별도 빌드에서, cd /lesson과 같은 RUN의 pwd는 /lesson, 다음 RUN의 pwd는 /였다. 그래도 앞서 쓴 /lesson/first.txt는 다음 명령에서 전체 경로로 읽혔다. 다음 명령이 상대 경로로 쓴 파일은 /next.txt에 생겼고, WORKDIR /lesson 뒤에 쓴 파일은 /lesson/workdir.txt에 생겼다. 파일시스템 변경은 남지만 앞 셸의 현재 위치는 전달되지 않는다. Docker 문서의 RUN 설명과 Linux 기본 셸인 /bin/sh -c를 이 관찰과 함께 구분해 읽어야 한다. RUN (새 탭에서 열림), SHELL (새 탭에서 열림)
다음 RUN이 항상 /에서 시작하는 것은 아니다. 앞서 선언했거나 베이스 이미지에서 물려받은 WORKDIR가 있으면 그 위치가 기준이다. 실패 명령 직전까지 적용된 설정을 확인하고, 의도한 기준은 WORKDIR /app처럼 절대 경로로 적는다. 상대 WORKDIR는 이전 작업 디렉터리에 이어 붙기 때문이다.
이 비교는 2026년 10월 22일 KST에 Windows 11의 Docker Desktop 4.92.0, Linux Engine 29.8.0, BuildKit 0.33.0, Buildx 0.37.1과 busybox:1.37.0으로 실행했다. 확인한 범위는 단일 Linux 빌드 단계의 셸 형식 RUN과 일반 파일이다. 상속된 WORKDIR의 규칙은 문서로 확인했으며 별도 상속 변형은 실행하지 않았다. Windows 컨테이너, 사용자 지정 SHELL, 여러 빌드 단계 사이의 설정 전달도 실행하지 않았다.