LoginSignup
12
9

Dockerでフロントエンド(React)+バックエンド(TypeScript)+DB(MySQL)の開発環境を構築してみた

Posted at

はじめに

この記事はDockerについて何もわからないLv.1のエンジニアが時代についていくために
Dockerでフロントエンド+バックエンド+DBの開発環境を構築してみようと思い立った顛末を記した記事です。

Dockerってなんだ?

まずDockerとはそもそも何なのか、
なんとなく下記のようなイメージを抱いていました。

  • いわゆるコンテナ的なもの?
  • アプリケーションの実行がお手軽にできる
  • 開発環境構築が楽になるらしい
  • 何もわからん!!!

Dockerとは

Docker社の開発したオープンソースのコンテナ型プラットフォーム。
Dockerを使用すると一台のPCで複数のコンテナ(アプリケーションの実行環境パッケージ)を立てて実行することができるようになるらしい。
つまり、お手軽にアプリケーションの実行環境を用意できるもの?

Dockerの用語たち

Dockerエンジン

色々な処理を行うDockerの本体のようなもの。
CLIとREST API、Dockerデーモンの3つで構成されていて
CLIでコマンドを打つとREST APIが叩かれてサーバー(Dockerデーモン)に処理内容を伝えてくれるらしい。

Dockerコンテナ

Dockerが実行するコンテナのこと。
そのままの名前。

Dockerイメージ

Dockerコンテナを実行するためのテンプレートのようなもの。
Dockerイメージを実行することでDockerコンテナを生成し、アプリケーションを実行させることができる。
Dockerレジストリ(後述)に登録されているイメージをPullして用意するほか、Dockerfile(後述)からビルドすることで自身でカスタマイズしたDockerイメージを用意することも可能。

つまり、流れとしてはこんな感じ?
DockerHub → (Pull) → Dockerイメージ → (実行) → Dockerコンテナ
Dockerfile → (ビルド) → Dockerイメージ → (実行) → Dockerコンテナ

Dockerレジストリ

作成したDockerイメージを保管するサービス。
Docker Hub(GitHub的なイメージ?)やAWS Elastic Container Registry等があり、公開されているイメージをPullして利用することもできる。

Dockerfile

Dockerイメージの設計ファイル。
Dockerfileを書くことで自身でカスタマイズしたDockerイメージを作成することができる。

Docker Compose

複数のDockerコンテナを操作するためのツール。
docker-compose.ymlという設定ファイルを定義することで複数コンテナの起動や停止、ビルド等をまとめて行うことができて便利らしい。

動かしてみよう

なんとな~~~くDockerについて理解を深めた(つもりになった)ところで実際に動かしてみることにします。
まずはDockerのインストールから。

Docker DesktopなるソフトウェアはGUIで色々操作ができるほか、インストールするとDockerエンジンやCLI、Docker Compose等をまとめてインストールしてくれるそうなのでDocker Desktopをインストールします。
利用にはDocker Hubのアカウントを作る必要があるそうなのでまずはアカウントを作成。
今回は個人利用目的なのでPersonalプランでアカウントを作り、早速Docker Desktop on Windowsをインストール。

nginxをDockerで動かしてみる

インストールが完了したら早速Dockerを動かしてみようということで、
nginxのDockerイメージからDockerコンテナを動かしてみます。

↓作業するディレクトリ構造はこんな感じです。

root
┣ index.html
┣ Dockerfile
┗ docker-compose.yml

Dockerfile

今回はとりあえず動かすだけなのでDockerfileをわざわざ作る必要もないですが、Dockerfileから作る流れを知るためにDockerfileから作ってみます。

# ベースとなるイメージを指定
# nginxが提供している最新バージョンのイメージを指定している
FROM nginx:latest

# 作業を行うディレクトリを指定
# nginxのイメージはこのディレクトリで色々作業するらしい
WORKDIR /usr/share/nginx

# ローカルのindex.htmlを/usr/share/nginx/html配下にコピーする
COPY ./index.html ./html
index.htmlの中身はどうでもいいので折りたたみます。
index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>nginx × Dockerサンプル</title>
</head>
<body>
    <h1>nginxをDockerで動かしてみるよ!!</h1>
