DrupalサイトのDocker ローカル環境を作る

Drupal 11 を動かすための php-fpm / nginx / MySQL の最小3点セットを作り、コンテナ起動まで行います。
プロジェクトパス:~/projects/rikka/(適宜ご自身の環境に読み替えて下さい)

当初はLightsailで環境構築を行い、スケールした際にはEC2に移行をするように考えていますが、LightsailのBitmaniイメージはApache前提で構成されています。私もいま仕事で担当しているWEBサイトはApacheで動いていますし、これまでもApacheの経験しかありません。

Apacheとnginxの比較

Apache

歴史が長く、設定例が豊富
htaccess を利用でき、共有ホスティング向き
Bitnami / cPanel / XAMPP など「オールインワンパッケージ」では Apache が多い

nginx

軽量・高パフォーマンス(特に静的ファイル配信・同時接続数に強い)
.htaccess が無いのでセキュリティリスクを減らせる(設定は一元管理)
Drupal コミュニティの推奨構成例(公式 docs でも紹介)に nginx が含まれる
近年は「PHP-FPM + nginx」という組み合わせがモダンなデフォルトに近い

RIKKAのサイトは将来的にEC2やCloudFrontを導入してスケールする際、nginxの方が高負荷耐性た高いことから、スケーラブルな運用を見据えてnginxを選択しました。

Drupal 11 スケルトン & Drush 導入、Git 初期化

Bash
# 1) ルートを用意し、そこへ移動
mkdir -p ~/projects/rikka && cd ~/projects/rikka

# 2) Drupal 11 公式推奨テンプレートでスケルトン作成
#    (web/ がドキュメントルートになる構成)
composer create-project drupal/recommended-project:^11.0 .

# 3) Drush 13 をプロジェクト依存で導入(Drupal 11 対応)
composer require drush/drush:^13

# 4) Git 初期化
git init
git add -A
git commit -m "chore: scaffold Drupal 11 project and add Drush 13"

Config Sync を web ルート外へ固定 & settings 準備

Bash
# 1) 設定保存ディレクトリ(web/ の外)を作成
mkdir -p config/sync
touch config/sync/.gitkeep
git add config/sync/.gitkeep
git commit -m "chore: add config/sync directory outside web root"

# 2) settings.php / settings.local.php を準備
cp web/sites/default/default.settings.php web/sites/default/settings.php
cp web/sites/example.settings.local.php web/sites/default/settings.local.php

web/sites/default/settings.php の末尾付近に 以下を追記してください(元々入っていてもコメントアウトされていると思うのでそもままコピペで大丈夫です)

PHP
// === Config sync directory (outside webroot) ===
$settings['config_sync_directory'] = $app_root . '/../config/sync';

// === Trusted host patterns(後日、本番/検証ドメインを追加)===
$settings['trusted_host_patterns'] = [
  '^localhost$',
  '^[a-z0-9\-\.]+\.localhost$',
  '^stg\.rikkainc\.jp$',
];

// ローカル専用設定を読み込み(存在する場合)
if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) {
  include $app_root . '/' . $site_path . '/settings.local.php';
}

.env(ローカル実体)を作成

Bash
cat > .env <<'EOF'
# === App ===
APP_ENV=local
APP_DEBUG=true

# === Database (MySQL 8.0) ===
DB_HOST=db
DB_PORT=3306
DB_NAME=drupal
DB_USER=drupal
DB_PASS=drupal

# === AWS / S3(本番で使用。ローカルでは未使用)===
AWS_REGION=ap-northeast-1
S3_BUCKET=
S3_PREFIX=public
CLOUDFRONT_DOMAIN=
EOF

# 共有用サンプルも残す(任意)
cp .env .env.sample
git add .env.sample
git commit -m "chore: add .env.sample for future Docker/Prod configuration"

docker-compose.yml を作成

