以前書いた記事で開発を進めていたら、ホットリロードが出来なくなっていた。
それどころか、リロードしても修正が反映されない。。。
開発環境をDockerに移行した途端このような事態になったので、原因はDockerにあるはず。というわけで、調査&修正を行った。
原因
原因はすごく簡単な事だった。
Dockerfileで、コードをbuildして静的ファイルを作成→Nginxコンテナに静的ファイルをコピーという手順を踏んでいる。
ブラウザで表示しているのはNginxコンテナ内のファイルであるため、いくらコードに修正しても反映されるわけがない。
そりゃそうだ。。。
FROM node:21-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
ENV NODE_OPTIONS=--openssl-legacy-provider
RUN npm install
COPY . ./
# 原因1
RUN npm run build
FROM nginx:alpine
# 原因2
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
修正内容
ホットリロードするためには、ソースをbuildせずnpm startでプロジェクトを実行すればいい。
とはいえ、本番環境ではNginxに静的ファイルを置いたほうがいい。(ファイルサイズの圧縮とかパフォーマンスの向上のため)
ということで、docker-composeファイルを作ってマルチステージビルドすることにした。
・Dockerfile(修正後)
# development stage
FROM node:21-alpine AS dev
WORKDIR /app
COPY package.json package-lock.json ./
ENV NODE_OPTIONS=--openssl-legacy-provider
RUN npm install
COPY . ./
CMD ["npm", "start"]
# build stage
FROM dev AS build
RUN npm run build
# production stage
FROM nginx:alpine AS prod
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
docker-compose.yml
version: '3'
services:
front:
build:
context: .
# ここ重要
target: dev
volumes:
- .:/app
- /app/node_modules
ports:
- "${PORT_MAPPING}"
environment:
- NODE_ENV=${NODE_ENV}
制御方法
Dockerfileでやっていることは以下。
開発環境では1、本番環境では1~3を実行するようコマンドで制御する。
- developmentステージでアプリケーションのイメージ作成
- buildステージで静的ファイル作成
- Nginxに静的ファイルをコピー
本番用のイメージを作りたい時はオプションでprodを指定する。
こうすることで、上記1~3を実施する。
docker build --target prod .
開発環境ではdocker-compose upするだけでOK。
docker-compose up