🥬

Docker で React + TypeScript の開発環境(自分用メモ)

2022/09/24に公開約9,200字

サマリー

Docker Desktop(docker デーモン)を起動させておいて…

zsh
% git clone https://github.com/sprout2000/docker-react-ts.git
% cd docker-react-ts
% docker-compose up

localhost:5173 を開きます。これだけです。

ローカルに Node.js がインストールされていなかったり、インストールされていてもこのコンテナで利用されているバージョンとは異なっていたりしても同じ(仮想)環境でプロジェクトが起動します。

Docker Desktop のインストール

公式ドキュメントに従ってインストールします。

https://docs.docker.com/desktop/windows/install/

https://docs.docker.com/desktop/mac/install/

docker-compose の利用

1. React + TypeScript アプリを作成

最速との呼び声高い Vite.js を利用します。

https://vitejs.dev/
zsh
npm create vite myapp -- --template react-ts
Scaffolding project in /Users/Foo/myapp...

Done. Now run:

  cd myapp
  npm install
  npm run dev

2. Vite の設定ファイルをアップデート

Vite のローカルサーバーがリッスンすべき IP アドレスを '0.0.0.0' に設定します。

vite.config.ts
  // https://vitejs.dev/config/
  export default defineConfig({
    plugins: [react()],
+   server: {
+     host: '0.0.0.0',
+   },
  });

"0.0.0.0" もしくは true に設定することで LAN やパブリックアドレスを含むすべてのアドレスをリッスンします。

https://ja.vitejs.dev/config/server-options.html#server-host

3. compose.yml の作成

プロジェクトフォルダ直下に compose.yml を作成します。

https://docs.docker.com/compose/compose-file/#compose-file
compose.yml
services: #1
  app: #2
    container_name: react-app-container #3
    image: node:16-alpine #4
    volumes:
      - ./:/app #5
    working_dir: /app #6
    command: sh -c "npm install && npm run dev" #7
    ports:
      - '5173:5173' #8
  • #1 services: このエントリ以下が 1 つのサービス (Node.js サーバ) となります。
  • #2 app: このエントリ以下が1つのコンテナとなります。
  • #3 container_name: コンテナの名前です。
  • #4 image: コンテナを作成するベースイメージ(ここでは node@16 の軽量版)を指定します。バージョンの一覧はこちら
  • #5 volumes: ホスト側のパス ./ をコンテナ側のパス /app にマウントします。
  • #6 working_dir: コンテナ実行時のカレントディレクトリです。通常は #6 のコンテナ側パスと同じです。
  • #7 command: 上記のカレントディレクトリで実行するコマンドを指定します。
  • #8 ホストのポート:コンテナのポート: これによりホスト (macOS や Windows) 側の http://localhost:5173 から、コンテナ側のポート 5173 (Vite の出力先) へアクセスできます。

4. docker-compose の実行

では、さっそくコンテナを作成・起動します。

zsh
docker-compose up -d

-d オプションを使用しているため、バックグラウンドでコンテナが作成・起動されます。
この過程のログを確認するには docker-compose logs を利用します。

zsh
docker-compose logs -f
react-app-container  |
react-app-container  | up to date, audited 90 packages in 647ms
react-app-container  |
react-app-container  | 8 packages are looking for funding
react-app-container  |   run `npm fund` for details
react-app-container  |
react-app-container  | found 0 vulnerabilities
# ~ 中略 ~
react-app-container  | > myapp@0.0.0 dev
react-app-container  | > vite
react-app-container  |
react-app-container  |
react-app-container  |   VITE v3.1.3  ready in 1768 ms
react-app-container  |
react-app-container  |   ➜  Local:   http://localhost:5173/
react-app-container  |   ➜  Network: http://172.22.0.2:5173/

"ready in 1768 ms" と表示されたので、http://localhost:5173 をブラウザで開きます。

5. コンテナの情報を確認する

現在のコンテナの稼働状況を確認するには、docker-compose ps コマンドを用います。

zsh
docker-compose ps
# 一部省略
NAME                  SERVICE    STATUS    PORTS
react-app-container   app        running   0.0.0.0:5173->5173/tcp

react-app-container という名前のコンテナが 5173番ポートrunning(稼働中) であることが分かります。

また、このコンテナを作成するにあたって、Docker レポジトリからプルして来た(= compose.ymlimage エントリに指定した)イメージも docker-compose images コマンドで確認できます。

zsh
docker-compose images
Container             Repository    Tag          Image Id        Size
react-app-container   node          16-alpine    6e983a17c040    114MB

node:16-alpine というイメージをレポジトリからプルして来て、react-app-container というコンテナを作成しています。

6. コンテナを停止・削除する

docker-compose stop コマンドでコンテナを停止させます。

zsh
docker-compose stop
[+] Running 1/1
 ⠿ Container react-app-container  Stopped    0.7s


% docker-compose ps
       Name                      Command               State    Ports
