DockerfileのWORKDIRのポイントは何ですか?


105

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

省略WORKDIRしてプロジェクトのルートにCopy置くことはできませんDockerfileか?このアプローチを使用することの欠点は何ですか?


ビルド時にディレクトリを次の方法で変更しますWORKDIR
紫外

1
@紫外線について説明してください。私はポイントを完全に
理解し

回答:


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


1
私が使用しFROM ubuntu as builder、続いてイメージを使用する場合COPY、「ビルダー」イメージでWORKDIRを使用したことを「知っている」のでしょうか、それとも絶対パスを使用しないと仮定する必要がありますか?
アレックス75

よると、ドッキングウィンドウのドキュメント私はそれが保持していることだと思いWORKDIRますが、実行する前にDockerfile内の命令RANであるため、値をCOPY1に
juanlumn

あなたのRUN mkdirコマンドは必要ありません。つまり、その行を削除できます。ドキュメントによると、「WORKDIRが存在しない場合は、後続のDockerfile命令で使用されていなくても作成されます。」- docs.docker.com/engine/reference/builder/#workdir
Purplejacket

正しい@Purplejacket、答えを更新します
juanlumn

59

あなたはする必要はありません

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がUSERを尊重しないため、RUN mkdirが必要になる場合があります-github.com/moby/moby/issues/20295
Joe Bowbeer

22
WORKDIRでフォルダが自動的に作成されるのが気に入っています。
GingerBeer 2018

32

コンテナー内のWORKDIRように考えることができますcd(コマンドのように、Dockerfileの後半にあるコマンドに影響しますRUN)。WORKDIR上記の例で削除した場合、コンテナ内RUN npm install/usr/src/appディレクトリにいないため、機能しません。

これがDockerfileの配置場所にどのように関係するかはわかりません(ホストマシン上のDockerfileの場所はコンテナー内のpwdとは関係がないため)。プロジェクト内のどこにでもDockerfileを配置できます。ただし、の最初の引数COPYは相対パスであるため、Dockerfileを移動する場合は、それらのCOPYコマンドを更新する必要がある場合があります。


3
WORKDIRようcdに追加した場合COPY、元の例の2つは同じソースと宛先を持たないのですか?
Jonas Rosenqvist

5
いいえ。コンテナ内WORKDIRの作業ディレクトリに影響します。元の例では、最初のコピーはホスト(Dockerfileへの相対パス)からコンテナーにコピーさます。実際、宛先は(コンテナー内で)相対パス(パスはで始まる)を使用していないため、はその特定のコマンドに影響を与えません。COPYpackage.json /usr/src/app/package.json WORKDIR/
mkasberg 2018年

@mkasberg ifのWORKDIRように振る舞いcdます。下の2つのスニペットは同等ですか? WORKDIR /usr/src/app COPY package.json /usr/src/app/WORKDIR /usr/src/app COPY package.json . ありがとう
kcatstack

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の前にスラッシュを付けないでください。これにより、コンテナーのルートにパスが移動します
Timothy c

1

のターゲットディレクトリ名としてvarsを使用することに注意してください。これをWORKDIR行うと、「何も正規化できません」という致命的なエラーが発生するようです。IMO、WORKDIR同じように動作することも指摘する価値mkdir -p <path>があります。つまり、パスのすべての要素がまだ存在しない場合は作成されます。

更新:多段階ビルドの実行中に変数関連の問題(上記)に遭遇しました-変数の使用は問題ないように見えます-(変数)が「スコープ内」にあるWORKDIR場合、たとえば、2番目の参照は失敗します...

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.