2026年7月1日

2026年7月1日

WordPressをDocker Composeで複数サービスと連携させるローカル開発環境の作り方

WordPress本体とデータベースだけでなく、Redis(オブジェクトキャッシュ)、メール確認用のMailpit、WP-CLI、phpMyAdminまでを1つの compose.yaml にまとめると、本番に近い構成を手元で何度でも作り直せるようになります。この記事では、サービス同士の名前解決・起動順・ファイル権限という「複数サービスならでは」のつまずきどころを押さえながら、動く構成を一つずつ組み立てます。

最低限のWordPress+MySQLの起動だけを知りたい場合は1サービス構成の解説で足ります。ここでは「本番ではRedisやメール送信を使っているのに、ローカルでは試せない」という人を想定しています。

全体の構成と考え方

今回作るサービスは次の6つです。

  • db:MariaDB。WordPressのデータベース
  • wordpress:公式イメージ(Apache+PHP)
  • redis:オブジェクトキャッシュ用
  • mailpit:WordPressが送るメールを受け止めて、ブラウザで確認するための開発用SMTPサーバー
  • wpcli:WP-CLIを実行するための使い捨てコンテナ
  • phpmyadmin:DBをブラウザで見るための管理画面(必要なときだけ起動)

Docker Composeでは、同じプロジェクト内のサービスは共通のネットワークに参加し、サービス名がそのままホスト名になります。WordPressから見たDBの接続先は localhost ではなく db です。ここを localhost にしてしまうのが、複数サービス構成で最も多い接続エラーの原因です。コンテナの中の localhost はそのコンテナ自身を指すからです。

なお、Docker Compose は現在 docker compose(スペース区切りのCLIプラグイン)として使うのが標準で、ファイル先頭の version: 指定は不要になっています(書くと警告が出る場合があります)。細部はDockerのバージョンにより異なるため、以下のイメージのタグや挙動は執筆時点のものとして読んでください(2026年10月現在)。

手順1:作業フォルダと .env を用意する

まずプロジェクト用のフォルダを作り、パスワードなどを .env に分けます。Composeは同じフォルダにある .env を読み込み、compose.yaml 内の ${変数名} に展開します。

mkdir wp-local && cd wp-local
mkdir -p wp-content/themes wp-content/plugins mu-plugins
# .env(ローカル専用のダミー値。本番の値は使わない)
DB_NAME=wordpress
DB_USER=wp_user
DB_PASSWORD=change-me-local
DB_ROOT_PASSWORD=change-me-root
WP_PORT=8080

.env はGitにコミットしないよう .gitignore に入れておきます。ローカル用とはいえ、本番と同じパスワードを使い回すのは避けてください。

手順2:compose.yaml を書く

services:
  db:
    image: mariadb:11
    restart: unless-stopped
    environment:
      MARIADB_DATABASE: ${DB_NAME}
      MARIADB_USER: ${DB_USER}
      MARIADB_PASSWORD: ${DB_PASSWORD}
      MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    restart: unless-stopped

  mailpit:
    image: axllent/mailpit
    restart: unless-stopped
    ports:
      - "127.0.0.1:8025:8025"

  wordpress:
    image: wordpress:php8.3-apache
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    ports:
      - "127.0.0.1:${WP_PORT}:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_NAME: ${DB_NAME}
      WORDPRESS_DB_USER: ${DB_USER}
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
      WORDPRESS_DEBUG: "1"
      WORDPRESS_CONFIG_EXTRA: |
        define( 'WP_REDIS_HOST', 'redis' );
        define( 'WP_ENVIRONMENT_TYPE', 'local' );
    volumes:
      - wp_core:/var/www/html
      - ./wp-content/themes:/var/www/html/wp-content/themes
      - ./wp-content/plugins:/var/www/html/wp-content/plugins
      - ./mu-plugins:/var/www/html/wp-content/mu-plugins

  wpcli:
    image: wordpress:cli
    user: "33:33"
    depends_on:
      db:
        condition: service_healthy
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_NAME: ${DB_NAME}
      WORDPRESS_DB_USER: ${DB_USER}
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
    volumes:
      - wp_core:/var/www/html
      - ./wp-content/themes:/var/www/html/wp-content/themes
      - ./wp-content/plugins:/var/www/html/wp-content/plugins
      - ./mu-plugins:/var/www/html/wp-content/mu-plugins
    profiles: ["tools"]

  phpmyadmin:
    image: phpmyadmin
    environment:
      PMA_HOST: db
    ports:
      - "127.0.0.1:8081:80"
    profiles: ["tools"]

volumes:
  db_data:
  wp_core:

この構成でのポイントを順に説明します。

起動順はヘルスチェックで待つ。 depends_on に名前を書くだけでは「DBコンテナが起動した」ことしか待たず、MariaDBが接続を受け付ける前にWordPressが接続しにいき、「データベース接続確立エラー」が出ることがあります。condition: service_healthy とDB側の healthcheck を組み合わせると、DBが応答できる状態になってからWordPressを起動します。healthcheck.sh はMariaDB公式イメージに同梱されているスクリプトですが、古いタグには含まれていないため、エラーになる場合はイメージのタグを確認してください。

