Я изучаю Докер. Я много раз видел, что 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” ] 

Разве я не могу просто опустить WORKDIR и Copy и оставить мой Dockerfile в корне моего проекта? Каковы недостатки использования этого подхода?

Le garcon

Ответов: 6

Ответы (6)

According to the documentation:

Инструкция WORKDIR устанавливает рабочий каталог для любого RUN, CMD, Ввести, КОПИРОВАТЬ и ДОБАВИТЬ инструкции, которые следуют за ними в Dockerfile. Если WORKDIR не существует, он будет создан, даже если он не будет использоваться в последующих инструкциях Dockerfile.

Кроме того, в лучших практиках Docker рекомендуется использовать его:

... вы должны использовать WORKDIR вместо распространения инструкций вроде RUN cd… && do-something, которые трудно читать, устранять неполадки и поддерживать.

Я бы посоветовал оставить его себе.

Я думаю, вы можете реорганизовать свой Dockerfile примерно так:

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

Необязательно

ЗАПУСТИТЬ 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” ] 

Beware of using vars as the target directory name for WORKDIR - doing that appears to result in a "cannot normalize nothing" fatal error. IMO, it's also worth pointing out that WORKDIR behaves in the same way as mkdir -p i.e. all elements of the path are created if they don't exist already.

ОБНОВЛЕНИЕ: Я столкнулся с проблемой, связанной с переменной (упомянутой выше), во время выполнения многоступенчатой ​​сборки - теперь кажется, что использование переменной - это нормально - если она (переменная) находится "в области видимости", например. далее вторая ссылка WORKDIR не работает ...

FROM 
ENV varname varval
WORKDIR $varname

FROM 
WORKDIR $varname

тогда как это удается ...

FROM 
ENV varname varval
WORKDIR $varname

FROM 
ENV varname varval
WORKDIR $varname

.oO (Возможно, это в документации, и я его пропустил)

Be careful where you set WORKDIR because it can affect the continuous integration flow. For example, setting it to /home/circleci/project will cause error something like .ssh or whatever is the remote circleci is doing at setup time.

You can think of WORKDIR like a cd inside the container (it affects commands that come later in the Dockerfile, like the RUN command). If you removed WORKDIR in your example above, RUN npm install wouldn't work because you would not be in the /usr/src/app directory inside your container.

Я не понимаю, как это связано с тем, куда вы помещаете свой Dockerfile (поскольку местоположение вашего Dockerfile на хост-машине не имеет ничего общего с pwd внутри контейнера). Вы можете разместить Dockerfile в любом месте вашего проекта. Однако первый аргумент для COPY является относительным путем, поэтому, если вы переместите файл Docker, вам может потребоваться обновить эти команды COPY.

Before applying WORKDIR. Here the WORKDIR is at the wrong place and is not used wisely.

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"]

Таким образом, он действует как cd и задает тон для следующих заявлений.

2022 WebDevInsider