</body>
</html>

Dockerfile(とindex.html)が書けたらDockerfileからイメージをビルドしてコンテナを実行します。

# Dockerfileから`nginx-sample-image`という名前でイメージをビルド
docker image build ./ -t nginx-sample-image

# nginx-sample-imageから`nginx-sample`という名前でコンテナを実行する
# -p 8080:80でホストPCの8080ポートとコンテナ上の80ポートを紐づけ(ポートフォワード)
docker run --name nginx-sample -p 8080:80 nginx-sample-image

http://localhost:8080 へアクセスしてみると・・・
image.png

無事コンテナを動かすことができました。

Docker Compose

Docker Composeでも動かしてみようということで、
docker-compose.ymlを作成します。

docker-compose.yml
# docker-composeファイルのバージョン
version: '3'

# アプリケーションを構成するサービスの設定
services:
  web:
    # Dockerビルドの設定
    build: 
      context: .
      dockerfile: ./Dockerfile
    # サービスで使用するポートを指定する
    ports:
      - 8080:80

docker-compose.ymlを作成したらイメージをビルドして実行します。

# docker-composeでDockerイメージをビルドする
docker-compose build

# Dockerコンテナを実行する
docker-compose up

アクセスしてみると・・・
image.png

Docker Composeでもコンテナを動かすことができました。

開発環境を作る

さて、Docker初心者がとりあえず触ってみた編を終えたところで
いよいよDockerを用いた開発環境を作っていきます。

DevContainer

VSCodeの拡張機能「Remote Development」を利用すると開発用DockerコンテナにVSCodeからアクセスし、コンテナ内のファイルを直接編集することができるようになります。
DevContainerを使うことでローカルPC上にライブラリや各種拡張機能等々が入り混じってごちゃついてしまう現象を解消することが可能となるらしく、便利そうなので利用してみます。

root
┣ frontend
┗ backend

フロントエンド

frontendディレクトリにひな型を作成します。
本当はDevContainerの中で作業を行うようにしたかったのですが、
DevContainerの中でうまいことcreate-react-appができなかったのであきらめてローカルで作りました。。。

# frontendのひな型を作成
cd frontend

npx create-react-app . --template typescript

# ローカルに不要なnode_modulesを消す
rm -r node_modules

バックエンド

backendディレクトリにひな型を作成します。

# backendのひな型を作成
cd backend

npm init -y

# 必要なパッケージをインストール
npm i -D typescript nodemon ts-node

npx tsc --init

mkdir src

touch src/index.ts

touch nodemon.json

# ローカルに不要なnode_modulesを消す
rm -r node_modules

tsconfing.jsonを適当に弄り、

tsconfig.json
{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "rootDir": "./src",
    "outDir": "./dist",
    "strict": true,
    "skipLibCheck": true
  }
}

ホットリロードの設定を行います。

