Closed7

Cloud Run(サイドカー)でnginx + php-fpmの環境を作ってCloud Build対応させたメモ

Yusuke KawabataYusuke Kawabata

まず、サイドカー版Cloud Runですが、いままで1コンテナで頑張っていたときは、nginx+php-fpmだとコールドスタート時に500エラーが起きる問題がありました。今だからわかるんですがnginxが1秒くらいで起動して、php-fpmは3秒くらい起動にかかるのでその間エラーになるんですよね。

それが今回はコンテナ間の依存関係が指定できるので、php-fpmの9000番ポートの疎通が確認出来たらnginxもアクティブになる。という構成ができるようになりました。

Yusuke KawabataYusuke Kawabata

最終的に出来上がったのはこちら。YAMLで以下のようなことが設定されている

  • 利用するコンテナ定義
  • インスタンス定義(gen2とか最小インスタンス、最大インスタンス)
  • CloudSQLへの接続定義
  • SecretManagerのファイルパスへのマウント
  • それぞれのコンテナのポート
  • 起動時の依存関係

https://gist.github.com/ku-suke/fb049e76b232cb9258618a3322a77719#file-service-yaml

envがちょろっとしか書いてないのはサンプルで、下にあるけど最終的に.envをまるっとSecretManagerにつっこんでビルド時に渡すようにしました。どうもディレクトリマウント方式だとすでにあるアプリケーションフォルダにマウントするのは難しいようで、ビルド時に吐き出しています。

Yusuke KawabataYusuke Kawabata

nginxのコンテナはシンプル。/var/publicをドキュメントルートにして、そこに静的ファイルだけコピーしてindex.phpを消してます(雑)

FROM nginx:latest

# デフォルトのサイト設定を無効化し自前の設定をコピー
RUN mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
COPY ./docker-nginx/nginx.conf /etc/nginx/nginx.conf

COPY ./public /var/public
RUN rm -rf /var/public/*.php

# nginxユーザで実行
RUN chown -R 101:0 /var/cache/nginx \
    && chmod -R g+w /var/cache/nginx \
    && chown -R 101:0 /var/public \
    && chmod -R g+w /var/public

USER 101
Yusuke KawabataYusuke Kawabata

php-fpmのほうもそんな難しいことをやっていませんが、apcuとsentry用にexcimerは導入しています。ポイントとしては、pathがそのまま飛んでくるので、/var/public/index.phpで受けるようにするくらいですかね。

FROM php:8.2-fpm-bullseye

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

RUN apt-get update \
    && apt-get install -y  --no-install-recommends \
    git \
    zip \
    unzip \
    libzip-dev \
    libpng-dev \
    libpq-dev \
    libfreetype6-dev \
    libjpeg-dev \
    libonig-dev \
    libgmp-dev \
    libmagickwand-dev \
    && pecl install imagick apcu excimer \
    && docker-php-ext-configure gd \
    --with-freetype=/usr/include/ \
    --with-jpeg=/usr/include \
    && docker-php-ext-install -j$(nproc) bcmath exif gmp intl gd opcache pdo pdo_mysql mysqli zip \
    && docker-php-ext-enable imagick apcu excimer \
    && docker-php-source delete \
    && rm -rf /var/lib/apt/lists/*

ADD ./docker-nginx/php.ini /usr/local/etc/php/

# 記事においてはマルチステージビルドにしてない版を載せます
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# nginx自身のパスが飛んでくるので、合わせる
COPY ./ /var/
WORKDIR /var 
RUN composer install -o --apcu-autoloader; \
    chmod -R 777 /var/storage; \
    chmod -R 777 /var/bootstrap/cache; 
Yusuke KawabataYusuke Kawabata

そして、これらのコンテナをArtifact RegistryにPushします。

docker build -t asia-northeast1-docker.pkg.dev/プロジェクト名/リポジトリ名/nginx:latest
docker push asia-northeast1-docker.pkg.dev/プロジェクト名/リポジトリ名/nginx:latest

docker build -t asia-northeast1-docker.pkg.dev/プロジェクト名/リポジトリ名/php-fpm:latest
docker push asia-northeast1-docker.pkg.dev/プロジェクト名/リポジトリ名/php-fpm:latest

https://cloud.google.com/artifact-registry/docs/docker/store-docker-container-images?hl=ja

latestになってる部分は微妙なので後述します。

あとはデプロイするだけです!

gcloud run service replace service.yaml
Yusuke KawabataYusuke Kawabata

さて、うまくいったらお次はCloudBuildです。ここは試行錯誤しすぎて途中のエラー回避などは忘れてしまったのですが、つまずいたのは以下のような点です。

  • そもそも実行されない
    • secretなどのパス記述ミスで権限がついてないけど権限がないって言われ続けた
  • Pushできない
    • Cloud Buildの権限不足
  • Secret Managerから.envをコピーしようとするも一生入らない
    • パス間違い。コピー元は / で作業してたにのコピー先に合わせて/varに設置してた。あとSecretManagerのアクセサー権限がなかった。あと""で囲ってなかったので改行コードが消えた。
  • デプロイ成功するも内容が更新されない
    • Cloud Runのyamlは latest など文字列でしか変更を見ないので、コンテナの中身が変わっていようとも同じタグでは取得しなおしてくれない

そんなこんなで、sedを入れたり頑張りました。

steps:
# install dependency
- name: node
  entrypoint: npm
  args: ['install']
- name: node
  entrypoint: npm
  args: ['run', 'production']
# Build the nginx image(この段階で↑でビルドしたjsもコピーされる)
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', 
  '-t', 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/リポジトリ名/nginx:$COMMIT_SHA', 
  '-t', 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/リポジトリ名/nginx:latest', 
  '-f', 'Dockerfile.nginx', 
  '.']
# Push the nginx image to Container Registry
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', '-a', 'asia-northeast1-docker.pkg.dev/dev/リポジトリ名/nginx']
# export env from secrets
- name: 'gcr.io/cloud-builders/docker'
  entrypoint: 'bash'
  args: ['-c', 'echo "$$SECENV" > .env']
  secretEnv: ['SECENV']
# Build the php-fpm image
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', 
  '-t', 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/リポジトリ名/php-fpm:$COMMIT_SHA', 
  '-t', 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/リポジトリ名/php-fpm:latest', 
  '-f', 'Dockerfile.php-fpm', 
  '.']
# Push the php-fpm image to リポジトリ名 Registry
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', '-a', 'asia-northeast1-docker.pkg.dev/dev/リポジトリ名/php-fpm']
# Replace cloudrun yaml for image tag
- name: 'gcr.io/cloud-builders/gcloud'
  id: Generate manifest
  entrypoint: /bin/bash
  args: ['-c', 'sed -ri "s/:latest/:$COMMIT_SHA/g" service.yaml']
# Deploy リポジトリ名 image to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: gcloud
  args: ['run', 'services', 'replace', 'service.yaml']
availableSecrets:
  secretManager:
  - versionName: projects/プロジェクトID/secrets/SECRET名/versions/latest
    env: 'SECENV'
このスクラップは2023/07/02にクローズされました