---------------------------------------------------------------------
react-app-container   docker-entrypoint.sh sh -c ...   Exit 0

コンテナも削除する場合は、docker-compose down コマンドを入力します(稼働中のコンテナにもこのコマンドを適用できます)。

zsh
docker-compose down
[+] Running 2/0
 ⠿ Container react-app-container    Removed     0.0s
 ⠿ Network docker-react-ts_default  Removed     0.0s

% docker-compose ps
Name   Command   State   Ports
------------------------------

また、--volumes オプションを追加することでコンテナが利用していたデータボリュームも削除できます。

zsh
docker-compose down --volumes

Docker イメージの作成

では、この React + TypeScript 開発環境を独自イメージとしてビルドしてみます。

1. Dockerfile の作成

Docker イメージを作成するための設定ファイル、Dockerfile をプロジェクトディレクトリへ作成します。

https://docs.docker.com/engine/reference/builder/
Dockerfile
#1
FROM node:16-alpine
#2
WORKDIR /app
#3
COPY package.json .
COPY package-lock.json .
#4
RUN npm install
#5
COPY . .
#6
EXPOSE 5173
#7
CMD [ "npm", "run", "dev" ]
  • #1 FROM: ベースとなるイメージを指定します。
  • #2 WORKDIR: コンテナ上でのワーキングディレクトリを指定します。
  • #3 COPY: 依存パッケージをインストールするために package.json とロックファイルをイメージのファイルシステム上にコピーします。
  • #4 RUN: イメージのファイルシステム内でコマンドを実行します。
  • #5 COPY: 残りのソースコードをホスト上からイメージのファイルシステム上にコピーします。
  • #6 EXPOSE: 実行時にコンテナが特定のポートをリッスンするよう Docker に通知します。
  • #7 CMD: コンテナ内でコマンドを実行します。JSON 文字列なのでシングルクォートは使えません。

2. .dockerignore の作成

イメージに含めたくないファイルやフォルダを .dockerignore ファイルに指定します。
ここでは、とりあえず node_modules のみを指定しておきます。

.dockerignore
node_modules

3. Docker イメージのビルド

では、さっそくイメージをビルドしてみます。

zsh
# カレントディレクトリをビルド
% docker build -t {your_docker_id}/myapp .

-t オプションでタグ名を指名します。
Docker Hub へもプッシュする場合は、Docker アカウント名とスコープを一致させておく必要があります。

zsh
% docker build -t sprout2000/myapp .

[+] Building 3.8s (11/11) FINISHED
 => [internal] load build definition from Dockerfile               0.0s
 => => transferring dockerfile: 186B                               0.0s
 => [internal] load .dockerignore                                  0.0s
 => => transferring context: 53B                                   0.0s
 => [internal] load metadata for docker.io/library/node:16-alpine  0.0s
 => [1/6] FROM docker.io/library/node:16-alpine                    0.0s
 => [internal] load build context                                  0.0s
 => => transferring context: 102.42kB                              0.0s
 => CACHED [2/6] WORKDIR /app                                      0.0s
 => [3/6] COPY package.json .                                      0.0s
 => [4/6] COPY package-lock.json .                                 0.0s
 => [5/6] RUN npm install                                          3.3s
 => [6/6] COPY . .                                                 0.0s
 => exporting to image                                             0.3s
# 以下略

docker images コマンドで結果を確認します。

zsh
docker images
REPOSITORY         TAG         IMAGE ID       CREATED         SIZE
sprout2000/myapp   latest      b0f0c8be2997   3 minutes ago   242MB
node               16-alpine   6e983a17c040   5 weeks ago     114MB

バージョン番号を指定しないでビルドしたため、latest が自動的に割り振られました。

4. コンテナの作成と実行

上で作成した Docker イメージからコンテナを作成・実行します。

zsh
docker run --rm -d -p 5173:5173 --name myapp {your_id}/myapp
  • --rm: コンテナを終了させると、そのコンテナ自身も自動的に削除されます。
  • -d: バックグラウンドでコンテナを実行します。
  • -p ホストのポート:コンテナのポート: ホストのポート 5173 に入ってくるトラフィックを、コンテナのポート 5173 へ転送します。
  • --name: コンテナの名前を指定します(省略化)。

docker ps コマンドで確認します。

zsh
docker ps -a
# 一部省略
CONTAINER ID   IMAGE              STATUS          NAMES
9ceadf8f3c5e   sprout2000/myapp   Up 19 seconds   myapp

localhost:5173 へアクセスすると、React アプリの起動を確認できました。

5. コンテナの停止

コンテナの作成・実行が確認できたので、このコンテナを停止します。
--name オプションを指定していたので、その名前でコンテナを特定できます。

zsh
docker stop myapp
zsh
% docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

--rm オプションが与えられていたので、コンテナそのものも削除されました。

Discussion

ログインするとコメントできます