🔧 0. このステップの前提知識
📚 STEP 15・16の復習
このステップでは、以下の知識を使います。忘れた場合は復習してから進めましょう。
- Docker Compose:複数コンテナを管理するツール
- docker-compose.yml:services、volumes、networksの設定
- depends_on:起動順序の制御
- サービス名での通信:コンテナ間はサービス名でアクセス
0-1. 作業ディレクトリの準備
# 作業ディレクトリを作成して移動
mkdir -p ~/docker-practice/step17
cd ~/docker-practice/step17
# 現在の場所を確認
pwd
0-2. このステップで構築する環境
【PostgreSQL + pgAdmin 構成図】
┌─────────────────────────────────────────────────────────────┐
│ ユーザー(あなた) │
└───────────────────────────┬─────────────────────────────────┘
│
│ ブラウザでアクセス
↓ http://localhost:5050
┌─────────────────────────────────────────────────────────────┐
│ pgAdmin(データベース管理GUI) │
│ dpage/pgadmin4 │
│ ポート 5050:80 │
└───────────────────────────┬─────────────────────────────────┘
│
│ サービス名「postgres」で接続
↓ postgres:5432
┌─────────────────────────────────────────────────────────────┐
│ PostgreSQL(データベース) │
│ postgres:13 │
│ ポート 5432:5432 │
└───────────────────────────┬─────────────────────────────────┘
│
│ データ永続化
↓
┌─────────────────────────────────────────────────────────────┐
│ Dockerボリューム │
│ postgres_data │
└─────────────────────────────────────────────────────────────┘
0-3. 必要なコンポーネント
🐘 PostgreSQL
- イメージ: postgres:13
- ポート: 5432
- 環境変数: ユーザー、パスワード、DB名
- ボリューム: データ永続化
🔧 pgAdmin
- イメージ: dpage/pgadmin4
- ポート: 5050(80番を公開)
- 環境変数: 管理者メール、パスワード
- 依存関係: PostgreSQL
🎯 1. PostgreSQL + pgAdminの構成
1-1. なぜこの構成?
PostgreSQL(データベース)とpgAdmin(管理ツール)の組み合わせは、データエンジニアリングで最も基本的な構成です。
📊 構成の役割
- PostgreSQL:データを保存・管理するデータベース本体
- pgAdmin:ブラウザでデータベースを操作できるGUIツール
この2つを連携させることで、コマンドラインなしでデータベースを操作できます。
1-2. 最小構成のdocker-compose.yml
# 最小構成の例
version: ‘3.8’
services:
postgres:
image: postgres:13
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
POSTGRES_DB: mydb
ports:
– “5432:5432”
volumes:
– postgres_data:/var/lib/postgresql/data
pgadmin:
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: admin@example.com
PGADMIN_DEFAULT_PASSWORD: admin
ports:
– “5050:80”
depends_on:
– postgres
volumes:
postgres_data:
🌐 2. サービス間の通信
2-1. Docker Composeのネットワーク
Docker Composeで起動したコンテナは、自動的に同じネットワークに配置されます。
【サービス間通信の仕組み】
┌─────────────────────────────────────────────────────────────┐
│ Docker Composeネットワーク │
│ (myproject_default) │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ pgadmin │ ─────────────────▶│ postgres │ │
│ │ │ postgres:5432 │ │ │
│ │ │ (サービス名で接続)│ │ │
│ └─────────────┘ └─────────────┘ │
│ │
│ 💡 サービス名 = ホスト名 │
│ IPアドレスを調べる必要なし! │
└─────────────────────────────────────────────────────────────┘
💡 重要ポイント
Docker Composeでは、IPアドレスを調べる必要がありません。
サービス名を使えば、Dockerが自動的にIPアドレスを解決してくれます。
2-2. 接続設定の正しい書き方
# ❌ 悪い例:IPアドレスを使う
接続先: 172.18.0.2:5432
# ❌ 悪い例:localhostを使う
接続先: localhost:5432
# ✅ 良い例:サービス名を使う
接続先: postgres:5432
2-3. ポート番号の使い分け
ポートの使い分け
| アクセス元 → アクセス先 |
使用するアドレス |
| ホスト(ブラウザ)→ pgAdmin |
localhost:5050 |
| pgAdmin → PostgreSQL |
postgres:5432(サービス名) |
| ホスト(psql)→ PostgreSQL |
localhost:5432 |
2-4. 通信の確認方法
# pgAdminコンテナからPostgreSQLにpingを打つ
docker-compose exec pgadmin ping postgres -c 3
PING postgres (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.123 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.098 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.102 ms
🌉 3. ネットワークの自動作成
3-1. デフォルトネットワーク
Docker Composeは、プロジェクト名_defaultという名前のネットワークを自動で作成します。
【デフォルトネットワークの命名規則】
docker-compose.ymlがあるディレクトリ名がプロジェクト名になる
myproject/ ← ディレクトリ名
└── docker-compose.yml
↓ docker-compose up -d
ネットワーク名: myproject_default
コンテナ名: myproject_postgres_1
myproject_pgadmin_1
# ネットワーク確認
docker network ls
NETWORK ID NAME DRIVER SCOPE
abc123def456 myproject_default bridge local
3-2. カスタムネットワークの定義
必要に応じて、独自のネットワークを定義できます。
version: ‘3.8’
services:
postgres:
image: postgres:13
networks:
– db-network # カスタムネットワークを使用
pgadmin:
image: dpage/pgadmin4
networks:
– db-network # 同じネットワークに参加
# ネットワークの定義
networks:
db-network:
driver: bridge
3-3. 複数ネットワークによるセキュリティ向上
【複数ネットワークによる分離】
┌─────────────────────────────────────────────────────────────┐
│ frontend-network │
│ ┌─────────┐ ┌─────────┐ │
│ │ nginx │ ────────▶│ webapp │ │
│ │ │ │ │ │
│ └─────────┘ └────┬────┘ │
└────────────────────────────┼────────────────────────────────┘
│
┌────────────────────────────┼────────────────────────────────┐
│ backend-network │
│ ┌───┴───┐ │
│ │webapp │ │
│ └───┬───┘ │
│ │ │
│ ┌───▼───┐ │
│ │postgres│ │
│ └───────┘ │
└─────────────────────────────────────────────────────────────┘
💡 nginxからpostgresには直接アクセスできない = セキュリティ向上
version: ‘3.8’
services:
postgres:
image: postgres:13
networks:
– backend-network # バックエンド専用
webapp:
image: myapp:latest
networks:
– backend-network # DBにアクセス
– frontend-network # フロントエンドにも公開
nginx:
image: nginx
networks:
– frontend-network # フロントエンドのみ
networks:
backend-network:
frontend-network:
🔧 4. データベースの初期化
4-1. 初期化スクリプトの配置
PostgreSQLコンテナは、/docker-entrypoint-initdb.d/ディレクトリ内のSQLファイルを自動実行します。
【初期化スクリプトの仕組み】
ホスト側 コンテナ内
─────────────────────────────────────────────────────────────
./init-scripts/ /docker-entrypoint-initdb.d/
├── 01-create-tables.sql ──────▶ 01-create-tables.sql (1番目に実行)
├── 02-insert-data.sql ──────▶ 02-insert-data.sql (2番目に実行)
└── 03-create-indexes.sql ──────▶ 03-create-indexes.sql (3番目に実行)
💡 ファイル名のアルファベット順で実行される
💡 初回起動時のみ実行(ボリュームが空の時)
4-2. docker-compose.ymlでマウント
version: ‘3.8’
services:
postgres:
image: postgres:13
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypass
POSTGRES_DB: mydb
volumes:
# データ永続化
– postgres_data:/var/lib/postgresql/data
# 初期化スクリプト
– ./init-scripts:/docker-entrypoint-initdb.d
ports:
– “5432:5432”
volumes:
postgres_data:
⚠️ 初期化の実行タイミング
- 初期化スクリプトは、初回起動時のみ実行されます
- ボリュームにデータが既にある場合は実行されません
- 再初期化するには、ボリュームを削除してから再起動
4-3. 再初期化の方法
# 1. コンテナとボリュームを削除
docker-compose down -v
# 2. 再起動(初期化スクリプトが実行される)
docker-compose up -d
🛠️ 5. 実践演習:データベース管理環境の構築
5-1. 演習の目標
PostgreSQL + pgAdminの本格的な環境を、初期データ込みで構築します。
📁 完成時のプロジェクト構成
postgres-pgadmin-full/
├── docker-compose.yml
├── .env
└── init-scripts/
├── 01-create-tables.sql
└── 02-insert-data.sql
5-2. プロジェクトディレクトリを作成
# プロジェクトディレクトリを作成
mkdir -p ~/docker-practice/postgres-pgadmin-full/init-scripts
cd ~/docker-practice/postgres-pgadmin-full
# 現在の場所を確認
pwd
5-3. .envファイルを作成
# .envファイルを作成
cat > .env << ‘EOF’
# PostgreSQL設定
POSTGRES_USER=admin
POSTGRES_PASSWORD=admin123
POSTGRES_DB=mydatabase
# pgAdmin設定
PGADMIN_DEFAULT_EMAIL=admin@example.com
PGADMIN_DEFAULT_PASSWORD=admin123
EOF
# 内容を確認
cat .env
5-4. 初期化スクリプト(テーブル作成)
# テーブル作成スクリプト
cat > init-scripts/01-create-tables.sql << ‘EOF’
— 部署テーブル
CREATE TABLE departments (
dept_id SERIAL PRIMARY KEY,
dept_name VARCHAR(50) NOT NULL,
location VARCHAR(100)
);
— 従業員テーブル
CREATE TABLE employees (
emp_id SERIAL PRIMARY KEY,
emp_name VARCHAR(100) NOT NULL,
dept_id INT REFERENCES departments(dept_id),
salary DECIMAL(10, 2),
hire_date DATE,
email VARCHAR(100)
);
— プロジェクトテーブル
CREATE TABLE projects (
project_id SERIAL PRIMARY KEY,
project_name VARCHAR(100) NOT NULL,
start_date DATE,
end_date DATE,
budget DECIMAL(12, 2)
);
— 従業員-プロジェクト関連テーブル
CREATE TABLE employee_projects (
emp_id INT REFERENCES employees(emp_id),
project_id INT REFERENCES projects(project_id),
role VARCHAR(50),
PRIMARY KEY (emp_id, project_id)
);
EOF
# 内容を確認
cat init-scripts/01-create-tables.sql
5-5. 初期化スクリプト(データ挿入)
# データ挿入スクリプト
cat > init-scripts/02-insert-data.sql << ‘EOF’
— 部署データ
INSERT INTO departments (dept_name, location) VALUES
(‘開発部’, ‘東京’),
(‘営業部’, ‘大阪’),
(‘管理部’, ‘東京’),
(‘マーケティング部’, ‘福岡’);
— 従業員データ
INSERT INTO employees (emp_name, dept_id, salary, hire_date, email) VALUES
(‘田中太郎’, 1, 450000, ‘2020-04-01’, ‘tanaka@example.com’),
(‘佐藤花子’, 1, 480000, ‘2019-06-15’, ‘sato@example.com’),
(‘鈴木一郎’, 2, 420000, ‘2021-01-10’, ‘suzuki@example.com’),
(‘高橋美咲’, 3, 380000, ‘2020-09-01’, ‘takahashi@example.com’),
(‘伊藤健太’, 4, 410000, ‘2021-03-20’, ‘ito@example.com’);
— プロジェクトデータ
INSERT INTO projects (project_name, start_date, end_date, budget) VALUES
(‘Webサイトリニューアル’, ‘2024-01-01’, ‘2024-06-30’, 5000000),
(‘新製品開発’, ‘2024-02-01’, ‘2024-12-31’, 10000000),
(‘顧客管理システム構築’, ‘2024-03-01’, ‘2024-09-30’, 8000000);
— 従業員-プロジェクト関連
INSERT INTO employee_projects (emp_id, project_id, role) VALUES
(1, 1, ‘リーダー’),
(2, 1, ‘デザイナー’),
(1, 2, ‘エンジニア’),
(3, 3, ‘プロジェクトマネージャー’),
(5, 1, ‘マーケティング担当’);
EOF
# 内容を確認
cat init-scripts/02-insert-data.sql
5-6. docker-compose.ymlを作成
# docker-compose.ymlを作成
cat > docker-compose.yml << ‘EOF’
version: ‘3.8’
services:
# PostgreSQLデータベース
postgres:
image: postgres:13
container_name: postgres_db
env_file:
– .env
volumes:
# データ永続化
– postgres_data:/var/lib/postgresql/data
# 初期化スクリプト
– ./init-scripts:/docker-entrypoint-initdb.d
ports:
– “5432:5432”
restart: unless-stopped
healthcheck:
test: [“CMD-SHELL”, “pg_isready -U admin”]
interval: 10s
timeout: 5s
retries: 5
# pgAdmin管理ツール
pgadmin:
image: dpage/pgadmin4
container_name: pgadmin_gui
env_file:
– .env
volumes:
– pgadmin_data:/var/lib/pgadmin
ports:
– “5050:80”
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
# ボリュームの定義
volumes:
postgres_data:
pgadmin_data:
EOF
# 内容を確認
cat docker-compose.yml
🎯 healthcheckの説明
test: 実行するコマンド(pg_isreadyでPostgreSQLの準備確認)
interval: チェック間隔(10秒ごと)
timeout: タイムアウト時間(5秒)
retries: 失敗許容回数(5回)
condition: service_healthy:ヘルスチェック成功後にpgadminを起動
5-7. ファイル構成を確認
# ファイル構成を確認
find . -type f
./.env
./docker-compose.yml
./init-scripts/01-create-tables.sql
./init-scripts/02-insert-data.sql
5-8. 起動
# 起動
docker-compose up -d
# ログ確認(Ctrl+Cで終了)
docker-compose logs -f
Creating network “postgres-pgadmin-full_default” with the default driver
Creating volume “postgres-pgadmin-full_postgres_data” with default driver
Creating volume “postgres-pgadmin-full_pgadmin_data” with default driver
Creating postgres_db … done
Creating pgadmin_gui … done
5-9. pgAdminでデータベース接続
🌐 pgAdminへのアクセス手順
- ブラウザで
http://localhost:5050を開く
- ログイン:
Email: admin@example.com
Password: admin123
- 左上の「Add New Server」をクリック
- Generalタブ:
Name: My PostgreSQL
- Connectionタブ:
Host name: postgres(サービス名!)
Port: 5432
Maintenance database: mydatabase
Username: admin
Password: admin123
☑ Save password
- 「Save」をクリック
5-10. データ確認(pgAdminでクエリ実行)
📊 pgAdminでクエリ実行
- 左サイドバーでMy PostgreSQL > Databases > mydatabaseを展開
- 「mydatabase」を右クリック → Query Tool
- 以下のSQLを入力して実行(▶ボタン)
— 全従業員を表示
SELECT * FROM employees;
— 部署別の従業員数
SELECT d.dept_name, COUNT(e.emp_id) as employee_count
FROM departments d
LEFT JOIN employees e ON d.dept_id = e.dept_id
GROUP BY d.dept_name;
— プロジェクト別の参加者
SELECT p.project_name, e.emp_name, ep.role
FROM projects p
JOIN employee_projects ep ON p.project_id = ep.project_id
JOIN employees e ON ep.emp_id = e.emp_id
ORDER BY p.project_name;
5-11. コマンドラインからも接続
# PostgreSQLコンテナ内でpsql起動
docker-compose exec postgres psql -U admin -d mydatabase
mydatabase=# \dt
List of relations
Schema | Name | Type | Owner
——–+——————-+——-+——-
public | departments | table | admin
public | employees | table | admin
public | employee_projects | table | admin
public | projects | table | admin
(4 rows)
mydatabase=# SELECT emp_name, salary FROM employees ORDER BY salary DESC LIMIT 3;
emp_name | salary
————+———-
佐藤花子 | 480000.00
田中太郎 | 450000.00
鈴木一郎 | 420000.00
(3 rows)
mydatabase=# \q
5-12. クリーンアップ
# 停止して削除
docker-compose down
# ボリュームも削除(データが消える)
docker-compose down -v
🔍 6. トラブルシューティング
6-1. よくある問題と解決策
❌ 問題1:pgAdminからPostgreSQLに接続できない
症状:「could not connect to server」エラー
原因:
- ホスト名に
localhostを指定している
- PostgreSQLが完全に起動していない
解決策:
- ホスト名を
postgres(サービス名)に変更
- PostgreSQLのログを確認:
docker-compose logs postgres
- 数秒待ってから再接続
❌ 問題2:初期化スクリプトが実行されない
症状:テーブルが作成されていない
原因:
- ボリュームに既にデータが存在する
- SQLファイルに構文エラーがある
解決策:
# 1. 完全にリセット
docker-compose down -v
# 2. 再起動
docker-compose up -d
# 3. ログで初期化を確認
docker-compose logs postgres | grep -i “init\|create\|insert”
❌ 問題3:ポート5432が使用中
症状:「port is already allocated」エラー
解決策:
# 方法1:ホストのポートを変える
services:
postgres:
ports:
– “5433:5432” # ホスト側を5433に変更
# 方法2:使用中のプロセスを確認
lsof -i :5432
6-2. デバッグコマンド集
# コンテナの状態確認
docker-compose ps
# ログ確認
docker-compose logs postgres
docker-compose logs pgadmin
# ネットワーク確認
docker network ls
docker network inspect postgres-pgadmin-full_default
# ボリューム確認
docker volume ls
# コンテナ内でシェル起動
docker-compose exec postgres bash
docker-compose exec pgadmin sh
# PostgreSQLの接続テスト
docker-compose exec postgres pg_isready -U admin
# ネットワーク疎通確認
docker-compose exec pgadmin ping postgres -c 3