🔐

Next.jsとSentryの連携でSENTRY_AUTH_TOKENをSecret mountで安全に扱う方法

に公開

はじめに

Next.jsアプリケーションでエラー監視のためにSentryを導入する際、ソースマップをSentryにアップロードすることで本番環境でのエラーを正確にデバッグできるようになります。しかし、このプロセスにはSENTRY_AUTH_TOKENという秘密情報が必要になります。この記事では、DockerのSecret mountを使ってSENTRY_AUTH_TOKENを安全に扱う方法を紹介します。

前提知識

  • Next.jsの基本的な知識
  • Sentryの基本的な理解
  • Dockerの基本的な使い方

なぜSecret mountが必要なのか

Sentryにソースマップをアップロードするには、通常以下のように環境変数を設定します:

SENTRY_AUTH_TOKEN=your_auth_token
SENTRY_ORG=your_org
SENTRY_PROJECT=your_project

しかし、このように環境変数をDockerfileに直接記述したり、.envファイルに保存したりすると、以下の問題が発生します:

  1. セキュリティリスク: ビルドイメージ内に秘密情報が残る可能性がある
  2. 情報漏洩: GitHubなどのリポジトリに誤ってコミットしてしまう危険性
  3. 柔軟性の欠如: CI/CDパイプラインごとに設定を変更する必要がある

これらの問題を解決するために、DockerのSecret mountが有効です。

Secret mountとは

Secret mountは、ビルド時にのみ秘密情報をコンテナ内で利用可能にする機能です。ビルドが完了すると、その情報は最終イメージには含まれません。これにより、秘密情報の漏洩リスクを大幅に減らすことができます。

実装方法

1. Dockerfileの準備

まず、Next.jsプロジェクトのDockerfileを準備します。以下はNext.js公式リポジトリのwith-docker-multi-env例をベースにした構成です:

# syntax=docker.io/docker/dockerfile:1

FROM node:lts AS base

# 1. Install dependencies only when needed
FROM base AS deps
# libc6-compatはalpineイメージで必要になる場合があります
RUN apk add --no-cache libc6-compat

WORKDIR /app

# パッケージマネージャに応じて依存関係をインストール
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
RUN \
  if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
  elif [ -f package-lock.json ]; then npm ci; \
  elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i; \
  else echo "Lockfile not found." && exit 1; \
  fi

# 2. ソースコードのビルド
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Sentryの設定
ARG SENTRY_ORG
ARG SENTRY_PROJECT

# Sentryのソースマップアップロード用のシークレットマウント
RUN --mount=type=secret,id=SENTRY_AUTH_TOKEN \
    SENTRY_AUTH_TOKEN=$(cat /run/secrets/SENTRY_AUTH_TOKEN) \
    SENTRY_ORG=${SENTRY_ORG} \
    SENTRY_PROJECT=${SENTRY_PROJECT} \
    npm run build

# 3. 本番環境のイメージ作成
FROM base AS runner
WORKDIR /app

ENV NODE_ENV=production

RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

COPY --from=builder /app/public ./public

# Next.jsの出力トレースを活用してイメージサイズを削減
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT=3000

CMD ["node", "server.js"]

ここで重要なのは以下の部分です:

RUN --mount=type=secret,id=SENTRY_AUTH_TOKEN \
    SENTRY_AUTH_TOKEN=$(cat /run/secrets/SENTRY_AUTH_TOKEN) \
    SENTRY_ORG=${SENTRY_ORG} \
    SENTRY_PROJECT=${SENTRY_PROJECT} \
    npm run build

この記述により、ビルド時にのみSENTRY_AUTH_TOKENが利用可能になります。

2. next.config.jsの設定

Next.jsプロジェクトでSentryを使用するには、通常以下のような設定をします:

// next.config.js
const { withSentryConfig } = require('@sentry/nextjs');

const nextConfig = {
  // 他の設定...
};

const sentryWebpackPluginOptions = {
  org: process.env.SENTRY_ORG,
  project: process.env.SENTRY_PROJECT,
  authToken: process.env.SENTRY_AUTH_TOKEN,
  // その他のオプション...
};

module.exports = withSentryConfig(nextConfig, sentryWebpackPluginOptions);

3. Dockerビルドの実行

Secret mountを使用してビルドするには、以下のようにコマンドを実行します:

docker build \
  --build-arg SENTRY_ORG=your-org \
  --build-arg SENTRY_PROJECT=your-project \
  --secret id=SENTRY_AUTH_TOKEN,env=SENTRY_AUTH_TOKEN \
  -t my-nextjs-app .

環境変数SENTRY_AUTH_TOKENの値がビルド時にのみコンテナ内で利用可能になります。また、SENTRY_ORGSENTRY_PROJECTはビルド引数として渡されます。

4. CI/CDパイプラインでの設定

GitHub ActionsなどのCI/CDパイプラインでも同様に設定できます:

# .github/workflows/build.yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      
      - name: Build
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          tags: my-registry/my-nextjs-app:latest
          build-args: |
            SENTRY_ORG=${{ vars.SENTRY_ORG }}
            SENTRY_PROJECT=${{ vars.SENTRY_PROJECT }}
          secrets: |
            "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}"

メリット

Secret mountを使用することで得られる主なメリットは次のとおりです:

  1. セキュリティの向上: 秘密情報が最終イメージに含まれない
  2. コード管理の簡素化: 秘密情報をコードリポジトリから分離できる
  3. CI/CDとの統合: 様々なCI/CDシステムでシームレスに動作する

注意点

  • BuildKitが有効になっている必要があります(Docker 18.09以降ではデフォルトで有効)
    • 明示的に有効化するには以下の方法があります:
      • 環境変数で設定: export DOCKER_BUILDKIT=1
      • Docker設定ファイル(~/.docker/config.json)で設定: { "features": { "buildkit": true } }
      • docker buildコマンドに--buildkitフラグを追加
    • 詳細はDocker BuildKitのドキュメントを参照してください
  • ローカル開発時とCI/CDパイプラインでの一貫性を保つことが重要
  • SENTRY_AUTH_TOKENは機密情報のため、適切なシークレット管理サービスを使用して保存・管理すべきです

まとめ

Next.jsとSentryを連携する際に必要となるSENTRY_AUTH_TOKENは、DockerのSecret mount機能を使うことで安全に扱うことができます。これにより、セキュリティリスクを低減しながら、効率的なCI/CDパイプラインを構築できます。

もしあなたのプロジェクトでSentryを使用しているなら、ぜひSecret mountの導入を検討してみてください。

参考資料

Discussion