React アプリを Docker 化する方法: 開発者向けのステップバイステップガイド

あなたが私のような人なら、Reactを使用して洗練された応答性の高いユーザーインターフェイスを作成するのが大好きです。 しかし、一貫した開発環境を設定し、スムーズなデプロイを確保することは、複雑になることもあります。 そこで、Docker が窮地を救うお手伝いをします。

シニアDevOpsエンジニアおよびDockerキャプテンとして、私はコンテナ化の海をナビゲートし、Dockerがワークフローにどのように革命をもたらすかを直接目の当たりにしてきました。 このガイドでは、React アプリを Docker 化して開発プロセスを合理化し、「自分のマシンで動作する」という厄介な問題を排除し、シームレスなデプロイで同僚を感動させる方法を共有します。

DockerとReactの世界に飛び込みましょう!

2400×1260 DockerエバーグリーンロゴブログD 1

なぜReactアプリケーションをコンテナ化するのですか?

「なぜわざわざReactアプリをコンテナ化する必要があるのか」と疑問に思われるかもしれません。いい質問ですね! コンテナ化には、開発とデプロイメントのゲームを向上させる次のような魅力的な利点があります。

  • CI/CD パイプラインの合理化: React アプリを Docker コンテナにパッケージ化することで、開発から本番環境まで一貫した環境を作成できます。 この一貫性により、継続的インテグレーションと継続的デプロイ (CI/CD) パイプラインが簡素化され、ビルドとデプロイ中の環境固有の問題のリスクが軽減されます。
  • 依存関係管理の簡素化: Docker は、アプリのすべての依存関係をコンテナ内にカプセル化します。 これは、悪名高い「私のマシンで動作する」というジレンマに対処する必要がなくなることを意味します。 すべてのチームメンバーとデプロイメント環境が同じセットアップを使用しているため、スムーズなコラボレーションが保証されます。
  • リソース管理の改善: コンテナは軽量で効率的です。 仮想マシンとは異なり、Docker コンテナはホストシステムのカーネルを共有するため、同じハードウェア上でより多くのコンテナを実行できます。 この効率性は、アプリケーションをスケーリングしたり、本番環境でリソースを管理したりするときに重要です。
  • 競合のない孤立した環境: Docker は、アプリケーションに分離された環境を提供します。 この分離により、同じマシン上の異なるプロジェクトの依存関係または構成間の競合が防止されます。 それぞれが独自の依存関係を持つ複数のアプリケーションを実行でき、互いに足を引っ張ることはありません。

React と Docker を使い始める

先に進む前に、Reactアプリのコンテナ化を開始するために必要なものがすべて揃っていることを確認しましょう。

必要なツール

Docker の簡単な紹介

Docker は、エンタープライズ対応ツール、クラウド サービス、信頼できるコンテンツ、およびワークフローの合理化と開発効率の最大化を支援する共同コミュニティの包括的なスイートを提供します。 Docker 生産性プラットフォームを使用すると、開発者はアプリケーションをコンテナ (ソフトウェアの実行に必要なすべてのものを含む標準化されたユニット) にパッケージ化できます。 コンテナは、アプリケーションがデプロイされている場所に関係なく、同じように実行されることを保証します。

ReactプロジェクトをDocker化する方法

それでは、本題に入りましょう。 このプロセスを段階的に進め、最後には、Dockerコンテナ内でReactアプリを実行できるようになります。

ステップ 1:Reactアプリをセットアップする

すでに React アプリをお持ちの場合は、この手順をスキップできます。 そうでない場合は、作成しましょう。

npx create-react-app my-react-app
cd my-react-app

このコマンドは、 my-react-app というディレクトリで新しい React アプリケーションを初期化します。

ステップ 2: Dockerfile を作成する

プロジェクトのルート ディレクトリに、 Dockerfile という名前のファイルを作成します (拡張子はありません)。 このファイルには、Docker イメージをビルドするための手順が含まれています。

開発 Dockerfile (オプション)

開発目的で、単純な Dockerfile を作成できます。

# Use the latest LTS version of Node.js
FROM node:18-alpine

# Set the working directory inside the container
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of your application files
COPY . .

# Expose the port your app runs on
EXPOSE 3000

# Define the command to run your app
CMD ["npm", "start"]