ポートは 127.0.0.1 に限定する。 "8080:80" と書くと、同じネットワーク(社内LANやカフェのWi-Fi)の他の端末からも開けてしまいます。ローカル開発なら 127.0.0.1: を付けて自分のPCからだけ見えるようにしておくのが安全です。DBとRedisはポートを公開していません。コンテナ同士はCompose内部のネットワークで通信できるので、外に開ける必要がないからです。

自分が編集するものだけをバインドマウントする。 WordPressのコア一式は名前付きボリューム wp_core に置き、テーマ・プラグイン・mu-pluginsだけを手元のフォルダと共有しています。コアまで手元に展開すると、WindowsやmacOSではファイル同期の負荷で表示が遅くなりやすいためです。Windowsの場合、プロジェクトをWSL2側のLinuxファイルシステムに置くと速度が改善することが多いです。

WP-CLIとphpMyAdminは profiles で普段は起動しない。 profiles: ["tools"] を付けたサービスは docker compose up では起動せず、明示的に呼んだときだけ動きます。

手順3:起動してインストールする

docker compose up -d
docker compose ps

docker compose ps で db の状態が healthy になり、wordpress が起動していれば http://localhost:8080 を開いてインストール画面に進めます。WP-CLIでインストールする場合は次のとおりです。

docker compose run --rm wpcli wp core install \
  --url="http://localhost:8080" \
  --title="Local Dev" \
  --admin_user="admin" \
  --admin_email="admin@example.com" \
  --prompt=admin_password

--prompt=admin_password を使うと、パスワードを対話入力にでき、シェルの履歴に残りません。

wpcliサービスに user: "33:33" を指定しているのは権限のずれを防ぐためです。wordpress:cli イメージはAlpine Linuxベースで、Debianベースの wordpress イメージとは www-data のユーザーIDが異なります。指定しないと、WP-CLIで入れたプラグインのファイルをWordPress側が書き換えられない、といった症状が出ます。イメージの中身は更新で変わる可能性があるので、権限エラーが出たら docker compose exec wordpress id www-data でIDを確認して合わせてください。

手順4:Redisをオブジェクトキャッシュとしてつなぐ

WORDPRESS_CONFIG_EXTRA で WP_REDIS_HOST を redis(サービス名)に設定済みなので、あとはプラグインを入れて有効化するだけです。

docker compose run --rm wpcli wp plugin install redis-cache --activate
docker compose run --rm wpcli wp redis enable
docker compose run --rm wpcli wp redis status

ここで使っているのは「Redis Object Cache」プラグインで、wp redis コマンドはこのプラグインが追加するものです。status で接続状態を確認でき、つながらない場合はホスト名の設定が 127.0.0.1 のままになっていないかを最初に疑ってください。

手順5:送信メールをMailpitで受け止める

ローカルで問い合わせフォームやパスワードリセットを試すと、WordPressはメールを送ろうとします。本物のメールが外に出ると困るので、mu-pluginでSMTPの送信先をMailpitに向けます。

<?php
// mu-plugins/local-mailpit.php
// ローカル環境だけで、wp_mail() の送信先を Mailpit に向ける
if ( 'local' === wp_get_environment_type() ) {
	add_action( 'phpmailer_init', function ( $phpmailer ) {
		$phpmailer->isSMTP();
		$phpmailer->Host     = 'mailpit';
		$phpmailer->Port     = 1025;
		$phpmailer->SMTPAuth = false;
	} );
}

phpmailer_init はWordPressコアのアクションで、wp_mail() が送信する直前のPHPMailerオブジェクトを受け取れます。wp_get_environment_type() で local のときだけ有効にしているので、このファイルを誤って本番に持っていっても送信先は変わりません。メールは http://localhost:8025 のMailpit画面で確認できます。

よくあるつまずきと確認方法

  • 「データベース接続確立エラー」:WORDPRESS_DB_HOST が db になっているか、docker compose logs db で初期化が終わっているかを確認します。.env のパスワードを途中で変えた場合、既存の db_data ボリュームには古いパスワードが残っているため、初期化し直す必要があります。
  • ポートが使用中で起動しない:別のアプリが8080番を使っています。.env の WP_PORT を変えて起動し直します。サイトURLもポートを含むので、インストール後に変える場合は wp search-replace が必要です。
  • プラグインの更新で権限エラー:前述のユーザーIDのずれです。
  • 作り直したい:docker compose down はコンテナを消すだけで、DBとコアのボリュームは残ります。docker compose down -v はボリュームまで削除し、DBの中身も消えます。残したいデータがあれば先に wp db export でSQLを書き出してください。

まとめ

  • 複数サービス構成では、接続先は localhost ではなくサービス名(db、redis、mailpit)
  • depends_on は condition: service_healthy とヘルスチェックの組み合わせで「使える状態」まで待つ
  • ポートは 127.0.0.1 に限定し、DBやRedisは外に公開しない
  • コアは名前付きボリューム、編集するテーマ・プラグインだけをバインドマウントすると扱いやすい
  • WP-CLIコンテナはユーザーIDを合わせ、メールはMailpitで受け止めて外に出さない
  • down -v はデータも消えるので、作り直す前にエクスポートしておく

お気軽にご相談ください

お見積りへ お問い合わせへ
▲