基本的に、Dockerfileは親ディレクトリにあるファイルを参照することができません。
サンプルとして、以下のようなディレクトリ構造でDockerfileからビルドしてみます。
$ /tmp/copy_test$ tree ./
./
├── dir_in_Dockerfile
│ ├── Dockerfile
│ ├── child_dir
│ │ └── testfile_in_childdir.txt
│ └── testfile.txt
└── testfile_in_parent.txt
2 directories, 4 files
テスト用のDockerfileはこのように作成しました。
FROM alpine:latest
COPY ./testfile.txt /tmp
# 親ディレクトリのファイル
COPY ../testfile_in_parent.txt /tmp
# 子ディレクトリのファイル
COPY ./child_dir/testfile_in_child.txt /tmp
# 絶対パスでの記述
COPY /tmp/testfile_in_tmp.txt /tmp
CMD ["/bin/sh"]
dir_in_Dockerfile でビルドをしてみます。
/tmp/copy_test/dir_in_Dockerfile$ docker build .
[+] Building 0.1s (9/9) FINISHED
=> [internal] load build definition from Dockerfile
=> => transferring dockerfile: 38B
=> [internal] load .dockerignore
=> => transferring context: 2B
=> [internal] load metadata for docker.io/library/alpine:latest
=> CACHED [1/5] FROM docker.io/library/alpine:latest
=> [internal] load build context
=> => transferring context: 112B
=> CACHED [2/5] COPY ./testfile.txt /tmp
=> ERROR [3/5] COPY ../testfile_in_parent.txt /tmp
=> CACHED [4/5] COPY ./child_dir/testfile_in_child.txt /tmp
=> ERROR [5/5] COPY /tmp/testfile_in_tmp.txt /tmp
親ディレクトリのファイルを指定した部分([3/5] COPY ../testfile_in_parent.txt /tmp)と、絶対パスでファイルを指定した部分(ERROR [5/5] COPY /tmp/testfile_in_tmp.txt /tmp)でエラーが起きています。
どうしてもDockerfileの親階層のファイルを参照したいとき
Dockerfileの上位ディレクトリにあるファイルをCOPYしたい場合、ビルドコンテクストを指定する必要があります。
以下のように、Dockerfileを書き換えます。
# docker buildコマンドで、Dockerfileの親ディレクトリをコンテキストに指定してビルド実行する
FROM alpine:latest
# Dockerfileと同階層のファイル
COPY ./dir_in_Dockerfile/testfile.txt /tmp
# Dockerfileからみて親ディレクトリにあるファイルを、カレントディレクトリとして参照
COPY ./testfile_in_parent.txt /tmp
# 子ディレクトリのファイル
COPY ./dir_in_Dockerfile/child_dir/testfile_in_child.txt /tmp
# 絶対パスでの記述
COPY /tmp/testfile_in_tmp.txt /tmp
CMD ["/bin/sh"]
そして、 docker build する際に-f オプションでDockerfileの位置と、コンテキスト(基準になるディレクトリ)を指定します。
/tmp/copy_test/dir_in_Dockerfile$ docker build -f ./Dockerfile ../
[+] Building 0.2s (9/9) FINISHED
=> [internal] load build definition from Dockerfile
=> => transferring dockerfile: 38B
=> [internal] load .dockerignore
=> => transferring context: 2B
=> [internal] load metadata for docker.io/library/alpine:latest
=> [internal] load build context
=> => transferring context: 242B
=> CACHED [1/5] FROM docker.io/library/alpine:latest
=> CACHED [2/5] COPY ./dir_in_Dockerfile/testfile.txt /tmp
=> CACHED [3/5] COPY ./testfile_in_parent.txt /tmp
=> CACHED [4/5] COPY ./dir_in_Dockerfile/child_dir/testfile_in_child.txt /tmp
=> ERROR [5/5] COPY /tmp/testfile_in_tmp.txt /tmp
------
> [5/5] COPY /tmp/testfile_in_tmp.txt /tmp:
------
failed to compute cache key: "/tmp/testfile_in_tmp.txt" not found: not found
今度は、絶対パスで指定した部分(ERROR [5/5] COPY /tmp/testfile_in_tmp.txt /tmp)だけがエラーになりました。
コンテキストはデフォルトではDockerfileのある階層になるため、そのままだと親階層のファイルが使えません。
明示的に親ディレクトリを指定することで、Dockerfileの親階層のファイルも参照できます。
一応この方法で実現できますが、Dockerfikeに記載されたパスと実際に参照されるファイルの所在が変わってしまううえ、Dockerfile上のすべてのパスを書き換える必要があります。
加えて、ビルドの際に適切にオプションと引数を指定しないと意図した内容がビルドされません。
しかも、、、コンテキストに指定されたディレクトリ以下にあるファイルは、すべてDockerデーモンに送信されてしまい、ビルドに時間がかかる原因にもなったりするみたいです。
あくまで「一応できる」というものであり、副作用が多いですね。あまり多用しない方がよさそうです。
以上です。あなたのお役に立てればうれしいです。