0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Vite + React + Docker】ホットリロード付きのローカル環境構築

Posted at

【初めに】

こんにちは。
@hayatohanaoka です。

休日に遊び感覚で ReactDocker で動かせるようにしてみたところ、
ホットリロード周りでいくつか学びがあったので残します。
出来としては雑でお粗末なものかもしれないのですが、誰かの助けになれば幸いです。

【リポジトリ】

:mega: 「とりあえず中身見せろや!!」
って人向けに、冒頭で置いておきます...
sample-react

【環境】

マシン
M3 Mac

コンテナマネージャ
Rancher Desktop

言語
typescript 5.6.2

ランタイム
node 23.7.0

ライブラリ
react 18.3.1

【ReactAppの作成】

公式Docs に従ってコマンド実行しただけです。
ここはそこまで大変でないのと、次のトピックが主題なので割愛。

【コンテナ化】

Dockerfile を作成して、コンテナ化していきます。
Dockerfile の解説を少し挟むと、コンテナの元になる image の作成の際に必要となるファイルです。
ここに書いたステップを元に image を作成し、保存します。

FROM node:23-alpine
WORKDIR /app
# 依存関係のインストール
COPY package*.json ./
RUN npm install
# ソースコードのコピー
COPY . .
# アプリケーションの起動
CMD ["npm", "run", "dev"]

ローカルで実行するために簡単に用意したため、
ビルドと実行のステぷを分けること(マルチステージビルド)はしていません。