package.json
{
  "name": "backend",
  "version": "1.0.0",
  "description": "",
  "devDependencies": {
    "nodemon": "^3.0.1",
    "ts-node": "^10.9.1",
    "typescript": "^5.2.2"
  },
  "scripts": {
    "dev": "npx nodemon"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
nodemon.json
{
    "watch": ["src"],
    "ext": "ts",
    "exec": "npx ts-node ./src/index.ts"
}

DevContainer

各Dockerコンテナ用のDevContainer設定ファイルを追加します。

frontend/.devcontainer.json
{
    "name": "Frontend",
    "dockerComposeFile": ["../docker-compose.yml"],
    "service": "frontend",
    "shutdownAction": "none",
    "workspaceFolder": "/workspace/frontend"
}
backend/.devcontainer.json
{
    "name": "Backend",
    "dockerComposeFile": ["../docker-compose.yml"],
    "service": "backend",
    "shutdownAction": "none",
    "workspaceFolder": "/workspace/backend"
}

DockerFile

各Dockerfileの設定を行います。

root
┣ frontend
┃  ┣ src
┃  ┣ public
┃  ┣ package.json
┃  ┣ tsconfig.json
┃  ┗ .devcontainer.json
┣ backend
┃  ┣ src
┃  ┣ nodemon.json
┃  ┣ package.json
┃  ┣ tsconfig.json
┃  ┗ .devcontainer.json
┗ docker
   ┣ frontend.Dockerfile
   ┣ backend.Dockerfile
   ┗ db.Dockerfile
frontend.Dockerfile
FROM node:20

WORKDIR /workspace/frontend

COPY ../frontend/ ./

RUN npm install

# コンテナ起動時に実行するコマンド
CMD [ "npm", "start" ]
backend.Dockerfile
FROM node:20

WORKDIR /workspace/backend

COPY ../backend/ ./

RUN npm install

# コンテナ起動時に実行するコマンド
CMD ["npm", "run", "dev"]

dbはとりあえずMySQLの実行環境のみ用意(正直Dockerfileは要らない)。

db.Dockerfile
FROM mysql:latest

docker-compose.yml

docker-compose.yml
version: '3'

services:
  # frontendの設定
  frontend:
    container_name: docker-sample-frontend
    build: 
      context: .
      dockerfile: ./docker/frontend.Dockerfile
    environment:
      # Reactのホットリロードを有効化するための設定
      - WATCHPACK_POLLING=true
    volumes:
      # ルートディレクトリ配下をworkspace配下にマウントする
      - .:/workspace:cached
      # node_modulesは別ボリュームでマウントする
      - frontend_node_modules:/workspace/frontend/node_modules
    ports:
      - '8080:3000'
  # backendの設定
  backend:
    container_name: docker-sample-backend
    build:
      context: .
      dockerfile: ./docker/backend.Dockerfile
    environment:
      # nodemonでホットリロードを有効化するための設定
      - CHOKIDAR_USEPOLLING=true
    volumes:
      # ルートディレクトリ配下をworkspace配下にマウントする
      - .:/workspace:cached
      # node_modulesは別ボリュームでマウントする
      - backend_node_modules:/workspace/backend/node_modules
    ports:
      - '3000:3000'
  # dbの設定
  db:
    container_name: docker-sample-mysql
    build:
      context: .
      dockerfile: ./docker/db.Dockerfile
    ports:
      - '3306:3306'
    environment:
      MYSQL_ROOT_PASSWORD: mysql
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      TZ: Asia/Tokyo
    volumes:
      # MySQLのデータをボリュームにマウントする
      - db-store:/var/lib/mysql

# ボリュームの設定、実行時に作ってくれる
volumes:
  frontend_node_modules: 
  backend_node_modules:
  db-store:

最終的に以下のようなディレクトリ構造になりました。

root
┣ frontend
┃  ┣ src
┃  ┣ public
┃  ┣ package.json
┃  ┣ tsconfig.json
┃  ┗ .devcontainer.json
┣ backend
┃  ┣ src
┃  ┣ nodemon.json
┃  ┣ package.json
┃  ┣ tsconfig.json
┃  ┗ .devcontainer.json
┣ docker
┃  ┣ frontend.Dockerfile
┃  ┣ backend.Dockerfile
┃  ┗ db.Dockerfile
┗ docker-compose.yml

開発用Dockerコンテナにアクセスする

さて、ここまで出来たら開発用コンテナにアクセスして開発してみましょう。
VSCodeからfrontendプロジェクトを開き、F1 >「Dev Containers: Reopen in Container」を選択するとfrontendコンテナにVSCodeからアクセスすることができます。

image.png

開発コンテナ frontendにアクセスできました。
これでコンテナ内のファイルを直接編集することができるようになります。
また、ソースコードはホストPCのディレクトリとマウントされているため、DevContainer内での変更内容はホストPCにもしっかり反映されます。
image.png

更に、DevContainerを起動すると、.devcontainer.jsonで指定したdocker-compose.ymlに基づいて(?)、関連するコンテナをまとめて起動してくれます。
今回であればfrontendのDevContainerの起動に合わせてbackend、dbのDockerコンテナも起動してくれます。

おわりに

さて、何とかDockerとDevContainerを用いてReact×TypeScript×MySQLの開発環境構築ができました。

・・・が、結局Dockerについて詳しくなれた気がしませんね。
調べれば調べるほどわからないことが増えていく不思議。
なんとかLv.1.1くらいにはなれたと信じて今後も勉強していきたいです。

参考

12
9
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
12
9