Dockerを利用することで、開発環境や運用環境の構築にかかる手間を大幅に削減できます。
環境構築の設計情報がテキストファイルとして「見える化」される上、環境の構築・破棄がコマンド一つで簡単に実行できることから、作業ミスによる「手戻り」を防ぐことも可能です。
ただ、多くのプロジェクトでは「類似する環境や機能(例えばデータベースやログ出力機能など)」を構築するケースが多いと思われ、それらを「汎用的なテンプレート」として事前に用意しておけば、さらに作業負荷を軽減することができそうです。
「類似する環境や機能」の解釈は人それぞれですが、本記事はあくまで 私の独断と偏見 に基づいて説明していくので ご容赦を。
そのため、本記事では個人開発を念頭に置いた「Docker環境テンプレート」を作成していくことにします。
構築するDocker環境
私自身が何かを開発するときに構成するであろう「4つの機能ブロック」を構築します。
-
データベース
リレーショナルデータベース(PostgreSQL)と その管理ツール(pgAdmin4)、および インメモリ データベース(Valkey)を構築します。
特定のアプリケーションや機能に特化した設定は行わず、公開されている Docker イメージそのままに各コンテナを作成します。
-
ログ出力
Valkeyでログ出力要求を受け付ける「キュー」を形成し、ログメッセージをリレーショナルデータベース(PostgreSQL)へ格納する機能を提供します。
使用する言語は Python とし、Valkey を使って「キュー」の仕組みを実現します。
-
バックエンド(API)
「指定されたメッセージをログ出力する Web API」をサンプルとして用意します。
言語は Python とし、FastAPI フレームワークで Web API(入出力データは JSON 形式)を作成します。
-
フロントエンド(UI)
「Hello World」を表示する Webアプリケーション をサンプルとして用意します。
ブラウザ画面がリロードされるたびに Web API を呼び出し、ログを出力する仕組みを組み込みます。
docker-composeファイル
本記事では 4本の docker-compose ファイルを作成します。
ファイル名 | Service | 機能分類 | Remote接続 |
---|---|---|---|
docker-compose.yml | 3個 | データベース | |
docker-compose_dbg_log.yml | 1個 | ログ | 〇 |
docker-compose_dbg_api.yml | 1個 | バックエンド | 〇 |
docker-compose_dbg_ui.yml | 1個 | フロントエンド | 〇 |
Remote接続 とは、VSCode からリモート接続して コーディング および デバッグ実行 が可能であることを示しています。
VS Codeでリモート接続を終了すると、原則として そのdocker-compose.yml
ファイルで定義された全てのコンテナが停止します。
デバッグ対象のコンテナと同じdocker-compose.yml
ファイルに、本来常時稼働させておきたいコンテナ(データベースなど)が定義されている場合、それらのコンテナまで道連れで停止してしまうことになってしまいます。
この問題を避けるため、VS Codeでリモート接続・デバッグを行うコンテナごとにdocker-compose.yml
ファイルを分割することをお勧めします。これにより、デバッグ対象のコンテナを停止させても、他の常時稼働コンテナは影響を受けずに稼働し続けることができます。
一方、リモート接続終了とともに全ての関連コンテナを停止させたい場合は、全ての定義を1つのdocker-compose.yml
ファイルに記述するのが適切でしょう。
機能ブロック①: データベース
二つのデータベースと一つの管理ツールのそれぞれを Docker コンテナとします。
作成する Dockerコンテナ
① リレーショナル データベース(db-service)
② データベース管理ツール(pgadmin-service)
③ インメモリ データベース(valkey-service)
フォルダ構成
プロダクトのルートフォルダ名を「sample-product」とします。
また、Valkey用の設定ファイル(valkey.conf
)を valkey
フォルダの直下に作成します。
※ 各ファイルの内容は後述します。
C:\...\sample-product
│ .env
│ docker-compose.yml
│
└─valkey
valkey.conf
Dockerコンテナの詳細
① リレーショナル データベース(db-service)
Docker Hubの公式イメージを活用することで、特別な作り込みをせずとも汎用的なPostgreSQL RDB環境を迅速に構築できます。
docker-compose.yml に記述する内容
このdb-service
コンテナは、networks
セクションで定義された独自のDockerネットワーク(例: my_sample_network
)を利用し、同じネットワーク内の他のコンテナからのみアクセスできます。
もしホストOS側から直接データベースにアクセスしたい場合は、ports
セクションでポートマッピングを追加することで対応可能です。
image
タグにはlatest
ではなくマイナーバージョンまで含めた安定版(17.6
)を指定します。
latest
タグは「最新の安定版」を意味しますが、コンテナの再作成によって予期せぬバージョンアップが実施される可能性もあるため、原則として使用を避けた方が良いでしょう。
#----------------------------------------
# PostgreSQL データベースサービス
#----------------------------------------
db-service:
# PostgreSQL 17 を使用する。
# (2025/10/1 時点の最新版は 18.0)
image: postgres:17.6
container_name: ${DB_CONTAINER_NAME} # コンテナ名
# サーバー再起動時やエラー発生時に自動でコンテナを再起動する。
# 開発作業に使用をきたす場合はコメントアウトすること。
restart: always
environment:
POSTGRES_DB: ${POSTGRES_DB} # データベース名
POSTGRES_USER: ${POSTGRES_USER} # データベースユーザー名
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} # データベースパスワード
volumes:
# データ永続化用の名前付きボリューム
# 注)PostgreSQL 18 以降とはフォルダパスが異なります。
# /var/lib/postgresql/data : データベースファイルの既定の配置場所
- db_data_volume:/var/lib/postgresql/data
networks:
# コンテナ間 専用ネットワーク
- my_sample_network
# PostgreSQL データベースへ接続可能となったかを確認する処理。
# 他コンテナの「depends_on」で「condition: service_healthy」が
# 指定されていた場合に実行する。
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s # 5秒毎にチェック
timeout: 5s # 5秒以内に応答が無ければ失敗
retries: 5 # 5回連続で失敗したら unhealthy と判断
start_period: 10s # 起動から10秒間は失敗しても無視する
.env ファイル に記述する内容
下記はサンプルの値なので、必要に応じて書き換えてください。
特にユーザー名やパスワードは、必ず書き換えるようにしてください。
パスワードは、セキュリティの観点から十分に複雑な文字列を設定しましょう。
#----------------------------------------
# PostgreSQL データベースサービス
#----------------------------------------
DB_CONTAINER_NAME=pgdb-container # コンテナ名
DB_VOLUME_NAME=pgdb-volume # 名前付きボリューム名
POSTGRES_DB=my-sample-db # データベース名
POSTGRES_USER=postgres # データベースユーザー名
POSTGRES_PASSWORD=your_strong_password # データベースパスワード
② データベース管理ツール(pgadmin-service)
pgAdminもDocker Hubの公式イメージ(dpage/pgadmin4
)から簡単に導入できます。
docker-compose.yml に記述する内容
このpgadmin-service
コンテナは、dpage/pgadmin4
の公式イメージ(9.8.0
)を使用します。
ports
セクションでは、ホストOS側のポート(例: 18080
)とコンテナ内部の pgAdminが使用するポート(デフォルト 80
)をマッピングします。これにより、ホストOSのWebブラウザからpgAdminへアクセスできるようになります。
また、depends_on
を使用することで、db-service
のヘルスチェックが正常に完了するまでpgadmin-service
の起動を待機させることができます。
#----------------------------------------
# pgAdmin 4 データベース管理ツールサービス
#----------------------------------------
pgadmin-service:
# pgAdmin4 9.8.0 を使用する。
# (2025/10/1 時点の最新版は 9.8.0)
image: dpage/pgadmin4:9.8.0
container_name: ${PGADMIN_CONTAINER_NAME} # コンテナ名
environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_EMAIL} # ログイン用メールアドレス
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD} # ログイン用パスワード
volumes:
# データ永続化用の名前付きボリューム
- pgadmin_data_volume:/var/lib/pgadmin
ports:
# ホスト上のブラウザからアクセスするときのポート番号を、
# コンテナ内部ポート(80)へマッピング
- "${PGADMIN_HOST_PORT}:80"
networks:
# コンテナ間 専用ネットワーク
- my_sample_network
depends_on:
# db-service の起動が完了するまで待ち続ける
db-service:
# healthcheck が完了するまで待機
condition: service_healthy
.env ファイル に記述する内容
下記はサンプルの値なので、必要に応じて書き換えてください。
パスワードは、セキュリティの観点から十分に複雑な文字列を設定しましょう。
#----------------------------------------
# pgAdminアプリケーションサービス
#----------------------------------------
PGADMIN_CONTAINER_NAME=pgadmin-container # コンテナ名
PGADMIN_VOLUME_NAME=pgadmin-volume # 名前付きボリューム名
PGADMIN_HOST_PORT=18080 # ポスト側マッピングポート
PGADMIN_EMAIL=user@example.com # ログイン時に使用するメールアドレス
PGADMIN_PASSWORD=your_strong_password # ログイン時に使用するログインパスワード
③ インメモリ データベース(valkey-service)
Valkeyは、オープンソースのRedis
フォークであり、Redis
との高い互換性を持ちながら、コミュニティ主導で開発が進められている高速なインメモリデータストアです。
キャッシュ、メッセージキュー、セッション管理など、様々な用途に利用可能で、Docker Hubの公式イメージを活用することで、特別な作り込みをせずとも迅速に環境を構築できます。
docker-compose.yml に記述する内容
このvalkey-service
コンテナは、valkey/valkey
の公式イメージ(8.1.3
)を使用します。
Valkeyの動作をカスタマイズするための設定ファイル(valkey.conf
)は、volumes
にてコンテナ内部へ直接マウントしています。
また、Valkeyサーバーの正常起動を確認するための healthcheck
も定義しているので、Valkeyに依存する他コンテナが先に起動してしまう事を抑止することも可能です。
(他コンテナの定義で condition: service_healthy
を記述した場合のみ)
#----------------------------------------
# Valkey サービス
#----------------------------------------
valkey-service:
# Valkey 8.1.3 を使用する。
# (2025/10/1 時点の最新版は 8.1.3)
image: valkey/valkey:8.1.3
container_name: ${VALKEY_CONTAINER_NAME}
environment:
# Valkeyの認証パスワード
VALKEY_PASSWORD: ${VALKEY_PASSWORD}
volumes:
# データ永続化用の名前付きボリューム
- valkey_data:/data
# Valkey サービス用のカスタム設定ファイル
# ホスト側ファイルシステム上のファイルを、直接 コンテナ内に
# マウントする
- ./valkey/valkey.conf:/usr/local/etc/valkey/valkey.conf
networks:
# コンテナ間 専用ネットワーク
- my_sample_network
# ping コマンドに対する応答があるかどうかを確認する処理。
# 他コンテナの「depends_on」で「condition: service_healthy」が
# 指定されていた場合に実行する。
healthcheck:
test: ["CMD-SHELL", "valkey-cli -a ${VALKEY_PASSWORD} ping"]
interval: 5s # 5秒毎にチェック
timeout: 5s # 5秒以内に応答が無ければ失敗
retries: 5 # 5回連続で失敗したら unhealthy と判断
start_period: 10s # 起動から10秒間は失敗しても無視する
valkey.conf ファイルに記述する内容
カスタム設定ファイルvalkey.conf
でValkey動作の詳細を設定します。
このファイルはdocker-compose.yml
のvolumes
セクションでコンテナにマウントしており、Valkeyサーバーの起動時に読み込まれます。
# valkey/valkey.conf
#------------------------
# 認証設定
#------------------------
# パスワード設定
# 環境変数 VALKEY_PASSWORD と同じ値にする。
requirepass your_strong_password
#------------------------
# 接続設定
#------------------------
# コンテナで利用可能な すべてのネットワークインタフェース からの接続を許可。
bind 0.0.0.0
# 接続ポート(既定は 6379)
port 6379
# 保護モードを無効化して、コンテナ外からの接続を許可。
protected-mode no
#------------------------
# メモリ設定
#------------------------
# メモリ制限の設定(例: 256MB)
maxmemory 256mb
# メモリ上限に達した際のデータ削除ポリシー
# allkeys-lru: 全てのキーの中から最も長い間使用されていない Least Recently
# Usedキーを削除する。
maxmemory-policy allkeys-lru
#------------------------
# データの永続化設定
#------------------------
# データの永続化設定 (AOF: Append Only File)
# Valkeyがクラッシュした場合のデータ損失を最小限に抑えるため、データの
# 永続化を設定。
appendonly yes
# AOFファイルの同期頻度
# everysec: 毎秒fsyncを実行する。
appendfsync everysec
# 永続化ファイルの保存ディレクトリ
dir /data
#------------------------
# ログ設定
#------------------------
# ログ出力レベル
# debug, verbose, notice, warning
loglevel notice
.env ファイル に記述する内容
下記はサンプルの値なので、必要に応じて書き換えてください。
パスワードは、セキュリティの観点から十分に複雑な文字列を設定しましょう。
#----------------------------------------
# Valkey サービス
#----------------------------------------
VALKEY_CONTAINER_NAME=valket-container # コンテナ名
VALKEY_VOLUME_NAME=valkey-volume # 名前付きボリューム名
VALKEY_PASSWORD=your_strong_password # Valkeyの認証パスワード
名前付きボリューム
Dockerコンテナ内のデータは、コンテナが削除されると失われてしまいます。これを防ぎ、データを永続化するためには「名前付きボリューム」を利用します。
以下のvolumes
定義では、各サービスがそれぞれ専用のボリュームを使用することで、PostgreSQLのデータ、pgAdminの設定、Valkeyのデータなどを安全に保存できます。
各ボリュームのname
プロパティには、.env
ファイルで定義された環境変数を指定しており、これによりボリューム名を柔軟に管理できます。
#********************************************************
# 永続化のための 名前付きボリューム
#********************************************************
volumes:
db_data_volume:
name: ${DB_VOLUME_NAME}
pgadmin_data_volume:
name: ${PGADMIN_VOLUME_NAME}
valkey_data:
name: ${VALKEY_VOLUME_NAME}
ネットワーク定義
Docker Composeで複数のサービスを連携させる場合、コンテナ間の通信をセキュアかつ効率的に行うために独自のネットワークを定義することが可能です。
以下のnetworks
定義では、my_sample_network
という名前のプライベートネットワークを作成しています。このネットワークに接続されたコンテナは、互いにサービス名(例: db-service
、pgadmin-service
、valkey-service
)で名前解決し、通信できるようになります。
これにより、ホストOSのネットワークに直接公開することなく、コンテナ間の安全な連携環境を構築できます。
#********************************************************
# 独自ネットワークの定義
#********************************************************
networks:
my_sample_network:
コンテナの起動と終了
通常の docker compose コマンドでの操作と変わりません。
起動(docker compose up -d)
pgadmin-container
はpgdb-container
のヘルスチェックが終了してから起動します。
この動きはdocker-compose.yml
のdepends_on
によって制御されます。
$ docker compose up -d
[+] Running 39/39
✔ db-service Pulled 38.8s
✔ 8c7716127147 Pull complete 12.6s
✔ de7816569160 Pull complete 12.6s
✔ 1ed9605b075e Pull complete 13.4s
(中略)
[+] Running 7/7
✔ sample-product_my_sample_network Created 0.1s
✔ Volume pgadmin-volume Created 0.0s
✔ Volume valkey-volume Created 0.0s
✔ Volume pgdb-volume Created 0.0s
✔ Container pgdb-container Healthy 6.8s
✔ Container valket-container Started 1.4s
✔ Container pgadmin-container Started 6.3s
終了(docker compose down)
depends_on
で制御されたコンテナは、起動時とは逆順に終了していきます。
そのため、pgadmin-container
が終了してからpgdb-container
の終了処理が始まります。
$ docker compose down
[+] Running 4/4
✔ Container valket-container Removed 0.6s
✔ Container pgadmin-container Removed 2.8s
✔ Container pgdb-container Removed 0.5s
✔ Network sample-product_my_sample_network Removed 0.5s
終わりに
今回は Dockerイメージをそのまま活用して手軽に環境を構築したいと考える方々(個人開発者や学習・検証目的の方など)向けに、データベースのコンテナ定義について解説しました。
本連載では、ミッションクリティカルなシステムや大規模なクラスタリング環境ではない「主に個人開発や小規模なプロジェクト、あるいは学習・プロトタイプ開発の環境」を構築していきます。
次回は、ログ出力を非同期的に実施する仕組みの構築について解説する予定です。