Bash
# docker-compose.yml(~/projects/rikka/ 直下)
name: rikkainc-drupal
services:
  db:
    image: mysql:8.0
    command: ["--default-authentication-plugin=mysql_native_password"]
    environment:
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASS}
      MYSQL_ROOT_PASSWORD: root
    ports:
      - "3307:3306"   # 他のMySQLと衝突回避。必要に応じて変更可
    volumes:
      - dbdata:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-p${DB_PASS}"]
      interval: 5s
      timeout: 3s
      retries: 20

  php:
    build:
      context: ./.docker/php
      dockerfile: Dockerfile
    volumes:
      - .:/var/www/html
    working_dir: /var/www/html
    depends_on:
      db:
        condition: service_healthy

  nginx:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"
    volumes:
     

Composerは既に導入されている前提ですが、もし未導入であれば導入して下さい

Drush 導入と Git 初期化(~/projects/rikka/)

Drupal 11 対応の Drush 13 をプロジェクト依存で追加し、Git 管理を開始します。

Bash
cd ~/projects/rikka

# 1) Drush 13(Drupal 11 対応)をプロジェクト依存で追加
composer require drush/drush:^13

# 2) Git 初期化と初回コミット
git init
git add -A
git commit -m "chore: scaffolded Drupal 11 project and add Drush 13"

Bash
# Drush バージョン確認(出力が 13.x であること)
vendor/bin/drush --version

動作確認

composer require drush/drush:^13の実行した際に、Drupalは依存が多いため、初回requireは数分かかることがあります。
5分程度経過しても全く反応が返ってこなければ下記を試してみます

Bash
composer clear-cache

Composer のキャッシュをクリア

Bash
composer require drush/drush:^13 -vvv

再実行(-vvv オプションで進捗やどこで止まっているかが見えます)

Bash
composer self-update

Composer 自体のアップデート(バージョンが古いと依存解決に時間がかかる場合があります)

Drush 追加の検証と初回コミット

Bash
cd ~/projects/rikka
vendor/bin/drush --version
# => Drush Commandline Tool 13.x (13系であること)

Drush の導入確認

Git 初期化とコミット

Bash
git init
git add -A
git commit -m "chore: scaffolded Drupal 11 project and add Drush 13"

リポジトリ未初期化の場合

Bash
git add -A
git commit -m "chore: add Drush 13"

すでに Git 初期化済みなら差分だけコミット

Docker 定義の作成と起動(インストーラ画面の表示まで)

MySQL 8.0 / PHP 8.3-FPM / nginx の3コンテナを用意し、http://localhost:8080 で Drupal インストーラ画面が表示されるところまで進めます

Config Sync の保存先を web ルート外へ固定

Bash
cd ~/projects/rikka

# 設定ディレクトリ
mkdir -p config/sync
touch config/sync/.gitkeep

# settings.php / settings.local.php の用意(未作成なら)
[ -f web/sites/default/settings.php ] || cp web/sites/default/default.settings.php web/sites/default/settings.php
[ -f web/sites/default/settings.local.php ] || cp web/sites/example.settings.local.php web/sites/default/settings.local.php

web/sites/default/settings.php の末尾付近に 以下を追記(既にあれば重複不要)

PHP
// === Config sync directory (outside webroot) ===
$settings['config_sync_directory'] = $app_root . '/../config/sync';

// === Trusted host patterns(後で本番/検証ドメインを追加)===
$settings['trusted_host_patterns'] = [
  '^localhost$',
  '^[a-z0-9\-\.]+\.localhost$',
  '^stg\.rikkainc\.jp$',
];

// ローカル専用設定を読み込み(存在する場合)
if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) {
  include $app_root . '/' . $site_path . '/settings.local.php';
}

.env(ローカル実体)を作成

Bash
cd ~/projects/rikka

cat > .env <<'EOF'
# === App ===
APP_ENV=local
APP_DEBUG=true

# === Database (MySQL 8.0) ===
DB_HOST=db
DB_PORT=3306
DB_NAME=drupal
DB_USER=drupal
DB_PASS=drupal