ここで何が起こっているのですか?

  • FROM node:18-alpine: Alpine Linux に基づく最新の LTS バージョンの Node.js を使用しています。
  • WORKDIR /app: コンテナ内の作業ディレクトリを設定します。
  • *COPY package.json ./**: package.jsonpackage-lock.json を作業ディレクトリにコピーします。
  • RUN npm install: package.json で指定された依存関係をインストールします。
  • COPY . .: ローカル ディレクトリからコンテナにすべてのファイルをコピーします。
  • EXPOSE 3000: コンテナのポート 3000 を公開します (React のデフォルトポート)。
  • CMD ["npm", "start"]: コンテナの起動時に npm start を実行するように Docker に指示します。

多段階ビルドを使用した運用 Dockerfile

運用環境に対応したイメージの場合は、マルチステージ ビルドを使用してイメージ サイズを最適化し、セキュリティを強化します。

# Build Stage
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Production Stage
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

説明

  • ビルドステージ:
    • FROM node:18-alpine AS build: アプリの構築には Node.js 18 を使用します。
    • RUN npm run build: 最適化されたプロダクション ファイルをビルドします。
  • 生産段階:
    • FROM nginx: Nginx を使用して静的ファイルを提供します。
    • COPY --from=build /app/build /usr/share/nginx/html: 前のステージからビルド出力をコピーします。
    • EXPOSE 80: ポート を公開 80。
    • CMD ["nginx", "-g", "daemon off;"]: フォアグラウンドで Nginx を実行します。

利点

  • イメージ サイズが小さい: 最終的なイメージには、運用ビルドと Nginx のみが含まれます。
  • セキュリティの強化: 開発の依存関係と Node.js ランタイムを運用イメージから除外します。
  • パフォーマンスの最適化:Nginxは静的ファイルを効率的に提供します。

ステップ 3: .dockerignore を作成する ファイル

.gitignoreと同じように Git が特定のファイルを無視するのを助けます .dockerignore イメージのビルド時に除外するファイルまたはディレクトリを Docker に指示します。 .dockerignoreを作成する プロジェクトのルートディレクトリにあるファイル:

node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignore
.env

不要なファイルを除外すると、画像サイズが小さくなり、ビルドプロセスが高速化されます。

ステップ 4: Docker Compose をマルチコンテナ設定に使用する (オプション)

アプリケーションがバックエンド API やデータベースなどの他のサービスに依存している場合、 Docker Compose は複数のコンテナの管理に役立ちます。

compose.ymlファイルを作成します。

services:
  web:
    build: .
    ports:
      - "3000:80"
    volumes:
      - ./app
    environment:
      NODE_ENV: development
    stdin_open: true
    tty: true

説明

  • services: サービス (コンテナー) の一覧を定義します。
  • web:当社のサービスの名前。
    • build: .: 現在のディレクトリに Dockerfile をビルドします。
    • ports: コンテナのポート 3000 をホストのポート 3000 にマッピングします。
    • volumes: 現在のディレクトリとnode_modulesをホットリロード用にマウントします。
    • environment: 環境変数を設定します。
    • stdin_opentty: コンテナを稼働させ、インタラクティブに保ちます。

ステップ 5: Docker 化された React アプリをビルドして実行する

ドッカーイメージの構築

プロジェクトのルートディレクトリに移動し、次のコマンドを実行します。

docker build -t my-react-app .

このコマンドは、イメージに my-react-app. という名前でタグを付けます また、ビルド コンテキスト (現在のディレクトリ) を指定します。

Docker コンテナの実行

開発イメージの場合:

docker run -p 3000:3000 my-react-app

製品イメージの場合:

docker run -p 80:80 my-react-app
  • -p 3000:3000: コンテナのポート 3000 をマシンのポート 3000 にマッピングします。
  • -p 80:80: コンテナのポート 80 をマシンのポート 80 にマッピングします。

次に、ブラウザを開き、 http://localhost:3000 (開発)または http://localhost (本番環境)に移動します。 Dockerコンテナ内でReactアプリが実行されていることがわかります。

ステップ 6: イメージを Docker Hub に公開する

Docker イメージを共有すると、他のユーザーは自分で環境を設定せずにアプリを実行できます。

Docker Hubにログインします。

docker login

プロンプトが表示されたら、Docker Hub のユーザー名とパスワードを入力します。

画像にタグを付ける:

docker tag my-react-app your-dockerhub-username/my-react-app

your-dockerhub-username を実際の Docker Hub ユーザー名に置き換えます。

イメージをプッシュします。

docker push your-dockerhub-username/my-react-app

これで、イメージが Docker Hub で利用可能になり、他のユーザーがプルして実行できるようになります。

イメージをプルして実行します。

docker pull your-dockerhub-username/my-react-app
docker run -p 80:80 your-dockerhub-username/my-react-app

これで、イメージをプルすることで、誰でもアプリを実行できるようになりました。

環境変数の安全な取り扱い

環境変数を安全に管理することは、APIキーやデータベース資格情報などの機密情報を保護するために重要です。

.env の使用 ファイル

.envを作成する プロジェクトのルートにファイル:

REACT_APP_API_URL=https://api.example.com

compose.ymlを更新します。

services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules
    env_file:
      - .env
    stdin_open: true
    tty: true

セキュリティに関する注意:.envを確保 ファイルは .gitignore.dockerignore に追加され、バージョン管理にコミットされたり、Docker イメージに含まれたりするのを防ぎます。

実行時の環境変数の受け渡し

または、コンテナの実行時に変数を渡すこともできます。

docker run -p 3000:3000 -e REACT_APP_API_URL=https://api.example.com my-react-app

Docker シークレットの使用 (詳細)

本番環境の機密データについては、 Docker シークレット を使用して機密情報を安全に管理することを検討してください。

キャッシュを改善するための Dockerfile の最適化

Dockerfile の注文手順を戦略的に活用することで、Docker のキャッシュ メカニズムを活用でき、ビルド時間を大幅に短縮できます。

最適化された Dockerfile の例:

FROM node:18-alpine
WORKDIR /app

# Install dependencies separately to leverage caching
COPY package.json package-lock.json ./
RUN npm install

# Copy the rest of the application code
COPY . .

EXPOSE 3000
CMD ["npm", "start"]

説明:

  • 個別の依存関係のインストール: 最初に package.jsonpackage-lock.json をコピーして npm install を実行することで、Docker は依存関係を含むレイヤーをキャッシュします。
  • 効率的なリビルド:package.jsonが変更されない限り、Docker はキャッシュされたレイヤーを使用するため、コードが変更されても依存関係が同じままの場合、ビルドプロセスが高速化されます。

Docker と React の一般的な問題のトラブルシューティング

最善の指示があっても、問題が発生する可能性があります。 ここでは、一般的な問題とその修正方法を示します。

問題: 「ポート 3000 は既に使用されています」

解決: ポート 3000 を使用してサービスを停止するか、コンテナーの実行時にアプリを別のポートにマップします。

docker run -p 4000:3000 my-react-app

http://localhost:4000でアプリにアクセスします。

問題: 開発中に変更が反映されない

解決: Docker ボリュームを使用して、ホットリロードを有効にします。あなたの compose.ymlで、 以下のものが volumesされていることを確認してください。

volumes:
  - .:/app
  - /app/node_modules

この設定により、ローカルの変更をコンテナ内にミラーリングできます。

問題: ビルド時間が遅い

解決: Dockerfile を最適化してキャッシングを活用します。 npm installを実行する前に、package.jsonpackage-lock.jsonのみをコピーします。このように、Docker はこれらのファイルが変更されない限り、レイヤーをキャッシュします。

COPY package*.json ./
RUN npm install
COPY . .

問題: コンテナがすぐに終了する

原因: React 開発サーバーは、デフォルトではコンテナを実行し続けない場合があります。

解決: コンテナーを対話形式で実行していることを確認します。

docker run -it -p 3000:3000 my-react-app

問題: ファイルのアクセス許可エラー

解決: ファイルのアクセス許可を調整するか、 USER ディレクティブを使用して Dockerfile でユーザーを指定します。

# Add before CMD
USER node

問題: macOS と Windows でのパフォーマンスの問題

ホストシステムと Docker コンテナ間のファイル共有メカニズムは、特に大規模なリポジトリや多くのファイルを含むプロジェクトで作業する場合に、macOS と Windows で大きなオーバーヘッドを引き起こします。 osxfsgRPC FUSEなどの従来の方法では、これらの環境で効率的に拡張するのが難しいことがよくあります。

ソリューション:

同期されたファイル共有を有効にします (Docker Desktop 4.27+): Docker デスクトップ 4.27+ では、 同期されたファイル共有が導入され、Docker Desktop VM 内にホスト ファイルの高パフォーマンスの双方向キャッシュを作成することで、バインド マウントのパフォーマンスが大幅に向上します。

主な利点:

  • 大規模プロジェクト向けに最適化: モノレポや数千のファイルを含むリポジトリを効率的に処理します。
  • パフォーマンスの向上: 古いファイル共有メカニズムで発生していたボトルネックを解決します。
  • リアルタイム同期: ホストとコンテナ間のファイルシステムの変更をほぼリアルタイムで自動的に同期します。
  • ファイル所有権の競合の削減: ホストとコンテナ間のファイル権限の問題を最小限に抑えます。

有効にする方法:

  • Docker Desktop を開き、[設定] > [リソース] > [ファイル共有] に移動します。
  • [ 同期されたファイル共有] セクションで、共有するフォルダを選択し、[ ファイル共有の初期化] をクリックします。
  • docker-compose.yml でバインド マウントを使用するか、共有ディレクトリを指す Docker CLI コマンドを使用します。

.syncignoreで最適化する:.syncignoreを作成する 共有ディレクトリのルートにあるファイル( node_modules, .git/など)を除外します パフォーマンスを向上させるため。

.syncignore ファイル:

node_modules
.git/
*.log

docker-compose.ymlの例:

services:
  web:
    build: .
    volumes:
      - ./app:/app
    ports:
      - "3000:80"
    environment:
      NODE_ENV: development

Windows で WSL 2 を活用します。 Windowsユーザーの場合、DockerのWSL 2 バックエンドは、軽量のLinux VMでDockerエンジンを実行することにより、ネイティブに近いLinuxパフォーマンスを提供します。

バックエンド 2 WSL を有効にする方法:

  • Windows 10 バージョン 2004 以降がインストールされていることを確認します。
  • Windows Subsystem for Linux 2をインストールします。
  • Docker Desktop で、[設定] > [全般 ] に移動し、[ WSL 2 ベースのエンジンを使用する] を有効にします。

ボリュームマウントで更新されたキャッシュオプションを使用します。 :cached:delegated などの従来のオプションは非推奨ですが、整合性モードでは最適化が可能です。

  • consistent: 厳密な整合性 (デフォルト)。
  • cached: ホストがコンテンツをキャッシュできるようにします。
  • delegated: コンテナがコンテンツをキャッシュできるようにします。

ボリューム構成の例:

volumes:
  - type: bind
    source: ./app
    target: /app
    consistency: cached

React Docker セットアップの最適化

いくつかの高度なテクニックでセットアップを強化しましょう。

画像サイズを縮小する

特にクラウド環境にデプロイする場合は、すべてのメガバイトが重要です。

  • 小さい基本イメージを使用する: アルパインベースの画像は大幅に小さくなります。
  • 依存関係のインストール後にクリーンアップします。
RUN npm install && npm cache clean --force
  • 不要なファイルのコピーは避けてください。.dockerignoreを使用する 効果的。

Docker ビルドキャッシュの活用

キャッシュを不必要に無効にしていないことを確認します。 各ビルドステップに必要なファイルのみをコピーします。

Docker レイヤーを賢く使用する

Dockerfile の各コマンドは、新しいレイヤーを作成します。 必要に応じてコマンドを組み合わせて、レイヤーの数を減らします。

RUN npm install && npm cache clean --force

結論

React アプリの Docker 化は、ゲームチェンジャーです。 これにより、開発ワークフローに一貫性、効率性、スケーラビリティがもたらされます。 アプリケーションをコンテナ化することで、環境の不一致を排除し、デプロイメントを合理化し、コラボレーションを簡単に行うことができます。

ですから、次にReactプロジェクトを設定するときは、Dockerを試してみてください。 これにより、開発者としての生活が大幅に楽になります。 コンテナ化の世界へようこそ!

さらに詳しく