TL;DR
tar -ch . | docker build -
前提
以下のディレクトリ構造とします。
.
├── common
│ └── print_with_time.py
└── hello-world
├── Dockerfile
└── src
├── __init__.py
├── app.py
└── common -> ../../common
FROM python:3-alpine
RUN mkdir -p /app
COPY src /app/src
COPY src/common /app/src # ← src/commonはシンボリックリンク
WORKDIR /app
CMD ["python", "-m", "src.app"]
通常通りの docker build
コマンド
解決方法
コマンドを少し工夫して、シンボリックリンクをfollowして 1 作成されたtarボールをdockerコマンドに渡します。
最後の -
を忘れるとエラーになります。(stdinからのビルドと認識させるためです)
tar -ch . | docker build -t docker-build-symlink -
(ここを参考にしましたが、なぜかgzip圧縮のオプションはエラーになるので外しました)
無事ビルドでき、 Hello world!
が出力されました!
もし一部のディレクトリ/ファイルを除外してDockerに送りたい場合
画像の例ではありませんが、実際に私がこれを使っているプロジェクトはNode.jsのプロジェクトで、 node_modules
という615MBにもおよぶ巨大ディレクトリを含んでいます。
実際は Dockerfile
の中で yarn install
をしているので node_modules
自体は不要(しかもホストはmac、コンテナはAlpine Linuxなので、node-sassなどのバイナリを使う場合互換性はない)、これを docker build
に送らないようにするには --exclude
オプションを使います。
tar -ch --exclude=node_modules . | docker build -t docker-build-symlink -
このように --exclude=pattern
オプション2をつけるとtarボールにならないので、少し早くなります。
( --exclude-from=file
もアリですね)
コンテナの中身は?
中を覗いても、 /app/src/common
はシンボリックリンクではなく普通のディレクトリとなっています。