在Dockerfile中使用WORKDIR命令有什么意义

Le *_*con 66 docker dockerfile

我正在学习Docker.很多次,我看到它DockerfileWORKDIR命令

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” ] 
Run Code Online (Sandbox Code Playgroud)

我不能省略WORKDIR,Copy只是让我Dockerfile的项目根源?使用这种方法的缺点是什么?

jua*_*umn 76

根据文件:

WORKDIR指令为Dockerfile中的任何RUN,CMD,ENTRYPOINT,COPY和ADD指令设置工作目录.

此外,在Docker最佳实践中,它建议您使用它:

...你应该使用WORKDIR而不是像RUN cd那样增加指令... && do-something,这些都很难阅读,排除故障和维护.

我建议保留它.

我认为你可以将你的Dockerfile重构为:

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

  • @MarioGil请查看[COPY文档。](https://docs.docker.com/engine/reference/builder/#copy) (2认同)
  • 当我使用``FROM ubuntu as builder``然后连续的映像使用``COPY``时,它是否“知道”我在“builder”映像中使用了WORKDIR,或者我必须假设没有(并使用绝对路径) ? (2认同)

Sam*_*are 36

你不必

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” ] 
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢你指定WORKDIR将自动创建文件夹的事实. (10认同)
  • 但是,有时需要 RUN mkdir 因为 WORKDIR 在创建目录时不尊重 USER - https://github.com/moby/moby/issues/20295 (5认同)

mka*_*erg 26

你可以认为WORKDIR像一个cd容器内(它会影响晚一点在Dockerfile,像命令RUN命令).如果您WORKDIR在上面的示例中删除了,则RUN npm install无法工作,因为您不在/usr/src/app容器内的目录中.

我没有看到这与你放置Dockerfile的位置有什么关系(因为主机上的Dockerfile位置与容器内的pwd无关).您可以将Dockerfile放在项目中的任何位置.但是,第一个参数COPY是相对路径,因此如果移动Dockerfile,则可能需要更新这些COPY命令.

  • @mkasberg 如果“WORKDIR”就像“cd”一样。那么下面的 2 个片段是否等效?`WORKDIR /usr/src/app` `COPY package.json /usr/src/app/` 和 `WORKDIR /usr/src/app` `COPY package.json 。` 谢谢 (6认同)
  • 是的,这些是等效的。 (5认同)
  • 没有.`WORKDIR`影响工作目录_inside the container_.在最初的例子中,第一个`COPY`从host_(封装器文件的相对路径)上的`package.json`复制到容器_中的`/ usr/src/app/package.json` _.实际上,`WORKDIR`对该特定命令没有影响,因为目标(容器内)没有使用相对路径(路径以`/`开头). (3认同)
  • 我感觉就像 Derek Zoolander 说的:“*在*[Docker 容器] 中!” 哦,我现在明白了。与开发环境无关...仅与 Docker 容器内的运行时相关。知道了。但是......它可以只是根(即“/”)吗? (3认同)
  • 如果`WORKDIR`像`cd`这样添加,则原始示例中的两个`COPY'不会具有相同的源和目标吗? (2认同)
  • 是的,您可以执行“WORKDIR /”,您的工作目录将成为根目录。但是,在根目录中添加非标准文件夹是非常不寻常的,并且将其设为工作目录也有点不寻常。因此,通常情况下,您需要像上面的示例一样使用“/app”、“/root/app”、“/opt/app”或“/usr/src/app”之类的内容,并将应用程序文件复制到容器中的该位置,然后从那里(在容器中)构建并运行您的应用程序。因此“WORKDIR /”是允许的,但不常见。 (2认同)

use*_*745 7

@juanlumn 的答案很好,但我想补充一件(重要的)事情。

在常规命令行中,如果您cd在某个地方,它会保留在那里,直到您更改它。然而,在 Dockerfile 中,每个RUN命令都从根目录开始!这是 Docker 新手的一个陷阱,也是需要注意的事情。

因此,它不仅可以WORKDIR为阅读代码的人提供更明显的视觉提示,而且还可以保留不止一个 RUN 命令的工作目录。


Blu*_*uds 5

在应用 WORKDIR 之前。此处 WORKDIR 位于错误的位置并且未明智地使用。

FROM microsoft/aspnetcore:2
COPY --from=build-env /publish /publish
WORKDIR /publish
ENTRYPOINT ["dotnet", "/publish/api.dll"]
Run Code Online (Sandbox Code Playgroud)

我们更正了上面的代码以将 WORKDIR 放在正确的位置并通过删除优化以下语句 /Publish

FROM microsoft/aspnetcore:2
WORKDIR /publish
COPY --from=build-env /publish .
ENTRYPOINT ["dotnet", "api.dll"]
Run Code Online (Sandbox Code Playgroud)

所以它就像 acd并为即将到来的陈述定下了基调。

  • api.dll 前面不应该有斜杠,因为这会将其路径到容器的根目录 (2认同)