開発を通じた学んだdockerに関する知識を
言語化を通じた知識の深堀り&備忘を兼ねて書いていきます
そんなの豆知識じゃなくて基礎基本だろ!
というような内容も含まれるかもしれませんが、
暖かく見守ってもらえると幸いです。
DockerfileのCOPYとdocker-compose.ymlのvolumeの違い
COPYは、ビルド時にファイルをイメージに組み込む命令。
コンテナ作成時ではなく、イメージのビルド時に実行される
volumesは、ホストとコンテナ間でディレクトリをマウントする仕組み
COPY . ./は、ビルド時点のすべてのファイルを静的にイメージ内にコピーする。
そのため、コンテナ起動中にホスト側でファイルを変更しても、コンテナ内には反映されない。
一方、volumes: - .:/appは、ホストの.(カレントディレクトリ)とコンテナの/appをリアルタイムで同期し、ホスト側の変更が即座にコンテナ内に反映される
→これによりホットリロードが可能になる
複数のコンテナで処理を共通化させたい
マルチステージビルドを使う
以下のDockerfileでは、uvによるPython環境構築の一連のプロセスをbuilderステージとして定義している
これにより、builderステージで依存関係をインストールした状態を基盤として、
各サービス固有のファイルだけを追加するということを実現している
FROM python:3.13-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen
FROM builder AS schema-fetcher
COPY scripts/ ./scripts
CMD ["uv", "run", "scripts/fetch_table.py"]
FROM builder AS initializer
COPY scripts/ ./scripts/
CMD ["uv", "run", "scripts/create_table.py"]
FROM builder AS test-runner-ci
COPY src/ ./src/
COPY tests/ ./tests/
CMD ["uv", "run", "-m", "pytest", "tests/", "-v", "-s"]
docker-compose側
services:
schema-fetcher:
container_name: "schema-fetcher"
build:
dockerfile: Dockerfile
target: schema-fetcher
コンテナ間でファイルを共有する
基本的にはvolumesを使って、共有のためのハブを作る
- ローカルのディレクトリをハブとする
- 名前付きボリュームをハブとする
1の場合、データがローカルに残り続けるので、デバッグがしやすいがクリーンアップがしづらい
2の場合はその逆。不要になったらdocker compse down -vで簡単にクリーンアップできるが、デバッグがしづらい
# バインドマウントの例
volumes:
- ./shared:/shared
# 名前付きボリュームの例
volumes:
- shared:/shared
.が先頭につくか否かで変わる
Docker build vs docker-compose up --build
-
docker build: 箱を作る -
docker run: 箱を実行する。この際にopitionで環境変数などを指定できる
※ECSにおいても同じフローが行わている
- ECRから箱を引っ張ってくる
- タスク定義の環境変数を注入する
- 起動
docker composer up --buildは
docker build + docker runの2つの処理を一度にやる
つまり、下記は全く同じ処理をしている
docker build -t my-image .
docker run \
-d \
--name my-app \
-p 8000:8000 \
-e AWS_REGION=ap-northeast-1 \
--env-file .env \
-v $(pwd)/data:/data \
--network my-network \
my-image
以下のdocker-compose.ymlでdocker compose up --build
services:
my-app:
build: .
container_name: my-app
ports:
- "8000:8000"
environment:
- AWS_REGION=ap-northeast-1
env_file:
- .env
volumes:
- ./data:/data
networks:
- my-network
- Dockerイメージには環境変数は含まれない(箱だけ)
- 環境変数は実行時に注入される
- ローカル: docker-compose.yml or docker run
- 本番: ECSタスク定義 or Secrets Manager
備考: 何もわからなかったときの私の質問
docker-compose.ymlで定義されてる環境変数とECSのタスクの環境変数。どちらが優先されるんですか!?
→ docker-compose.ymlはデプロイ時には全く関係しない。ローカルのコンテナを環境変数とか詰め込んでオーケストレーションするだけ。なのでデプロイされたコンテナはECSの環境変数しか参照しない