📋 このステップで学ぶこと
services、networks、volumesの詳細
イメージ指定とビルド指定の使い分け
ポートマッピングの設定方法
環境変数の設定(.envファイル含む)
depends_on(依存関係)の活用
実践演習で2つのコンテナを連携
🔧 0. このステップの前提知識
📚 STEP 15の復習
このステップでは、以下の知識を使います。忘れた場合は復習してから進めましょう。
Docker Compose :複数コンテナを管理するツール
docker-compose up -d :全サービスをバックグラウンドで起動
docker-compose down :全サービスを停止・削除
サービス名での通信 :コンテナ間はサービス名でアクセス
0-1. 作業ディレクトリの準備
# 作業ディレクトリを作成して移動
mkdir -p ~/docker-practice/step16
cd ~/docker-practice/step16
# 現在の場所を確認
pwd
0-2. docker-compose.ymlの全体構造
このステップでは、docker-compose.ymlの各設定項目を詳しく学びます。
まず全体像を把握しましょう。
【docker-compose.ymlの全体構造】
docker-compose.yml
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
version: ‘3.8’ ← ① バージョン(3.8を使えばOK)
services: ← ② サービス定義(最重要!)
webapp: 各コンテナの設定を記述
image: …
build: …
ports: …
environment: …
volumes: …
depends_on: …
networks: ← ③ ネットワーク定義(省略可)
mynetwork: コンテナ間の通信設定
volumes: ← ④ ボリューム定義(省略可)
mydata: データ永続化の設定
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
💡 このステップでは②servicesの各設定項目を詳しく学びます
0-3. このステップで学ぶ設定項目
STEP 16で学ぶ主要設定項目
設定項目
役割
例
image
既存イメージを使用
image: postgres:13
build
Dockerfileからビルド
build: ./app
ports
ポートマッピング
ports: - "5000:5000"
environment
環境変数を設定
environment: DEBUG: true
env_file
外部ファイルから環境変数
env_file: - .env
volumes
ボリュームマウント
volumes: - data:/app/data
depends_on
起動順序の制御
depends_on: - postgres
🏗️ 1. services、networks、volumesの詳細
1-1. services(サービス)
各コンテナの設定 を定義します。最も重要なセクションです。
【servicesセクションの構造】
services:
サービス名: ← 自由に名前を付ける
┌─────────────────────────────────────────────┐
│ image: nginx:latest # イメージ指定 │
│ build: ./my-app # またはビルド │
│ container_name: my_nginx # コンテナ名固定 │
│ ports: # ポートマッピング │
│ – “8080:80” │
│ environment: # 環境変数 │
│ – KEY=value │
│ volumes: # ボリューム │
│ – ./data:/app/data │
│ networks: # ネットワーク │
│ – mynetwork │
│ depends_on: # 依存関係 │
│ – database │
│ restart: unless-stopped # 再起動ポリシー │
└─────────────────────────────────────────────┘
1-2. networks(ネットワーク)
コンテナ間の通信 を設定します。省略すると自動で作成されます。
# ネットワーク定義の例
networks:
# カスタムネットワーク
mynetwork:
driver: bridge # ドライバー(bridgeが標準)
# 外部ネットワークを使う場合
existing_network:
external: true
💡 ネットワークの自動作成
networks:セクションを省略すると、Docker Composeが自動でプロジェクト名_defaultという名前のネットワークを作成します。基本的には自動作成で問題ありません 。
1-3. volumes(ボリューム)
名前付きボリューム を定義します。データの永続化に使用します。
# ボリューム定義の例
volumes:
# 基本的な定義(空でOK)
postgres_data:
# ドライバーを指定する場合
mydata:
driver: local
🎯 バインドマウント vs 名前付きボリューム
services:
myapp:
volumes:
# バインドマウント(ホストのパスを直接指定)
– ./my-code:/app # 開発時に便利
# 名前付きボリューム(Dockerが管理)
– mydata:/app/data # データ永続化に推奨
volumes:
mydata: # 名前付きボリュームは宣言が必要
【バインドマウント vs 名前付きボリューム】
┌─────────────────────────────────────────────────────────────┐
│ バインドマウント │
│ ./my-code:/app │
├─────────────────────────────────────────────────────────────┤
│ ホスト コンテナ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ ./my-code/ │ ───────── │ /app/ │ │
│ │ ├── app.py │ 直接 │ ├── app.py │ │
│ │ └── … │ 同期 │ └── … │ │
│ └─────────────┘ └─────────────┘ │
│ │
│ 💡 開発時:ホストでコードを編集 → コンテナに即反映 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 名前付きボリューム │
│ mydata:/app/data │
├─────────────────────────────────────────────────────────────┤
│ Docker管理領域 コンテナ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ mydata │ ───────── │ /app/data │ │
│ │ (自動管理) │ Docker │ │ │
│ │ │ が管理 │ │ │
│ └─────────────┘ └─────────────┘ │
│ │
│ 💡 本番時:データベースなど永続化が必要なデータに使用 │
└─────────────────────────────────────────────────────────────┘
🖼️ 2. イメージ指定とビルド指定
2-1. image:既存イメージを使う
Docker Hubや他のレジストリからイメージを取得 して使用します。
services:
# Docker Hubの公式イメージ
postgres:
image: postgres:13
# バージョンタグ指定
redis:
image: redis:6.2-alpine
# プライベートレジストリ
myapp:
image: myregistry.com/myapp:latest
2-2. build:Dockerfileからビルド
カスタムイメージ をビルドして使用します。
services:
# 1. シンプルな指定(Dockerfileがあるディレクトリ)
webapp:
build: ./app
# 2. 詳細な指定
api:
build:
context: ./api # ビルドコンテキスト
dockerfile: Dockerfile.prod # Dockerfileの名前
args: # ビルド引数
– VERSION=1.0.0
– DEBUG=false
# 3. imageも一緒に指定(ビルド後のタグ名)
backend:
build: ./backend
image: mybackend:latest # ビルドしたイメージに名前を付ける
2-3. imageとbuildの使い分け
imageとbuildの使い分け
使用ケース
使う設定
例
公式イメージを使う
image:のみ
PostgreSQL、Redis、Nginx
カスタムアプリ
build:のみ
自作のFlaskアプリ
ビルド+タグ付け
両方
レジストリにプッシュする場合
2-4. プロジェクト構成例
【プロジェクト構成例】
myproject/
├── docker-compose.yml
├── frontend/ ← build: ./frontend
│ ├── Dockerfile
│ ├── package.json
│ └── src/
├── backend/ ← build: ./backend
│ ├── Dockerfile
│ ├── requirements.txt
│ └── app.py
└── nginx/ ← build: ./nginx
├── Dockerfile
└── nginx.conf
postgres、redis ← image: postgres:13, image: redis:alpine
(公式イメージを使用)
# docker-compose.yml
version: ‘3.8’
services:
# フロントエンド(ビルド)
frontend:
build: ./frontend
image: myapp-frontend:latest
# バックエンド(ビルド)
backend:
build: ./backend
image: myapp-backend:latest
# データベース(既存イメージ)
postgres:
image: postgres:13
# Nginx(ビルド)
nginx:
build: ./nginx
image: myapp-nginx:latest
ports:
– “80:80”
🔌 3. ポートマッピングの設定
3-1. 基本的なポートマッピング
ホストとコンテナのポート を対応付けます。
services:
webapp:
image: nginx
ports:
# 形式: “ホストポート:コンテナポート”
– “8080:80” # ホストの8080 → コンテナの80
– “8443:443” # ホストの8443 → コンテナの443
# コンテナポートだけ指定(ホストはランダム)
– “3000”
# IPアドレスも指定
– “127.0.0.1:8080:80” # localhostだけアクセス可
【ポートマッピングの動作】
ブラウザ ホスト コンテナ
┌─────────┐ ┌─────────┐ ┌─────────┐
│ │ localhost │ │ Docker │ │
│ アクセス │ ──────────▶ │ :8080 │ ─────────▶ │ :80 │
│ │ :8080 │ │ 内部通信 │ nginx │
└─────────┘ └─────────┘ └─────────┘
ports:
– “8080:80”
↑ ↑
│ └─ コンテナ内のポート
└─────── ホストのポート(外部からアクセス)
⚠️ ポート番号は必ず引用符で囲む
ports:
– “8080:80” # ✅ 正しい(引用符あり)
– 8080:80 # ⚠️ YAMLが時刻と解釈する可能性
特に60:60などは時刻として解釈される場合があるため、常に引用符を使いましょう 。
3-2. portsとexposeの違い
services:
# ports:外部(ホスト)に公開
frontend:
image: nginx
ports:
– “80:80” # ホストの80番でアクセス可能
# expose:内部のみ公開(他のコンテナから)
backend:
image: myapi
expose:
– “5000” # 他のコンテナから5000番でアクセス可能
# ホストからはアクセス不可
portsとexposeの違い
設定
アクセス範囲
使用例
ports
ホスト+他のコンテナ
Webサーバー、管理画面
expose
他のコンテナのみ
内部API、データベース
3-3. ポート番号の重複に注意
⚠️ よくあるエラー:ポートの重複
services:
service1:
ports:
– “5000:5000”
service2:
ports:
– “5000:5000” # ❌ エラー:ホストの5000は既に使用中
解決策: ホスト側のポートを変える
services:
service1:
ports:
– “5000:5000” # ✅ OK
service2:
ports:
– “5001:5000” # ✅ OK(ホスト側を5001に変更)
🔧 4. 環境変数の設定
4-1. 方法1:environmentで直接指定
services:
webapp:
image: myapp:latest
environment:
# 方法A:リスト形式
– DATABASE_URL=postgresql://user:pass@postgres:5432/db
– DEBUG=true
– PORT=5000
# 方法B:辞書形式
DATABASE_URL: postgresql://user:pass@postgres:5432/db
DEBUG: “true”
PORT: “5000”
4-2. 方法2:env_fileで外部ファイルから読み込み
# .envファイルを作成
cat > .env << ‘EOF’
DATABASE_URL=postgresql://user:pass@postgres:5432/db
DEBUG=true
PORT=5000
SECRET_KEY=my-secret-key
EOF
# docker-compose.yml
services:
webapp:
image: myapp:latest
env_file:
– .env # .envファイルから読み込む
# 複数ファイルも可能
backend:
image: backend:latest
env_file:
– .env.common
– .env.production
💡 .envファイルの利点
機密情報の分離: .envを.gitignoreに追加してGitに含めない
環境ごとの切り替え: .env.dev、.env.prod で分ける
管理が楽: 環境変数を1ファイルに集約
4-3. 方法3:ホストの環境変数を使う
# docker-compose.yml
services:
webapp:
image: myapp:latest
environment:
# ${変数名}でホストの環境変数を参照
DATABASE_URL: ${DATABASE_URL}
SECRET_KEY: ${SECRET_KEY}
# デフォルト値も指定可能
DEBUG: ${DEBUG:-false} # DEBUGがなければfalse
# 使用例:ホスト側で環境変数を設定してから起動
export DATABASE_URL=postgresql://localhost/mydb
export SECRET_KEY=supersecret
docker-compose up -d
4-4. 環境変数の優先順位
📊 優先順位(高い → 低い)
docker-composeコマンドの-eオプション
docker-compose.ymlのenvironment:
env_file:で指定したファイル
ホストの環境変数
DockerfileのENV
4-5. 実践例:PostgreSQL接続設定
# .envファイルを作成
cat > .env << ‘EOF’
POSTGRES_USER=myuser
POSTGRES_PASSWORD=mypassword
POSTGRES_DB=mydb
DATABASE_URL=postgresql://myuser:mypassword@postgres:5432/mydb
EOF
# docker-compose.yml
version: ‘3.8’
services:
postgres:
image: postgres:13
env_file:
– .env
volumes:
– postgres_data:/var/lib/postgresql/data
webapp:
build: ./app
env_file:
– .env
depends_on:
– postgres
volumes:
postgres_data:
⚡ 5. depends_on(依存関係)
5-1. 基本的な使い方
起動順序 を制御します。
services:
# データベース(最初に起動)
postgres:
image: postgres:13
# Webアプリ(postgresの後に起動)
webapp:
image: myapp:latest
depends_on:
– postgres # postgresを起動してから、webappを起動
# Nginx(webappの後に起動)
nginx:
image: nginx
depends_on:
– webapp # webappを起動してから、nginxを起動
【depends_onによる起動順序】
┌─────────────────────────────────────────────────────────────┐
│ 起動順序 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 時間 ─────────────────────────────────────────────────▶ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ postgres │───▶│ webapp │───▶│ nginx │ │
│ │ (起動) │ │ (起動) │ │ (起動) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ depends_on: depends_on: │
│ なし – postgres – webapp │
└─────────────────────────────────────────────────────────────┘
⚠️ depends_onの重要な注意点
depends_onは起動順序 を制御しますが、サービスが準備完了するまで待たない ことに注意!
【よくある問題】
時間 ─────────────────────────────────────────────────────▶
postgres コンテナ起動
│
├── PostgreSQLが初期化中…(数秒かかる)
│
│ webapp コンテナ起動(depends_onによりpostgres起動後)
│ │
│ └── PostgreSQLに接続試行 → ❌ 接続失敗!
│ (PostgreSQLがまだ準備完了していない)
│
└── PostgreSQL準備完了
5-2. 解決策:アプリ側でリトライ実装
# app.py(Python例)
import time
import psycopg2
import os
def connect_to_db():
“””データベース接続(リトライ付き)”””
max_retries = 5
retry_interval = 2 # 秒
for i in range(max_retries):
try:
conn = psycopg2.connect(os.environ[‘DATABASE_URL’])
print(“データベース接続成功!”)
return conn
except Exception as e:
print(f”接続失敗({i+1}/{max_retries}): {e}”)
if i < max_retries - 1:
time.sleep(retry_interval)
else:
raise
# アプリ起動時に接続
conn = connect_to_db()
5-3. 複数の依存関係
services:
postgres:
image: postgres:13
redis:
image: redis:alpine
rabbitmq:
image: rabbitmq:management
# 複数のサービスに依存
webapp:
image: myapp:latest
depends_on:
– postgres
– redis
– rabbitmq
🛠️ 6. 実践演習:Flask + PostgreSQLの連携
6-1. 演習の目標
FlaskアプリとPostgreSQLを連携させた環境を構築します。
📁 完成時のプロジェクト構成
flask-postgres/
├── docker-compose.yml
├── .env
├── app/
│ ├── Dockerfile
│ ├── requirements.txt
│ └── app.py
└── init.sql
6-2. プロジェクトディレクトリを作成
# プロジェクトディレクトリを作成
mkdir -p ~/docker-practice/flask-postgres/app
cd ~/docker-practice/flask-postgres
# 現在の場所を確認
pwd
6-3. .envファイルを作成
# .envファイルを作成
cat > .env << ‘EOF’
POSTGRES_USER=flaskuser
POSTGRES_PASSWORD=flaskpass
POSTGRES_DB=flaskdb
DATABASE_URL=postgresql://flaskuser:flaskpass@postgres:5432/flaskdb
EOF
# 内容を確認
cat .env
6-4. app/requirements.txtを作成
# requirements.txtを作成
cat > app/requirements.txt << ‘EOF’
Flask==2.0.1
psycopg2-binary==2.9.1
EOF
# 内容を確認
cat app/requirements.txt
6-5. app/Dockerfileを作成
# Dockerfileを作成
cat > app/Dockerfile << ‘EOF’
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install –no-cache-dir -r requirements.txt
COPY app.py .
CMD [“python”, “app.py”]
EOF
# 内容を確認
cat app/Dockerfile
6-6. app/app.pyを作成
# app.pyを作成
cat > app/app.py << ‘EOF’
from flask import Flask
import psycopg2
import os
import time
app = Flask(__name__)
def get_db_connection():
“””データベース接続(リトライ付き)”””
max_retries = 5
for i in range(max_retries):
try:
conn = psycopg2.connect(os.environ[‘DATABASE_URL’])
return conn
except Exception as e:
print(f”DB接続試行 {i+1}/{max_retries}: {e}”)
if i < max_retries - 1:
time.sleep(2)
else:
raise
@app.route('/')
def index():
return "Hello from Flask + PostgreSQL!"
@app.route('/db-test')
def db_test():
try:
conn = get_db_connection()
cur = conn.cursor()
cur.execute('SELECT version();')
version = cur.fetchone()[0]
cur.close()
conn.close()
return f"PostgreSQL Version: {version}"
except Exception as e:
return f"Error: {e}", 500
@app.route('/users')
def users():
try:
conn = get_db_connection()
cur = conn.cursor()
cur.execute('SELECT * FROM users;')
rows = cur.fetchall()
cur.close()
conn.close()
result = "<h2>Users:</h2><ul>"
for row in rows:
result += f"<li>ID: {row[0]}, Name: {row[1]}, Email: {row[2]}</li>"
result += "</ul>"
return result
except Exception as e:
return f"Error: {e}", 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
EOF
# 内容を確認(先頭20行)
head -20 app/app.py
6-7. init.sqlを作成
# init.sqlを作成(初期データ)
cat > init.sql << ‘EOF’
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100)
);
INSERT INTO users (name, email) VALUES
(‘Alice’, ‘alice@example.com’),
(‘Bob’, ‘bob@example.com’),
(‘Charlie’, ‘charlie@example.com’);
EOF
# 内容を確認
cat init.sql
6-8. docker-compose.ymlを作成
# docker-compose.ymlを作成
cat > docker-compose.yml << ‘EOF’
version: ‘3.8’
services:
# PostgreSQLサービス
postgres:
image: postgres:13
container_name: flask_postgres
env_file:
– .env
volumes:
– postgres_data:/var/lib/postgresql/data
– ./init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
– “5432:5432”
restart: unless-stopped
# Flaskアプリ
webapp:
build: ./app
container_name: flask_app
env_file:
– .env
ports:
– “5000:5000”
depends_on:
– postgres
restart: unless-stopped
# ボリュームの定義
volumes:
postgres_data:
EOF
# 内容を確認
cat docker-compose.yml
6-9. ファイル構成を確認
# ファイル構成を確認
find . -type f | head -20
./.env
./init.sql
./docker-compose.yml
./app/requirements.txt
./app/Dockerfile
./app/app.py
6-10. 起動
# イメージをビルドして起動
docker-compose up –build -d
# ログ確認(Ctrl+Cで終了)
docker-compose logs -f
Creating network “flask-postgres_default” with the default driver
Creating volume “flask-postgres_postgres_data” with default driver
Building webapp
…
Successfully built abc123def456
Successfully tagged flask-postgres_webapp:latest
Creating flask_postgres … done
Creating flask_app … done
6-11. 動作確認
# サービスの状態確認
docker-compose ps
🌐 ブラウザでアクセス
http://localhost:5000/ → “Hello from Flask + PostgreSQL!”
http://localhost:5000/db-test → PostgreSQLバージョン表示
http://localhost:5000/users → ユーザー一覧表示
6-12. データベースに直接接続
# PostgreSQLコンテナ内でpsql起動
docker-compose exec postgres psql -U flaskuser -d flaskdb
# psql内でSQL実行
# SELECT * FROM users;
# \q — 終了
6-13. クリーンアップ
# 停止して削除
docker-compose down
# ボリュームも削除(データが消える)
docker-compose down -v
# 作成したイメージも削除
docker rmi flask-postgres_webapp
💪 7. 練習問題
練習問題 1
基礎
imageとbuildの違いを説明してください。
解答を見る
【解答】
image: 既存のDockerイメージを指定する。Docker Hubなどから取得。
build: Dockerfileからイメージをビルドする。カスタムアプリケーション用。
使い分け:
公式イメージ(PostgreSQL、Redisなど)→ image:
自作アプリケーション → build:
練習問題 2
基礎
portsとexposeの違いは何ですか?
解答を見る
【解答】
ports: ホストからもアクセス可能にする。外部公開。
expose: 同じネットワーク内のコンテナからのみアクセス可能。内部公開。
services:
webapp:
ports:
– “5000:5000” # ホストの5000番でアクセス可
backend:
expose:
– “8080” # 他のコンテナからのみアクセス可
練習問題 3
応用
次の要件を満たすdocker-compose.ymlを作成してください。
Nginx(ポート80)
Flask(ポート5000、./appからビルド)
PostgreSQL(.envファイルから環境変数)
FlaskはPostgreSQLの起動後に起動
NginxはFlaskの起動後に起動
解答を見る
【解答】
version: ‘3.8’
services:
postgres:
image: postgres:13
env_file:
– .env
volumes:
– postgres_data:/var/lib/postgresql/data
restart: unless-stopped
flask:
build: ./app
env_file:
– .env
depends_on:
– postgres
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
– “80:80”
volumes:
– ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
– flask
restart: unless-stopped
volumes:
postgres_data:
練習問題 4
応用
環境変数を設定する3つの方法をそれぞれコード例で示してください。
解答を見る
【解答】
方法1:environmentで直接指定
services:
webapp:
image: myapp
environment:
DATABASE_URL: postgresql://user:pass@db:5432/mydb
DEBUG: “true”
方法2:env_fileで外部ファイル
services:
webapp:
image: myapp
env_file:
– .env
方法3:ホストの環境変数
services:
webapp:
image: myapp
environment:
DATABASE_URL: ${DATABASE_URL}
SECRET_KEY: ${SECRET_KEY:-default}
練習問題 5
応用
depends_onの注意点と、その対策を説明してください。
解答を見る
【解答】
注意点:
depends_onはコンテナの起動順序を制御しますが、サービスが完全に準備完了するまで待たない 。
例:PostgreSQLコンテナは起動しても、PostgreSQL自体の初期化には数秒かかる。
対策:
アプリ側でリトライロジックを実装する(推奨)
import time
import psycopg2
def connect_db(max_retries=5):
for i in range(max_retries):
try:
conn = psycopg2.connect(DATABASE_URL)
return conn
except:
if i < max_retries - 1:
time.sleep(2)
else:
raise
練習問題 6
発展
次の構成のdocker-compose.ymlを作成してください。
フロントエンド(React、./frontendからビルド、ポート3000)
バックエンド(Flask、./backendからビルド)
PostgreSQL(永続化あり)
Redis
Nginx(ポート80)
適切な依存関係と環境変数設定
解答を見る
【解答】
version: ‘3.8’
services:
postgres:
image: postgres:13
environment:
POSTGRES_USER: appuser
POSTGRES_PASSWORD: apppass
POSTGRES_DB: appdb
volumes:
– postgres_data:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: redis:alpine
restart: unless-stopped
backend:
build: ./backend
environment:
DATABASE_URL: postgresql://appuser:apppass@postgres:5432/appdb
REDIS_URL: redis://redis:6379
depends_on:
– postgres
– redis
restart: unless-stopped
frontend:
build: ./frontend
ports:
– “3000:3000”
environment:
REACT_APP_API_URL: http://backend:5000
depends_on:
– backend
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
– “80:80”
volumes:
– ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
– frontend
– backend
restart: unless-stopped
volumes:
postgres_data:
練習問題 7
発展
.envファイルを使った環境別設定を実装してください。
要件:
• .env.dev(開発環境)
• .env.prod(本番環境)
• docker-compose.dev.yml
• docker-compose.prod.yml
解答を見る
【解答】
.env.dev:
DEBUG=true
LOG_LEVEL=DEBUG
DATABASE_URL=postgresql://dev:devpass@postgres:5432/devdb
.env.prod:
DEBUG=false
LOG_LEVEL=INFO
DATABASE_URL=postgresql://prod:prodpass@postgres:5432/proddb
docker-compose.dev.yml:
version: ‘3.8’
services:
webapp:
build: ./app
env_file:
– .env.dev
ports:
– “5000:5000”
volumes:
– ./app:/app # ホットリロード用
postgres:
image: postgres:13
env_file:
– .env.dev
ports:
– “5432:5432” # デバッグ用に公開
使用方法:
# 開発環境
docker-compose -f docker-compose.dev.yml up
# 本番環境
docker-compose -f docker-compose.prod.yml up -d
練習問題 8
応用
バインドマウントと名前付きボリュームの使い分けを説明してください。
解答を見る
【解答】
バインドマウント:
使用場面: 開発時、設定ファイル、ソースコード
特徴: ホストのパスを直接指定
例: ./app:/app
名前付きボリューム:
使用場面: データベース、本番データ
特徴: Dockerが管理、バックアップしやすい
例: postgres_data:/var/lib/postgresql/data
services:
webapp:
volumes:
# バインドマウント(開発用)
– ./app:/app
– ./config.yml:/etc/config.yml
# 名前付きボリューム(データ永続化)
– app_data:/app/data
volumes:
app_data:
練習問題 9
基礎
docker-compose.ymlでポート番号を書く時、なぜ引用符で囲むべきですか?
解答を見る
【解答】
YAMLの文法上、xx:yyという形式は時刻として解釈される可能性 があるためです。
ports:
– 80:80 # ⚠️ 時刻と解釈される可能性
– “80:80” # ✅ 文字列として確実に解釈される
常に引用符で囲む ことがベストプラクティスです。
練習問題 10
発展
マイクロサービス構成のdocker-compose.ymlを作成してください。
API Gateway(Nginx、ポート80)
User Service(./user-serviceからビルド)
Order Service(./order-serviceからビルド)
各サービス専用のPostgreSQL
共有Redis
解答を見る
【解答】
version: ‘3.8’
services:
# User Service用DB
user-db:
image: postgres:13
environment:
POSTGRES_DB: userdb
POSTGRES_USER: useruser
POSTGRES_PASSWORD: userpass
volumes:
– user_db_data:/var/lib/postgresql/data
# Order Service用DB
order-db:
image: postgres:13
environment:
POSTGRES_DB: orderdb
POSTGRES_USER: orderuser
POSTGRES_PASSWORD: orderpass
volumes:
– order_db_data:/var/lib/postgresql/data
# 共有Redis
redis:
image: redis:alpine
# User Service
user-service:
build: ./user-service
environment:
DATABASE_URL: postgresql://useruser:userpass@user-db:5432/userdb
REDIS_URL: redis://redis:6379
depends_on:
– user-db
– redis
# Order Service
order-service:
build: ./order-service
environment:
DATABASE_URL: postgresql://orderuser:orderpass@order-db:5432/orderdb
REDIS_URL: redis://redis:6379
depends_on:
– order-db
– redis
# API Gateway
nginx:
image: nginx:alpine
ports:
– “80:80”
volumes:
– ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
– user-service
– order-service
volumes:
user_db_data:
order_db_data:
📝 STEP 16 のまとめ
✅ このステップで学んだこと
services、networks、volumes: docker-compose.ymlの3大要素
imageとbuild: 既存イメージか、カスタムビルドか
ポートマッピング: portsとexposeの使い分け
環境変数: environment、env_file、ホスト変数の3つの方法
depends_on: 起動順序の制御とリトライの重要性
実践: Flask + PostgreSQLの連携を実装
📊 docker-compose.yml 主要設定早見表
設定項目
説明・例
image
既存イメージを使用:image: postgres:13
build
Dockerfileからビルド:build: ./app
ports
外部公開:ports: - "8080:80"
expose
内部公開:expose: - "5000"
environment
環境変数直接指定
env_file
外部ファイルから環境変数:env_file: - .env
depends_on
起動順序制御:depends_on: - postgres
volumes
ボリューム:- data:/app/data
💡 重要ポイント
.envファイル で機密情報を分離(.gitignoreに追加)
ポート番号 は必ず引用符で囲む("8080:80")
depends_on は起動順序のみ、準備完了は待たない
バインドマウント は開発用、名前付きボリューム は本番用
🎯 次のステップの予告
次のSTEP 17では、「複数コンテナの連携」 をさらに深く学びます。
PostgreSQL + pgAdminの実践的な構成
サービス間の通信の詳細
ネットワークの自動作成
データベース初期化
より複雑なマルチコンテナ環境を構築していきましょう!