# === AWS / S3(本番で使用。ローカルでは未使用)===
AWS_REGION=ap-northeast-1
S3_BUCKET=
S3_PREFIX=public
CLOUDFRONT_DOMAIN=
EOF

# 共有用のサンプルも残す(任意)
cp .env .env.sample

docker-compose.yml を作成

Bash
cat > docker-compose.yml <<'YML'
name: rikkainc-drupal
services:
  db:
    image: mysql:8.0
    command: ["--default-authentication-plugin=mysql_native_password"]
    environment:
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASS}
      MYSQL_ROOT_PASSWORD: root
    ports:
      - "3307:3306"   # 他のMySQLと衝突回避。必要に応じ変更可
    volumes:
      - dbdata:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-p${DB_PASS}"]
      interval: 5s
      timeout: 3s
      retries: 20

  php:
    build:
      context: ./.docker/php
      dockerfile: Dockerfile
    volumes:
      - .:/var/www/html
    working_dir: /var/www/html
    depends_on:
      db:
        condition: service_healthy

  nginx:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"
    volumes:
      - .:/var/www/html:ro
      - ./.docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - php

volumes:
  dbdata:
YML

PHP 用 Dockerfile を作成(必要拡張入り)

Bash
mkdir -p .docker/php
cat > .docker/php/Dockerfile <<'EOF'
FROM php:8.3-fpm

