元はこういう 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 cannotADD ../something /something, because the first step of adocker buildis to send the context directory (and subdirectories) to the docker daemon.
と触れられていますので、build’s context の話と合わせて読むと良いかと思います。
