ステージング環境をインデックス登録されないようにする【Next.js + Docker + VPS】

ステージング環境は、本番環境とは違い、確認やテストを行うため環境のため、検索エンジンにインデックス登録されてしまうといけません。

今回はNext.js のプロジェクトを VPS 上の Docker にデプロイする【その5】にて作成したステージング環境をインデックスしないようにしていきます。

robots.txt を配置する

検索エンジンにインデックスしないように伝えるために、robots.txtを配置します。

robots.txt ファイルとは、検索エンジンのクローラに対して、サイトのどの URL にアクセスしてよいかを伝えるものです。 これは主に、サイトでのリクエストのオーバーロードを避けるために使用され、Google にウェブページが表示されないようにするためのメカニズムではありません。Google にウェブページが表示されないようにするには、noindex を使用してインデックス登録をブロックするか、ページをパスワードで保護します。

robots/robots.txt
User-agent: *
Disallow: /

ビルド時にpublic に配置するように Dockerfileに追記します。

stg.Dockerfile
##### deps ステージ #####
FROM node:16-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
  if [ -f yarn.lock ]; then yarn install --frozen-lockfile; \
  elif [ -f package-lock.json ]; then npm ci; \
  elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
  else echo "Lockfile not found." && exit 1; \
  fi

##### builder ステージ #####
FROM node:16-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN yarn build

##### runner ステージ #####
FROM node:16-alpine AS runner
WORKDIR /app

ENV NODE_ENV=production

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public
# runner ステージで robots.txt をコピーして配置する
COPY --from=builder /app/robots/robots.txt ./public/robots.txt
COPY --from=builder /app/package.json ./package.json

COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 53274

ENV PORT 53274

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

noindex を設定する

robots.txtの役割だけではインデックス登録のブロックはできないので、noindexの指定も行います。
Netlifyでテスト環境を構築したら、noindexがついてなくて焦った話」の記事を参考に実装しました。

STEP.1
noindex を追加する

NEXT_PUBLIC_APP_ENVという環境変数を新しく用意しました。ステージング環境かどうかの判定を行います。

_app.tsx
import Head from 'next/head'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  return <>
    <Head>
      {process.env.NEXT_PUBLIC_APP_ENV === 'staging' && <meta name="robots" content="noindex" />}
    </Head>
    <Component {...pageProps} />
  </>
}

export default MyApp
STEP.2
Dockerfile で環境変数を渡す

Dockerfile で環境変数の設定を行います。

stg.Dockerfile
##### deps ステージ #####
FROM node:16-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
  if [ -f yarn.lock ]; then yarn install --frozen-lockfile; \
  elif [ -f package-lock.json ]; then npm ci; \
  elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
  else echo "Lockfile not found." && exit 1; \
  fi

##### builder ステージ #####
FROM node:16-alpine AS builder
WORKDIR /app

# 環境変数をわたして設定する
ARG NEXT_PUBLIC_APP_ENV
ENV NEXT_PUBLIC_APP_ENV=$NEXT_PUBLIC_APP_ENV

COPY --from=deps /app/node_modules ./node_modules
COPY . .

ARG NODE_ENV=production
RUN echo ${NODE_ENV}

RUN yarn build

##### runner ステージ #####
FROM node:16-alpine AS runner
WORKDIR /app

ENV NODE_ENV=production

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public
COPY --from=builder /app/robots/robots.txt ./public/robots.txt
COPY --from=builder /app/package.json ./package.json

COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 49200

ENV PORT 49200

CMD ["node", "server.js"]
STEP.3
ワークフローで環境変数の設定

最後にワークフローで環境変数を設定します。

GitHub Actions を用いて VPS へのデプロイをする方法については「Next.js のプロジェクトを VPS 上の Docker にデプロイする【その4】,【その5】にて実装しました。

.github/workflows/deploy.stg.ymljobs.deploy.steps.envと jobs.deploy.steps.with.buildargsの部分に環境変数を設定しました。

.github/workflows/deploy.stg.yml
name: Deploy to Sakura VPS Staging

# staging ブランチにプッシュされた時に実行する
on: 
  push:
    branches: [staging]
  # 手動実行時のログを設定
  workflow_dispatch:
    inputs:
      logLevel:
        description: 'Log level'
        required: true
        default: 'warning'
jobs:
  deploy:
    runs-on: ubuntu-latest
    container: node:16
    steps:
      # チェックアウト
      - uses: actions/checkout@v3
      # Github Container Registry へビルドしてイメージを格納
      - name: Build and Publish to Github Container Registry
        uses: elgohr/Publish-Docker-Github-Action@master
        # env を追加
        env:
          NEXT_PUBLIC_APP_ENV: staging
        with:
          # 本番とステージングでイメージ名を変更
          name: GitHubのユーザ名(lowercase)/donutssite/donuts-site-image-staging
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
          dockerfile: stg.Dockerfile
          # buildargs に追加
          buildargs: NEXT_PUBLIC_APP_ENV
          tags: latest
      # VPSへのデプロイ
      - name: Deploy to Sakura VPS
        uses: appleboy/ssh-action@master
        env:
          GITHUB_USERNAME: ${{ github.actor }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          host: ${{ secrets.DEPLOY_HOST }}
          port: ${{ secrets.DEPLOY_PORT }}
          username: ${{ secrets.DEPLOY_USER }}
          key: ${{ secrets.DEPLOY_KEY }}
          envs: GITHUB_USERNAME, GITHUB_TOKEN
          script: |
            docker login ghcr.io -u $GITHUB_USERNAME -p $GITHUB_TOKEN
            docker image pull ghcr.io/GitHubのユーザ名(lowercase)/donutssite/donuts-site-image-staging:latest
            docker container stop donuts-site
            docker container rm donuts-site
            docker system prune -f
            docker container run --name donuts-site -dit -p 49200:49200 --restart=always ghcr.io/GitHubのユーザ名(lowercase)/donutssite/donuts-site-image-staging:latest

おわりに

これでステージング環境はインデックス登録されなくなったはずです。
環境変数を渡すのに少し苦戦しましたが、今回も「Deploying Next.js apps to a VPS using Github actions and Docker」の記事のおかげで解決しました。いつもありがとうございます。