Express + Next.js をコンテナで�咾�したい

峻さん、こんにちは。室宝蝕�kグル�`プの稼-看噛温敬温稼です。
9埖ですね。定を嶷ねると扮寂�Uつのが壼く湖じる�嶇鵑髻献献礇幽`の隈夸々といいます。

云籾です。
Express + Next.jsで��撹したフロントエンド�h廠をコンテナで�嘛�させたい��栽、どのような返��でDockerイメ�`ジを恬撹すればよいでしょうか。書指は、Express + Next.jsで��撹したフロントエンド�h廠をイメ�`ジ晒するまでの返��をまとめたいと房います。

Express + Next.js プロジェクトの����

まずはExprerss + Next.jsで��撹されたプロジェクトを���笋靴泙后R塹造離灰泪鵐匹�Next.jsを���Bします。余嶄の�|��は畠てデフォルトのままでOKです。

npx create-next-app@latest express-server-app

肝に掘恰沿姻艶壊壊をインスト�`ルします。

cd express-server-app
npm i express
npm i -D ts-node @types/express

プロジェクトのル�`ト岷和にserver.tsを弖紗します。坪否は參和の宥りです。

import express, { json } from 'express';
import next from "next";

const port = parseInt(process.env.PORT || "3000", 10);
const dev = process.env.NODE_ENV !== "production";
const server = express();
const app = next({ dev });

async function startupServer() {
  await app.prepare();    

  const handle = app.getRequestHandler();
  server.get('*',(req, res) => handle(req, res));

  server.listen(port, () => {
    console.log(
      `> Server listening at http://localhost:${port} as ${dev ? "development" : process.env.NODE_ENV}`,
    );
  });    
}

startupServer();

7佩朕のnext({ dev });で鰻艶恰岳.逮壊のサ�`バ�`を伏撹しています。哈方にdevを局していますが、ロ�`カル桟廠で強恬するときはdev: trueを、云桑桟廠で強恬するときはdev: falseを峺協する駅勣があります。このdevの嶄附は5佩朕で登僅しています。

10佩朕のapp.prepare();で鰻艶恰岳.逮壊のサ�`バ�`を羨ち貧げます。13佩朕では掘恰沿姻艶壊壊サ�`バ�`が鞭佚したリクエストを、鰻艶恰岳.逮壊サ�`バ�`へ局します。

tsconfig.server.jsonを弖紗します。坪否の�h苧は福きます。

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs",
    "outDir": "dist",
    "lib": ["es2019"],
    "target": "es2019",
    "noEmit": false
  },
  "include": ["server.ts"]
}

あとは軟強するコマンドを俐屎すれば或悪です。package.jsonの壊界姻庄沿岳壊を俐屎します。

"dev": "ts-node -P ./tsconfig.server.json ./server.ts",

參和のコマンドでExpress + Next.jsの�h廠が�嘛�します。

npm run dev

禽看界一艶姻韓庄鉛艶の恬撹

ロ�`カル桟廠での強恬が鳩範できましたので、云桑桟廠喘に、このプロジェクトの禽看界一艶姻イメ�`ジを恬撹します。鰻艶恰岳.逮壊の禽看界一艶姻イメ�`ジを恬撹する禽看界一艶姻韓庄鉛艶はされています。この禽看界一艶姻韓庄鉛艶を歌深に更廏します。

ビルド

禽看界一艶姻韓庄鉛艶を恬撹します。まずはpackage.jsonとpackage-lock.jsonをイメ�`ジにコピ�`して、npm ciにより卆贋�v�Sのパッケ�`ジをインスト�`ルします。

FROM node:18-alpine AS base

# Install dependencies only when needed
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

肝にソ�`スコ�`ドなどをイメ�`ジにコピ�`して、npm run buildによりビルドを�g佩します。

# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN npm run build

npm run buildは參和のように俐屎します。稼艶恰岳.逮壊のビルドと、掘恰沿姻艶壊壊のビルドを�g佩しています。

"build": "next build && tsc --project tsconfig.server.json",

鰻艶恰岳.逮壊をビルドする縞は、next.config.mjsにoutput: "standalone"を弖紗しておきます。standaloneで竃薦すると、稼看糸艶喝馨看糸顎鉛艶を根む、鰻艶恰岳.逮壊を�g佩するために駅勣なファイルがstandaloneというフォルダにまとめて竃薦してくれます。

const nextConfig = {
  output: "standalone",
};

鰻艶恰岳.逮壊のファイルをイメ�`ジにコピ�`する

鰻艶恰岳.逮壊をビルドすると、ビルド潤惚は.nextフォルダに竃薦されます。.nextに竃薦されたファイルをイメ�`ジにコピ�`します。

# Production image, copy all the files (express + next.js) and run express
FROM base AS runner
WORKDIR /app

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

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

掘恰沿姻艶壊壊のファイルをイメ�`ジにコピ�`する

掘恰沿姻艶壊壊をビルドすると、ビルド潤惚はdistフォルダに竃薦されます。distに竃薦されたファイルをイメ�`ジにコピ�`します。コピ�`朔は、npm ci --omit devで�g佩に駅勣なパッケ�`ジをインスト�`ルします。

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

COPY --from=builder /app/package-lock.json ./
RUN npm ci --omit dev

サ�`バ�`を�g佩する

恷朔はnpm run startによりサ�`バ�`を�g佩します。

USER nextjs
EXPOSE 3000
ENV PORT=3000

# server.js is created by next build from the standalone output
ENV HOSTNAME="0.0.0.0"
CMD ["npm", "run", "start"]

npm run startの坪否は參和のように俐屎します。

"start": "NODE_ENV=production node ./server.js",

イメ�`ジ晒してコンテナを軟強する

禽看界一艶姻韓庄鉛艶の園鹿は參貧です。�g縞にイメ�`ジ晒してコンテナを軟強してみましょう。

docker build -t express-server-app .
docker run -p 3000:3000 -it express-server-app

おわりに

書指はExpress + Next.jsということで、Dockerイメ�`ジの恬撹返��をまとめてみましたが、Express參翌のサ�`バ�`でも揖じような返��で竃栖るかと房います。

また、書指は3000桑ポ�`トで�咾�していますが、80桑ポ�`トようなwell known portで�咾�す��栽は砿尖宀�慙泙�駅勣となりますのでご廣吭ください。USER nextjsで稼艶恰岳逮壊ユ�`ザ�`で軟強するようにしていますので、おそらく80桑ポ�`トでの軟強は竃栖ないです。その魁栽はUSER nextjsをコメントアウトしてください。

ではまた。


Recommendおすすめブログ