WORKDIR在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” ]

我不能只是省略WORKDIRCopy,只是有我的Dockerfile在我的项目的根?使用这种方法的缺点是什么?

245615 次浏览

你可以把WORKDIR想象成容器中的cd(它会影响Dockerfile中后面的命令,比如RUN命令)。如果你在上面的例子中删除了WORKDIRRUN npm install将不起作用,因为你将不在容器中的/usr/src/app目录中。

我不知道这将如何与你把你的Dockerfile(因为你的Dockerfile在主机上的位置与容器内的pwd无关)。你可以把Dockerfile放在项目中的任何你想要的地方。然而,COPY的第一个参数是一个相对路径,所以如果你移动Dockerfile,你可能需要更新那些COPY命令。

根据文档:

WORKDIR指令为任何RUN, CMD, 的入口点、复制和添加指令 Dockerfile。如果WORKDIR不存在,即使它没有在任何后续Dockerfile指令中使用,它也会被创建

同样,在Docker最佳实践中,它建议你使用它:

< p >…你应该使用WORKDIR,而不是像 运行cd &&做一些很难读懂的事情,排除故障,还有 维护。< / p >

我建议保留它。

我认为你可以把Dockerfile重构成这样:

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

在应用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"]

因此,它的作用类似cd,并为接下来的语句设置基调。

你不必这么做

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

小心使用vars作为WORKDIR的目标目录名-这样做似乎会导致“不能标准化任何东西”的致命错误。在我看来,还值得指出的是,WORKDIR的行为方式与mkdir -p <path>相同,即路径的所有元素都是在它们还不存在的情况下创建的。

< p >更新: 我在运行多阶段构建时遇到了变量相关的问题(上面提到过)-现在看来使用变量是可以的-如果它(变量)是“在范围内”,例如在下面,第二次WORKDIR引用失败…< / p >
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 (也许它在文档里。我已经错过了)

在哪里设置WORKDIR要小心,因为它会影响持续集成流。例如,将其设置为/home/circleci/project将导致类似.ssh或远程circleci在设置时所做的任何错误。

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

在常规命令行中,如果你在某个地方cd,它会一直留在那里,直到你改变它。然而,在Dockerfile中,每个RUN命令都是从根目录开始的!对于docker新手来说,这是一个问题,需要注意。

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