はじめに
Dockerを根本的・体系的に理解するために、このシリーズを書き始めました。
第1回リンク
いきなりDockerそのものを理解するのではなく、イメージしやすいものから学習していくつもりです。
今回は「docker-compose.ymlについて完璧に理解しよう」の回です。前回でも概要は触れて、そのときはこう表現しました。
アプリ全体の「構成」と「連携方法」を定義する設計図。以下のような情報を記載しています。
- どのサービス(コンテナ)を扱うか
- 各サービスの設定
イメージも設計図という表現がされますが、イメージが一つの部屋(コンテナ)の設計図だとしたら、docker-compose.ymlはマンションの設計図です。
docker compose upの際に、このymlファイルを参考に関連サービス(コンテナ)が起動します。
docker-compose.yml
では具体的なymlファイルの書き方を深堀します。私は実物あった方が、理解が進むタイプなので、Claude Code先生に頼りつつ、一般的な書き方をコメント付きコードで記載してみました。あくまで一例ですが、大枠はどれも似たり寄ったりなので、一つ書くだけでymlファイルの役割がイメージしやすくなりました。
感想としては、自分で変数渡してビルドしたり、他の設定ファイルを利用したりもできるので、拡張性って表現するんですかね?柔軟性もある印象です。
一気に見ると情報量に圧倒されますが、コメント付けながら一つ一つかみ砕いていくと案外理解できました
# ファイルのバージョン
version: "3.8"
networks:
myapp-network: # 任意のネットワーク名
driver: bridge # 同じPC内でコンテナ間をつなぐ(その他にもPC間を繋ぐoverlayなど)
# ボリューム:コンテナを消してもデータが残る保存場所
volumes:
mysql-data: # 任意のボリューム名(例:データベースのデータ用)
app-logs: # 任意のボリューム名(例:アプリのログファイル用)
# config:機密情報といった別で保管したいものの利用に向いている
configs:
db-password: # 任意のconfig名
file: ./secrets/db_password.txt # 対象ファイル
services: # ここが本題!
nginx: # 任意のコンテナ名(他のコンテナから「http://nginx:80」のようにこの名前で呼び出せる)
image: nginx:alpine # ← 実際に使う技術
container_name: myapp-nginx # docker psで表示される名前(省略するとそのままサービス名が使われる)
ports: # ポート設定(2パターン)
- "80:80" # パターン1: "ホスト側:コンテナ側"
# パターン2: コンテナ側のポート、ホスト側のポート、プロトコル
- target: 443
published: 443
protocol: tcp
networks: # どのネットワークにつなぐか
- myapp-network
depends_on: #他のコンテナへの依存(2パターン)
- sample-api # パターン1: 対象コンテナ(api)が起動したら起動する
- sample-api # パターン2: 対象コンテナが正常になったら起動する
condition: service_healthy
volumes: # ボリューム設定:ホストとコンテナのフォルダ共有設定
- ./html:/usr/share/nginx/html # 指定したコンテナのファイルとローカルのファイルが同期できる。(ホスト側:コンテナ側で記述)
restart: unless-stopped # 手動で停止以外、コンテナが落ちたら自動で再起動する
sample-api: # コンテナ名
build: #imageが既製品を使うのに対して、buildは自分でDockerfile用意してコンテナを作る
context: ./sample-api # Dockerfileがあるフォルダ
dockerfile: Dockerfile # ファイル名(省略可能、デフォルトはDockerfile)
args: # ビルド時に渡す変数
NODE_VERSION: 18
ports:
- "3000:3000"
networks:
- myapp-network
environment: # 環境変数の書き方(2パターン)
# パターン1: リスト形式
- DATABASE_URL=mysql://user:pass@mysql:3306/mydb # ← @mysql の部分!サービス名で他のコンテナを指定できる
- NODE_ENV=production
# パターン2: ファイルから読み込む
env_file:
- .env # .envファイルに書いた環境変数を全部読む
configs:
- source: db-password # データベースのパスワードファイル
target: /run/secrets/db_password.txt # コンテナ内でこのパスで読める
healthcheck: # ヘルスチェック
test: ["CMD", "curl", "-f", "http://localhost:3000/health"] # このコマンドで確認
interval: 30s # チェック頻度
timeout: 10s # 10秒以内に応答がなければ失敗
retries: 3 # 3回連続で失敗したら異常
start_period: 40s # 起動後40秒は失敗してもOK
volumes:
- ./sample-api:/app
depends_on:
- mysql
# リソース制限(使いすぎを防ぐ)
deploy:
resources:
limits:
cpus: '1.0' # CPU 1コア分まで
memory: 512M # メモリ512MBまで
reservations: # 最低限これだけは確保
cpus: '0.5'
memory: 256M
mysql: # コンテナ名
image: mysql:8 # MySQLの公式イメージ
ports:
- "3306:3306"
networks:
- myapp-network
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: mydb
MYSQL_USER: dbuser
MYSQL_PASSWORD: dbpass
# データを永続化(コンテナ消してもデータ残る)
volumes:
- mysql-data:/var/lib/mysql # MySQLのデータ本体
- ./init.sql:/docker-entrypoint-initdb.d/init.sql # 初回起動時に実行されるSQL
restart: always # 常に再起動