Dockerfile에서 WORKDIR의 요점은 무엇입니까?


106

저는 Docker를 배우고 있습니다. 많은 시간 동안 나는 것을 본 적이 Dockerfile있다 WORKDIR명령을 :

FROM node:latest
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install
COPY . /usr/src/app
EXPOSE 3000
CMD [ “npm”, “start” ] 

난 그냥 생략 할 수 없습니다 WORKDIRCopy단지 내를 Dockerfile내 프로젝트의 루트에? 이 접근 방식을 사용하면 어떤 단점이 있습니까?


빌드시 디렉토리를 변경합니다WORKDIR
Ultraviolet

1
@Ultraviolet이 이것을 설명해 주시겠습니까? 요점을 이해하지 못합니다
Le garcon

답변:


118

문서 에 따르면 :

WORKDIR 명령어는 Dockerfile에서 뒤 따르는 RUN, CMD, ENTRYPOINT, COPY 및 ADD 명령어에 대한 작업 디렉토리를 설정합니다. WORKDIR이 존재하지 않으면 후속 Dockerfile 명령어에서 사용되지 않더라도 생성됩니다.

또한 Docker 모범 사례 에서는 다음을 사용하는 것이 좋습니다.

... 읽기, 문제 해결 및 유지 관리가 어려운 RUN cd… && do-something과 같은 명령을 확산시키는 대신 WORKDIR을 사용해야합니다.

나는 그것을 유지하는 것이 좋습니다.

Dockerfile을 다음과 같이 리팩터링 할 수 있다고 생각합니다.

FROM node:latest
WORKDIR /usr/src/app
COPY package.json .
RUN npm install
COPY . ./
EXPOSE 3000
CMD [ “npm”, “start” ] 

2
@MarioGil COPY 문서를
juanlumn

1
내가 사용 FROM ubuntu as builder하고 연속 이미지를 사용할 COPY때 "빌더"이미지에서 WORKDIR을 사용했음을 "알고"또는 그렇지 않은 것으로 가정해야합니까 (절대 경로 사용)?
Alex 75

도커 문서 에 따르면 나는 WORKDIR당신이 COPY하나 를 실행하기 전에 Dockerfile에서 명령이 실행 되었기 때문에 값을 유지한다고 말할 것입니다
juanlumn

귀하의 RUN mkdir명령이 필요하지 않습니다; 즉, 해당 줄이 삭제 될 수 있습니다. 문서에 따르면 "WORKDIR이 존재하지 않으면 후속 Dockerfile 명령에서 사용되지 않더라도 생성됩니다." - docs.docker.com/engine/reference/builder/#workdir
Purplejacket

@Purplejacket 맞습니다. 답변을 업데이트하겠습니다
juanlumn

60

당신은 할 필요가 없습니다

RUN mkdir -p /usr/src/app

지정하면 자동으로 생성됩니다. WORKDIR

FROM node:latest
WORKDIR /usr/src/app
COPY package.json .
RUN npm install
COPY . ./
EXPOSE 3000
CMD [ “npm”, “start” ] 

4
- 그러나, 때로는 디렉토리를 생성 할 때 WORKDIR 사용자를 존중하지 않기 때문에 MKDIR이 필요 RUN github.com/moby/moby/issues/20295
조 Bowbeer

24
WORKDIR을 지정하면 자동으로 폴더가 생성된다는 점이 마음에 듭니다.
GingerBeer

32

컨테이너 내부 WORKDIR처럼 생각할 수 있습니다 cd(명령처럼 나중에 Dockerfile에 나오는 명령에 영향을 미침 RUN). WORKDIR위의 예에서 제거한 경우 컨테이너 내부 RUN npm install/usr/src/app디렉토리에 있지 않기 때문에 작동하지 않습니다 .

이것이 Dockerfile을 넣은 위치와 관련이 있는지 모르겠습니다 (호스트 컴퓨터의 Dockerfile 위치가 컨테이너 내부의 pwd와 관련이 없기 때문입니다). 프로젝트에서 원하는 곳에 Dockerfile을 넣을 수 있습니다. 그러나의 첫 번째 인수 COPY는 상대 경로이므로 Dockerfile을 이동하는 경우 해당 COPY명령 을 업데이트해야 할 수 있습니다 .


3
경우 WORKDIR처럼 추가 cd, 두되지 않습니다 COPY원래의 예는 같은 소스와 대상을 가지고?
Jonas Rosenqvist

5
아니요 . 컨테이너 내부WORKDIR 의 작업 디렉토리에 영향을줍니다 . 원래의 예에서, 첫 번째 에서 복사 호스트 합니다 (Dockerfile 상대 경로)에 컨테이너 . 실제로 대상 (컨테이너 내부)이 상대 경로 (경로가로 시작 함 )를 사용하지 않기 때문에은 특정 명령에 영향을 미치지 않습니다 . COPYpackage.json /usr/src/app/package.json WORKDIR/
mkasberg

@mkasberg If WORKDIRcd. 그럼 아래의 2 개 스 니펫이 동일합니까? WORKDIR /usr/src/app COPY package.json /usr/src/app/그리고 WORKDIR /usr/src/app COPY package.json . 감사합니다
kcatstack 2018

1
예, 동일합니다.
mkasberg

1

WORKDIR 적용 전. 여기서 WORKDIR은 잘못된 위치에 있으며 현명하게 사용되지 않습니다.

FROM microsoft/aspnetcore:2
COPY --from=build-env /publish /publish
WORKDIR /publish
ENTRYPOINT ["dotnet", "/publish/api.dll"]

위의 코드를 수정하여 WORKDIR을 올바른 위치에 배치하고 다음 구문을 제거하여 최적화했습니다. /Publish

FROM microsoft/aspnetcore:2
WORKDIR /publish
COPY --from=build-env /publish .
ENTRYPOINT ["dotnet", "/api.dll"]

1
당신은 그 컨테이너의 루트 경로를 마찬가지로 api.dll의 슬래시 뿅을하지 말았어야
C 디모데

1

대상 디렉터리 이름으로 vars를 사용 WORKDIR하지 않도록 주의하십시오. 이렇게하면 "아무것도 정규화 할 수 없음"치명적인 오류가 발생하는 것처럼 보입니다. IMO, 즉 경로의 모든 요소가 아직 존재하지 않는 경우 생성 WORKDIR되는 것과 동일한 방식으로 작동 한다는 점도 지적 할 가치가 mkdir -p <path>있습니다.

업데이트 : 다단계 빌드를 실행하는 동안 변수 관련 문제 (위에서 언급)가 발생했습니다. 이제 변수를 사용하는 것이 괜찮은 것처럼 보입니다. 예를 들어 다음과 같이 변수가 "범위 내에"있는 경우 두 번째 WORKDIR참조가 실패합니다. ...

FROM <some image>
ENV varname varval
WORKDIR $varname

FROM <some other image>
WORKDIR $varname

반면에, 이것은 성공합니다 ...

FROM <some image>
ENV varname varval
WORKDIR $varname

FROM <some other image>
ENV varname varval
WORKDIR $varname

.oO ( 아마도 그것은 문서에 있고 나는 그것을 놓쳤습니다 )


0

WORKDIR연속 통합 흐름에 영향을 줄 수 있으므로 설정 위치에주의하십시오 . 예를 들어,로 설정하면 설정 시간에 원격 circleci가 수행하는 /home/circleci/project것과 같은 오류가 발생합니다 .ssh.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.