🐳

GitHub ActionsでNext.js 13のDockerコンテナーにNEXT_PUBLIC_を渡す

2023/05/28に公開

はじめに

最近ちょくちょく触っているNext.js 13アプリをクラウドにデプロイしていたところ

  • NEXT_PUBLIC_変数が空になる
  • クラウド環境のサーバーインスタンスに該当の環境変数は設定できている
  • ローカル環境ではproductionビルドで同じ環境変数名と値を設定していて問題ない

という事案に遭遇しました。
この記事では、その原因~おおまかな解決手順を記したいと思います。

前提

  • Next.js 13アプリはDockerfileを構成してある
  • GitHub ActionsでCI/CDパイプラインを構築してありNext.js 13アプリはコンテナーアプリとしてクラウドにデプロイされる
  • 環境変数はCI/CDパイプライン内にてGitHubリポジトリーのvariables/secretsを読み込んで設定している

原因

  • ビルド時ではなくデプロイ時に環境変数を設定していたため

NEXT_PUBLIC_環境変数/その他環境変数を設定すべきタイミングの違い

公式ドキュメントをちゃんと読めば書いてあったのですが(💦)、Next.js現行バージョン(13.4)ではクライアントに渡すNEXT_PUBLIC_変数はビルド時に環境変数からJavaScriptコード内に埋め込まれるようです。そのため、CI/CDパイプラインも以下のような構成にする必要がありました。

build(NEXT_PUBLIC_環境変数はここで設定しておく必要がある)

deploy(その他環境変数はここで設定しても基本問題なし)

公式ドキュメント
https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables#exposing-environment-variables-to-the-browser

おおまかな解決手順

1. workflowsからsecretsをDockerfileに渡す

以下のように、docker/build-push-action@v3であればwith.build-argssecretsをビルド引数に渡すことができます。
.github/workflows/release_example.yml

jobs:
  build:
    runs-on: 'ubuntu-latest'

    steps:
    # ...
    - name: Build and push container image to registry
      uses: docker/build-push-action@v3
      with:
        push: true
        tags: examplecr/exampleuser/exampleimage:${{ github.sha }}
        file: ./Dockerfile
        build-args: |
          "NEXT_PUBLIC_FOO=${{ secrets.NEXT_PUBLIC_FOO }}"

2. Dockerfileで.env.productionを生成する

そして以下のように、ARGで受け取った値をビルド前に.env.productionへ書き出しておくようにします。すると、Next.js 13がビルド時にNEXT_PUBLIC_を読み込み、クライアントに渡るJavaScriptコードにも埋め込まれるようになりました。
Dockerfile

# Create .env.production
ARG NEXT_PUBLIC_FOO
RUN touch .env.production
RUN echo "NEXT_PUBLIC_FOO=$NEXT_PUBLIC_FOO" >> .env.production
RUN cat .env.production

# Build
RUN npm run build

以上です。もしどなたかの参考になることがあれば幸いです。

Discussion