やっていることは非常にシンプルなので、初心者でも理解しやすいです。

  1. 土台となるイメージを用意する( node:23-alpine
  2. package.jsonを元に、依存関係をインストールする
  3. ソースコードを元に npm run dev でアプリケーションを起動する

こちらについても、特筆すべき点はありません。

【ホットリロードの有効化】

今回の記事の主題です。
編集が必要になったのは以下のファイルです。

  1. docker-compose.yaml
  2. vite.config.ts

上から順に解説します。

docker-compose.yaml

複数のコンテナをどのように立ち上げるか設定できるファイル。

  1. image の作成の際にどのDockerfileやファイルを参照するか
  2. どのポートを繋ぎ合わせるのか
  3. 環境変数には何を使用するか

等が設定できます。

docker-compose.yaml
services:
  react:
    build:
      context: ../../
      dockerfile: environments/local/Dockerfile
    ports:
      - 3000:5173 # host_port:container_port
    volumes: # ホストのディレクトリをマウントして、コンテナ内のディレクトリに反映
      - ../../src:/app/src
    environment:
      # ホットリロードのために必要なオプション値
      - CHOKIDAR_USEPOLLING=true
      - WATCHPACK_POLLING=true

ここでは以下の工夫が必要でした。

  1. ポートフォワード
    1. localhost:3000 でリクエストしたかったので、 ports で指定
  2. ボリュームマウント
    1. ここがないと、ローカルの変更がコンテ内部に反映されません
  3. 環境変数の設定
    1. ここがないと、ソースコードの変更が検知されません
    2. vite.config.ts で設定することも可能
      1. ローカルで npm run dev を行う際に不要な設定のため、こちらで設定した

vite.config.ts

vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vite.dev/config/
export default defineConfig({
  plugins: [react()],
  // サーバがリッスンするホストとポートを設定
  server: {
    host: true,
    port: 5173,
  },
})

こちらでは以下の設定を行なっています。

  1. viteが立ち上げるサーバーと通信可能なホストとポートを設定する
    1. host
      1. 0.0.0.0 または true を設定すると、全ホストを許可
      2. コンテナ内部の localhost と、 ホストマシンのlocalhost が別のものなので、
        繋ぎ合わせるために必要
    2. port
      1. 今回は 5173 を許可

図にするとこんな感じだと思います。

スクリーンショット 2025-06-12 3.20.59.png

【実行】

いよいよ実行です...!!
以下のコマンドを実行します。

$ cd environments/local 
$ docker compose up --build

Compose can now delegate builds to bake for better performance.
 To do so, set COMPOSE_BAKE=true.
[+] Building 2.4s (11/11) FINISHED                                                                                                                                                             docker:rancher-desktop
 => [react internal] load build definition from Dockerfile                                                                                                                                                       0.0s
 => => transferring dockerfile: 250B                                                                                                                                                                             0.0s
 => [react internal] load metadata for docker.io/library/node:23-alpine                                                                                                                                          1.4s
 => [react internal] load .dockerignore                                                                                                                                                                          0.0s
 => => transferring context: 2B                                                                                                                                                                                  0.0s
 => [react 1/5] FROM docker.io/library/node:23-alpine@sha256:a34e14ef1df25b58258956049ab5a71ea7f0d498e41d0b514f4b8de09af09456                                                                                    0.0s
 => [react internal] load build context                                                                                                                                                                          0.2s
 => => transferring context: 453.30kB                                                                                                                                                                            0.2s
 => CACHED [react 2/5] WORKDIR /app                                                                                                                                                                              0.0s
 => CACHED [react 3/5] COPY package*.json ./                                                                                                                                                                     0.0s
 => CACHED [react 4/5] RUN npm install                                                                                                                                                                           0.0s
 => [react 5/5] COPY . .                                                                                                                                                                                         0.5s
 => [react] exporting to image                                                                                                                                                                                   0.2s
 => => exporting layers                                                                                                                                                                                          0.2s
 => => writing image sha256:9ebfd4463af40681bafe16f2e4676938b1e58cfdd8323be570d88a39a672616e                                                                                                                     0.0s
 => => naming to docker.io/library/local-react                                                                                                                                                                   0.0s
 => [react] resolving provenance for metadata file                                                                                                                                                               0.0s
[+] Running 2/2
 ✔ react                    Built                                                                                                                                                                                0.0s 
 ✔ Container local-react-1  Recreated                                                                                                                                                                            0.0s 
Attaching to react-1
react-1  | 
react-1  | > sample-react@0.0.0 dev
react-1  | > vite
react-1  | 
react-1  | 
react-1  |   VITE v5.4.19  ready in 89 ms
react-1  | 
react-1  |   ➜  Local:   http://localhost:5173/
react-1  |   ➜  Network: http://172.21.0.2:5173/

うまくいってそう!!一応確認する。

$ docker ps
CONTAINER ID   IMAGE       COMMAND                CREATED         STATUS         PORTS                                         NAMES
0489acc9d69f   local-react "docker-entrypoint.s…" 2 minutes ago   Up 2 minutes   0.0.0.0:3000->5173/tcp, [::]:3000->5173/tcp   local-react-1

これで http://localhost:3000/ にもリクエストしてみると...

image.png

:ok: :ok: :ok: :ok: :ok: :ok:

試しにsrc/main.tsを変更してみると、こんなログが!

react-1  | 6:30:55 PM [vite] page reload src/main.tsx

画面を確認。

image.png

:ok: :ok: :ok: :ok: :ok: :ok:

リロードまで体感10秒〜15秒かかりました。
遅い理由はわかっていないですが、似た事例の記事を発見した。
いつか解消したい...。

【まとめ】

ホットリロードを有効化するには、以下のことが必要。

  1. docker-composeでボリュームマウントする
    1. 変更をコンテナ内部に反映させるため
  2. 以下のオプションを明示的に有効にする
    1. CHOKIDAR_USEPOLLING=true
    2. WATCHPACK_POLLING=true

【おまけ】

vite.config.ts にホットリロードに必要な設定をした場合のものを置いておきます。

vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vite.dev/config/
export default defineConfig({
  plugins: [react()],
  // サーバがリッスンするホストとポートを設定
  server: {
    host: true,
    port: 5173,
    // ホットリロードのために必要なオプション値
    watch: {
      usePolling: true,
      interval: 1000  
    }
  },
})
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?