$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

Next.jsアプリケーション用のDockerイメージを作る

Next.jsアプリケーションをECSで動かしたいと思い、Dockerfileを作ってみたのでメモ。

設定の用意

Dockerfileと.dockerignoreを用意し、ビルドコマンド用にMakefileも用意した。

Dockerfile

# syntax = docker/dockerfile:experimental

FROM node:12-stretch-slim AS nextjs-on-ecs-server-builder

USER node

WORKDIR /app

COPY --chown=node:node package.json yarn.lock ./

RUN mkdir -p /home/node/.cache
RUN --mount=type=cache,target=/home/node/.cache,id=yarn-cache,sharing=private,uid=1000 yarn install --pure-lockfile

COPY --chown=node:node . ./

RUN npm run build

FROM node:12-stretch-slim AS nextjs-on-ecs-server

WORKDIR /app

COPY --from=nextjs-on-ecs-server-builder /app/package.json /app/yarn.lock ./
RUN --mount=type=cache,target=/home/node/.cache,id=yarn-cache,sharing=private,uid=1000 yarn install --pure-lockfile --production
COPY --from=nextjs-on-ecs-server-builder /app/.next ./.next

CMD ["npm", "run", "start"]
  • 本番用に無駄なデータが入らないように、next buildを実行するビルド用イメージ(nextjs-on-ecs-server-builder)と、実際にに実行するためのイメージ(nextjs-on-ecs-server)を、マルチステージビルドで分離した
  • # syntax = docker/dockerfile:experimental を書いておき、yarn installでは高速化のため --mount=type=cache 付きで実行して、イメージ更新時にキャッシュが使われるようにする
  • https://nextjs.org/docs/deployment を参考にし、nextjs-on-ecs-serverには
    • package.json、yarn.lock、.nextだけ入れる
      • yarn.lockは実行するだけならいらないかも?
    • yarn installは--production付きでdependenciesだけを入れる

.dockerignore

.git
node_modules
.next

Makefile

export DOCKER_BUILDKIT=1

.PHONY: build
build:
    docker build --file Dockerfile.server --target nextjs-on-ecs-server --tag nextjs-on-ecs-server:latest --progress plain .

ビルドして実行する

ビルドする

$ make build

これでnextjs-on-ecs-serverというイメージが出来たので、実行する。

$ docker run --rm -ti -p 3000:3000 nextjs-on-ecs-server

> with-typescript@1.0.0 start /app
> next start

> Ready on http://localhost:3000

http://localhost:3000/ にアクセスすると、以下のように表示される。 f:id:shiba_yu36:20200202215412p:plain

まとめ

これでNext.jsアプリケーションをコンテナで動かすことができた。あとはECSなり何でも良いのでデプロイしたら良い。