July Sunday,3rd 2022: PM

GCP Cloud Run Dockerfile | Next.js

Cloud Runにした背景

私が作るプロダクトにはコンタクトフォームにnodemailerを使用しています。 node.js上でしか動作しない仕様なのでnext export系は全滅でした。 Github ActionsのAzure Web Static AppsやCloudflare Pagesなどは使ってみて動かなかったので除外されました。

3週間くらいかかった

環境変数につまずきすぎて3週間超えてしまった(もちろん他のこともやってた)。 Dockerとyamlの知識がなく環境変数を安全にデプロイするために必要な時間でした。 先の見えないビルドループから抜け出せたのでホッとしました。

これで一応月間3000000リクエストまでは0.4ドルで捌けるみたいです。

Dockerfile(Next.js in Cloud Build)

# Install dependencies only when needed
FROM node:lts-alpine AS deps

RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./ 
RUN npm ci

# Rebuild the source code only when needed
FROM node:lts-alpine AS builder

ARG _CONTENTFUL_SPACE_ID
ARG _CONTENTFUL_DELIVERY_TOKEN
ARG _NEXT_PUBLIC_GA_ID
ARG _MAIL_USER
ARG _MAIL_PASS
ARG _MAIL_TO

ENV NEXT_PUBLIC_CONTENTFUL_SPACE_ID=$_CONTENTFUL_SPACE_ID \
    NEXT_PUBLIC_CONTENTFUL_DELIVERY_TOKEN=$_CONTENTFUL_DELIVERY_TOKEN \
    NEXT_PUBLIC_GA_ID=$_NEXT_PUBLIC_GA_ID \
    NEXT_PUBLIC_MAIL_USER=$_MAIL_USER \
    NEXT_PUBLIC_MAIL_PASS=$_MAIL_PASS \
    NEXT_PUBLIC_MAIL_TO=$_MAIL_TO

WORKDIR /app
COPY . .
COPY --from=deps /app/node_modules ./node_modules
RUN npm run build

# Production image, copy all the files and run next
FROM node:alpine AS runner

WORKDIR /app
ENV NODE_ENV production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder --chown=node:node /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
USER nextjs
EXPOSE 3000
CMD ["npm", "start"]

ハマりポイント

m1チップからのDockerイメージだとbuildコマンドの引数に --platform linux/amd64を付けないといけない。 これは最初にContainer Registryにpushするときに必要(m(x)チップなら)

amd64はつまりx86_64と同じみたいで、使ってるPCのCPUアーキテクチャを引数でGCPのマシンに合わせる必要があります。 M1 MacでARMとIntelのターミナルを切り替えて使う (Homebrew 3以降の場合)


COPY --from=builder --chown=node:node /app/.next ./.next

--chown=node:nodeとしてroot権限エラー回避


FROM node:lts-alpine AS builder

ローカルのビルドは成功するにもかかわらず、ここのすぐ下,WORKDIR /appの前にARGとENVを記述しないとCloud Buildで設定した環境変数を吸わなかったです。 ここで他のところに記述してもローカルでイメージを焼いてlocalhost:3000で見ても問題なく動く、なのにCloud BuildからDocker imageに渡す場合この場所に記述しないとだめです。


・npmを使用しているならnpm installの代わりにnpm ciを使う ・dockerignoreで不要なファイルをはじく

#さいごに

リクエストが上がりにくい小規模な個人ブログではわざわざAWSやGCPを導入する必要はほぼないかもしれませんが、ぜひみんなも勉強としてやってみましょう!!

ここらへんの従量課金系サービスでよいところはドメインからCICDからコンソールから通信量やメモリCPU使用量のインフラ管理まですべてを一貫して行えることです。 私はGoogleドメインを使いたかったので今回GCPを使ってみました。 ここまでみてくれてありがとうございました! node.jsアプリでDockerfileを作る人の参考になれれば幸いです!

Google Cloud 料金計算ツール

3大クラウドサービス(Azure/AWS/GCP)のコンテナサービスをさわって比較してみた