# 基本ツール・拡張
RUN apt-get update && apt-get install -y \
    git unzip libzip-dev libicu-dev libpng-dev libjpeg-dev libwebp-dev libfreetype6-dev libonig-dev libxml2-dev \
 && docker-php-ext-configure gd --with-jpeg --with-webp --with-freetype \
 && docker-php-ext-install -j$(nproc) pdo_mysql zip intl gd opcache exif \
 && rm -rf /var/lib/apt/lists/*

# 推奨 PHP 設定(最小限)
RUN { \
  echo "memory_limit=512M"; \
  echo "upload_max_filesize=64M"; \
  echo "post_max_size=64M"; \
  echo "max_execution_time=120"; \
  echo "opcache.enable=1"; \
  echo "opcache.validate_timestamps=1"; \
  echo "opcache.revalidate_freq=0"; \
} > /usr/local/etc/php/conf.d/z-drupal.ini

WORKDIR /var/www/html
EOF

nginx の仮想ホスト設定を作成

Bash
mkdir -p .docker/nginx
cat > .docker/nginx/default.conf <<'EOF'
server {
  listen 80;
  server_name localhost;

  root /var/www/html/web;
  index index.php index.html;

  # クリーンURLとフロントコントローラ
  location / {
    try_files $uri $uri/ /index.php?$query_string;
  }

  location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass php:9000;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param DOCUMENT_ROOT $document_root;
  }

  # セキュリティ(機微ファイル遮断)
  location ~* \.(yml|yaml|twig|tpl(\.php)?|log|sql|conf|inc|install|module|profile|po|sh|.*~|composer\.(json|lock))$ {
    deny all;
  }

  # 静的ファイルは短めにキャッシュ(ローカル)
  location ~* \.(css|js|jpg|jpeg|png|gif|webp|svg|ico)$ {
    try_files $uri =404;
    expires 1h;
    access_log off;
  }
}
EOF

コンテナをビルド・起動し、疎通確認

Bash
cd ~/projects/rikka

# 初回ビルド&起動
docker compose up -d --build

# 稼働確認
docker compose ps

# ブラウザで確認(macOS)
open http://localhost:8080

正常であれば Drupal のインストーラ画面(/core/install.php に誘導)が表示されます。
ここではまだインストールは行いません(次ステップで Drush による無人インストールを行います)

Drush の実行確認(php コンテナ内)

Bash
# php コンテナに接続
docker compose exec php bash

# Drush 13 の動作確認
vendor/bin/drush --version

# Drupal プロジェクトが見えているか
ls -la web/ core/ modules/ themes/
exit

Drush で Drupal を無人インストール(ローカル)

目的:Docker 内から Drush を使って、DB 接続~サイト初期化まで一括で実行します。
前提:docker compose up -d 済み、DB_HOST=db / DB_NAME=drupal / DB_USER=drupal / DB_PASS=drupal(.env と compose の定義どおり)

権限の事前準備(files ディレクトリ)

Bash
cd ~/projects/rikka
docker compose exec php bash

# 公開ファイル保存先を用意
mkdir -p web/sites/default/files
chown -R www-data:www-data web/sites/default/files

# 念のため settings.php が存在することだけ確認
ls -l web/sites/default/settings.php

# 以降のコマンドはコンテナ内で実行します

無人インストール実行(標準プロファイル / 日本語)

Bash
# サイト名などは任意で変更可(例はローカル用)
vendor/bin/drush site:install standard \
  --db-url="mysql://drupal:drupal@db:3306/drupal" \
  --site-name="RIKKA (Local)" \
  --account-name="admin" \
  --account-pass="Admin@local123" \
  --account-mail="kurosawa@rikkainc.jp" \
  --locale=ja \
  -y

standard は Drupal 11 で一般的な初期構成です。
–db-url は compose の MySQL(サービス名 db)へ接続します。
–locale=ja で日本語化を同時適用します。
パスワードはローカル用の仮の値です。後で変更可能です。

動作確認と管理ログイン

Bash
# ステータス確認
vendor/bin/drush status

# キャッシュクリア(完了メッセージが出ていれば省略可)
vendor/bin/drush cr

# 管理者ワンタイムログインURL(必要に応じて)
vendor/bin/drush uli

ブラウザで http://localhost:8080 を開き、フロントページと /user/login(または drush uli のURL)から管理画面に入れることを確認します。

Drush による無人インストール(DB接続・管理者作成)

目的:Docker 内から Drush を用いて、DB 接続確認 → Drupal の初期インストールを一気に完了させます。
前提:docker compose up -d 済み、.env は DB_HOST=db / DB_NAME=drupal / DB_USER=drupal / DB_PASS=drupal のまま。

コンテナに入る

Bash
cd ~/projects/rikka
docker compose exec php bash

Drush で無人インストール(標準 / 日本語)

Bash
# 無人インストール(サイト名・メールは適宜調整可)
vendor/bin/drush site:install standard \
  --db-url="mysql://drupal:drupal@db:3306/drupal" \
  --site-name="RIKKA" \
  --account-name="admin" \
  --account-pass="Admin@local123" \
  --account-mail="test@test.jp" \
  --locale=ja \
  -y

DB を手動で作成する

Bash
# php コンテナ内から
mysql -h db -u drupal -pdrupal --skip-ssl -e "CREATE DATABASE drupal CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"

Drush でインストール実行

Bash
vendor/bin/drush site:install standard \
  --db-url="mysql://drupal:drupal@db:3306/drupal" \
  --site-name="RIKKA" \
  --account-name="account-name=" \
  --account-pass="account-pass" \
  --account-mail="test@test.com" \
  --locale=ja \
  -y

動作確認と後片付け

Bash
# ステータス
vendor/bin/drush status

# キャッシュクリア(任意)
vendor/bin/drush cr

# 管理者ログインURL(必要時)
vendor/bin/drush uli

ブラウザで http://localhost:8080 を開き、サイトトップが表示できることを確認してください

Config Sync の初回エクスポート

Bash
# まだ php コンテナ内なら抜けてもOK
exit

# 設定を書き出し
docker compose exec php bash -c "vendor/bin/drush config:export -y"

# ホスト側でコミット
cd ~/projects/rikka
git add config/sync
git commit -m "chore(config): initial export to config/sync"

Drush による無人インストールが成功し、Drupal サイトがローカルで稼働
Config Sync が web 外に正しく出力され、YAML が多数生成されていることを確認

PAGE TOP