2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

開発用Dockerテンプレートの作成(その1)

Posted at

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.ymlvolumesセクションでコンテナにマウントしており、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-servicepgadmin-servicevalkey-service)で名前解決し、通信できるようになります。
これにより、ホストOSのネットワークに直接公開することなく、コンテナ間の安全な連携環境を構築できます。

#********************************************************
# 独自ネットワークの定義
#********************************************************
networks:
  my_sample_network:

コンテナの起動と終了

通常の docker compose コマンドでの操作と変わりません。

起動(docker compose up -d)

pgadmin-containerpgdb-containerのヘルスチェックが終了してから起動します。
この動きはdocker-compose.ymldepends_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イメージをそのまま活用して手軽に環境を構築したいと考える方々(個人開発者や学習・検証目的の方など)向けに、データベースのコンテナ定義について解説しました。

本連載では、ミッションクリティカルなシステムや大規模なクラスタリング環境ではない「主に個人開発や小規模なプロジェクト、あるいは学習・プロトタイプ開発の環境」を構築していきます。

次回は、ログ出力を非同期的に実施する仕組みの構築について解説する予定です。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?