ハトネコエ Web がくしゅうちょう

プログラミングやサーバー関連、チームマネジメントなど得た技術のまとめ

Docker の ARG の宣言箇所に注意

元はこういう Dockerfile を書いていました。

ARG RUBY_VER="latest"
ARG ENV_FILE_DIR="."

FROM ruby:${RUBY_VER}

WORKDIR /home/repository/src

ADD src /home/repository/src
ADD ${ENV_FILE_DIR}/.env .
RUN bundle install

CMD bundle exec foreman start

こうすれば、docker build 時に

docker build ./ \
  --build-arg RUBY_VER=2.6.1 \
  --build-arg ENV_FILE_DIR=/data/sample_app
  -t sample_app:latest

と指定して、任意のディレクトリの .env ファイルを置けるかと思ってました。

しかしそんなことはなく、2 つの誤りがありました。

1. ARG は FROM の後に宣言する

ARG を FROM の前に書いていいのは、FROM のタグ指定などの時のみで、
基本的に ARG は FROM のあとで宣言 します。

そうしないと、この ARG 宣言は無効化され、
${ENV_FILE_DIR} の値は空文字となります

つまり、以下の順序で書くのが正解でした。

ARG RUBY_VER="latest"
FROM ruby:${RUBY_VER}

ARG ENV_FILE_DIR="."

WORKDIR /home/repository/src

ADD src /home/repository/src
ADD ${ENV_FILE_DIR}/.env .
RUN bundle install

CMD bundle exec foreman start

Dockerfile において ADD のソース指定が ./.env/.env のとき実質同じファイルを指すために、
エラーが出ることもなかったので、このバグを作ってしまっていることになかなか気付けず苦労しました。

あまりにわからなくて RUN echo ${ENV_FILE_DIR} を挟んでみたら出力がなかったので気付けました……。

2. ADD や COPY で使えるソースは特定ディレクトリ以下

この stack overflow での回答で触れられているように、
docker build 実行時のPATH以下のディレクトリにあるファイルしか参照できません。

docker build の help に

Usage: docker build [OPTIONS] PATH | URL | -

とありますが、 このPATHディレクトリが、ADDやCOPYでのルートディレクト として扱われます。

先ほどの 1. で

ADD のソース指定が ./.env/.env のとき実質同じファイルを指す

と書いたのはそういうことです。

たいていの場合、Dockerfile のあるディレクトリで docker build をおこなうでしょうから、
大雑把な表現をするなら、Dockerfile のあるディレクトリ以下のファイルのみがソース対象になりえるとも言えます。

なお、この話は公式ドキュメント上でも

The <src> path must be inside the context of the build; you cannot ADD ../something /something, because the first step of a docker build is to send the context directory (and subdirectories) to the docker daemon.

と触れられていますので、build’s context の話と合わせて読むと良いかと思います。

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