🙆‍♀️

Laravel + Nginx アプリケーションを GCP にデプロイする

に公開

目的

GCP (Google Cloud Platform) 上での Laravel アプリケーションのデプロイに関する情報はまだ少ないため、私自身の経験と構築手順を共有することを目的としています。特に Nginx を利用したデプロイ方法に焦点を当て、同じ課題を持つ開発者の一助となれば幸いです。

やったこと

1.GCP ネットワークの構築

Cloud Run と Cloud SQL が連携するためのネットワーク基盤を構築しました。

  • デフォルト VPC ネットワークの利用: GCP プロジェクトで提供されるデフォルトの VPC ネットワークを活用。
  • プライベート IP 接続の確立:
    セキュリティとベストプラクティスのため、Cloud Run と Cloud SQL 間はプライベート IP 接続が必須。パブリック IP はファイアウォールで制限されます。
    Cloud SQL 接続: VPC と Cloud SQL 間でPrivate Service Connectionを設定し、プライベート IP でアクセス可能にしました。
  • Cloud Run からのアクセス: Cloud Run が VPC 内の Cloud SQL にアクセスできるよう、Serverless VPC Access コネクタを作成し、Cloud Run サービスに割り当てました。
    これにより、Laravel + Nginx アプリケーションが Cloud SQL と安全に連携できるネットワーク環境が整いました。

2. Cloud Build を用いたコンテナイメージのビルドとプッシュ

Cloud Build を活用し、コンテナイメージのビルドと Artifact Registry へのプッシュを行いました。今回は、PHP と Nginx を一つのコンテナに統合しています。

Cloud Build の設定ファイル (cloudbuild.yaml)
プロジェクトルートに以下の cloudbuild.yaml を配置し、Docker イメージのビルドと Artifact Registry へのプッシュのステップを定義しました。

# cloudbuild.yaml
steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: [
      'build', '--no-cache',
      '-t', 'YOUR_REGION-docker.pkg.dev/${PROJECT_ID}/YOUR_REPOSITORY_NAME/YOUR_IMAGE_NAME:latest',
      '-f', 'Dockerfile.unified', '.'
    ]
  - name: 'gcr.io/cloud-builders/docker'
    args: [
      'push', 'YOUR_REGION-docker.pkg.dev/${PROJECT_ID}/YOUR_REPOSITORY_NAME/YOUR_IMAGE_NAME:latest'
    ]
images:
  - 'YOUR_REGION-docker.pkg.dev/${PROJECT_ID}/YOUR_REPOSITORY_NAME/YOUR_IMAGE_NAME:latest'

YOUR_REGION, YOUR_REPOSITORY_NAME, YOUR_IMAGE_NAME は、ご自身の環境に合わせて置き換えてください。

ビルドの実行と Artifact Registry へのプッシュ
gcloud builds submit --config cloudbuild.yaml . コマンドでイメージをビルドし、Artifact Registry へプッシュしました。

3. 統合コンテナの Dockerfile (Dockerfile.unified)

PHP-FPM と Nginx を単一のコンテナで動作させるための Dockerfile.unified を作成しました。

# Dockerfile.unified
FROM php:8.1-fpm-buster

ENV COMPOSER_ALLOW_SUPERUSER=1 \
    COMPOSER_HOME=/composer

RUN apt-get update && \
    apt-get -y install --no-install-recommends \
    git unzip libzip-dev libicu-dev libonig-dev \
    nginx supervisor && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    docker-php-ext-install intl pdo_mysql zip bcmath

COPY --from=composer:2.2 /usr/bin/composer /usr/bin/composer
COPY ./infra/nginx/default.conf /etc/nginx/conf.d/default.conf
COPY ./infra/php/php.ini /usr/local/etc/php/php.ini
COPY ./infra/php/zz-fpm.conf /usr/local/etc/php-fpm.d/zz-fpm.conf
COPY ./infra/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf

WORKDIR /data
COPY ./src /data
RUN composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader

RUN rm -f /etc/nginx/sites-enabled/default
RUN ln -s /etc/nginx/conf.d/default.conf /etc/nginx/sites-enabled/default
RUN mkdir -p /var/log/nginx && chown -R www-data:www-data /var/log/nginx
RUN chown -R www-data:www-data /data/storage /data/bootstrap/cache
RUN chmod -R 775 /data/storage /data/bootstrap/cache

EXPOSE 80
CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

4. Nginx 設定ファイル (infra/nginx/default.conf)

アプリケーションへのリクエストを処理し、PHP-FPM にルーティングするための Nginx 設定です。

# infra/nginx/default.conf
server {
    listen 80;
    root /data/public;
    index index.php;
    charset utf-8;
    location / { try_files $uri $uri/ /index.php?$query_string; }
    location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; include fastcgi_params; }
    # その他のセキュリティヘッダーやログ設定
}

Nginx 設定のポイント:

  • listen 80;: コンテナ内の Nginx がポート 80 でリクエストを受け付けます。
  • root /data/public;: Laravel の public ディレクトリを Web ルートに設定。
  • fastcgi_pass 127.0.0.1:9000;: 同じコンテナ内の PHP-FPM にリクエストを転送します。

5. PHP 設定ファイル (infra/php/php.ini)

PHP の基本的な動作設定を定義します。

; infra/php/php.ini
upload_max_filesize = 128M
post_max_size = 128M
memory_limit = 256M
date.timezone = Asia/Tokyo
display_errors = On

6. Supervisor 設定ファイル (infra/supervisor/supervisord.conf)

Supervisor は、単一コンテナ内で Nginx と PHP-FPM の両プロセスを管理し、コンテナ起動時に両サービスが適切に起動・維持されるようにします。

; infra/supervisor/supervisord.conf
[supervisord]
nodaemon=true

[program:php-fpm]
command=/usr/local/sbin/php-fpm --nodaemonize --allow-to-run-as-root
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr

[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr

Supervisor 設定のポイント:

  • nodaemon=true: Supervisor 自体をフォアグラウンドで実行し、Docker コンテナのメインプロセスとして機能させます。
  • [program:php-fpm] と [program:nginx]: それぞれのサービスを定義し、自動起動と再起動を設定。
  • stdout_logfile / stderr_logfile: 各プロセスのログをコンテナログとして出力されるよう設定。

7. Cloud SQL のセットアップと Cloud Run へのデプロイ

コンテナイメージ準備後、Cloud SQL をセットアップし、コンテナイメージを Cloud Run にデプロイして連携させました。これらの設定は主に **GCP コンソール(GUI)**を通じて行いました。

Cloud SQL (MySQL) インスタンスの作成と設定
Laravelのデータストアとして Cloud SQL for MySQL を利用しました。

  • インスタンス作成: GCP コンソールで新規 MySQL インスタンスを作成し、プライベート IP アドレスを有効にしました。
  • プライベート IP 設定: VPC ネットワークにプライベートサービス接続を設定。
  • データベースとユーザー作成: アプリケーション用のデータベースとユーザーを作成し、権限を付与。

Cloud Run へのデプロイと Cloud SQL との連携
ビルドした統合コンテナイメージを Cloud Run にデプロイし、Cloud SQL との接続を設定しました。

  • Cloud Run サービス作成: GCP コンソールで新規サービスを作成し、Artifact Registry のコンテナイメージを指定。
  • VPC Connector の設定: Cloud Run と Cloud SQL をプライベート IP で接続するため、Serverless VPC
  • Cloud Run サービスの編集にてアウトバウンド トラフィック用の VPC に接続するチェックをつけてdefaultのVPCにネットワークを割り当てました。
  • 環境変数の設定: データベース接続に必要な環境変数 (DB_CONNECTION, DB_HOST など) を Cloud Run に設定。
  • 自動スケーリングとリソース設定: 必要に応じてインスタンス数やリソース設定を調整。

これらの設定により、Cloud Run 上で Laravel + Nginx アプリケーションが起動し、プライベートネットワーク経由で Cloud SQL データベースと安全に通信できるようになりました。

Discussion