実装で学ぶフルスタックWeb開発 エンジニアの視野と知識を広げる「一気通貫」型ハンズオン
という本を今読んでいます。
この本のなかでは、フロントエンド、バックエンド、DBの環境はdocker composeを使わず、それぞれ独立したコンテナとして構築していたのですが、docker composeプロジェクトで構築してみたいと思ったので、その内容を実践してみたメモを書きます。
要約
- docker compose up一発でDB、フロントエンドサーバー、バックエンドサーバーを起動可能
- docker-compose.ymlで定義した各コンテナサービスは、networkの指定がない場合、デフォルトブリッジネットワークに追加される
- コンテナ内 -> 外の通信を、フロントエンド -> バックエンド、 バックエンド -> DBで通信接続できることを確認
- 実際のコードはこちら
環境
- Macbook Pro M1
- Docker Compose version v2.24.6-desktop.1
構成イメージ
docker-compose.ymlの記述
docker-compose.yml
services:
app-db:
image: mysql:8
command:
--collation-server=utf8mb4_0900_bin
--transaction-isolation=READ-COMMITTED
restart: always
container_name: app-db
hostname: app-db
environment:
MYSQL_USER: root
MYSQL_ROOT_PASSWORD: password
TZ: Asia/Tokyo
ports:
- 53306:3306
app-frontend:
build: ./dev/app/frontend
container_name: app-frontend
hostname: app-frontend
volumes:
- $PWD/dev/app/frontend:/app
- $PWD/dev/app/frontend/node_modules:/app/node_modules
ports:
- 3000:3000
environment:
NODE_ENV: development
stdin_open: true
app-backend:
build: ./dev/app/backend
container_name: app-backend
hostname: app-backend
volumes:
- $PWD/dev/app/backend:/go/src/app
ports:
- 4000:4000
stdin_open: true
Dockerfileの記述
frontend/Dockerfile
FROM node:20-alpine
WORKDIR /app/
COPY ./package.json ./
COPY src ./src
# buid時に実行
RUN yarn install
# コンテナ起動時に実行
CMD ["yarn", "dev"]
backend/Dockerfile
FROM golang:1.19-alpine
# ログに出力する時間をJSTにするため、タイムゾーンを設定
ENV TZ /usr/share/zoneinfo/Asia/Tokyo
ENV ROOT=/go/src/app
WORKDIR ${ROOT}
# ModuleモードをON
ENV GO111MODULE=on
COPY . .
EXPOSE 4000
# Airをインストールし、コンテナ起動時に実行する
# go1.19をサポートしているのは air v1.41.0
RUN go install github.com/cosmtrek/air@v1.41.0
CMD ["air"]
networkの確認
docker compose では、networkの指定がなければ、デフォルトのブリッジネットワークに各コンテナを登録します。
$ docker network ls
でネットワークを確認すると、
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
1bbc5d4c0d99 fullstack-react-go_default bridge local
デフォルトのネットワークが追加されており、これをdocker network inspect で確認すると、各コンテナサービスが同一ネットワークに追加されていることを確認できます。
$ docker network inspect fullstack-react-go_default
[
{
"Name": "fullstack-react-go_default",
"Id": "1bbc5d4c0d99c70d54d4518de6708bc137522696f2fd069ca170ebfdd37dee24",
"Created": "2024-03-20T02:26:36.947254879Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "xxxxxxxxxx",
"Gateway": "xxxxxxxxxx"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
# 各コンテナサービスが同一ネットワークに追加していることが確認できる
"Containers": {
"1e425d166b409a10dd721d16acba68a2a53159e89299f2ef2fc0c19aa4d13401": {
"Name": "app-backend",
"EndpointID": "5518afa96388efc2fc3f016cf36b6a24c25d88a76a487be9a8299121c38cd97e",
"IPv4Address": "xxxxxxxxxx",
"IPv6Address": ""
},
"34a1d7f3cfe58a3dd3cb8a9fbe943ef0094448f385f53e4a35f6dd0c9f4aace5": {
"Name": "app-db",
"EndpointID": "882bb1c9e69fe82b97998815aaea872d4f44d4f853bc17a929c6769364d6e615",
"IPv4Address": "xxxxxxxxxx",
"IPv6Address": ""
},
"c8fd9eef063a266f2be5727619464a0fe02607bd0c6f8b6f587cdf347a9ad67d": {
"Name": "app-frontend",
"EndpointID": "0f91d208a035d9330939f186e804b5f0fe8783fd2b693c2fa5f7795798d69028",
"IPv4Address": "xxxxxxxxxx",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "default",
"com.docker.compose.project": "fullstack-react-go",
"com.docker.compose.version": "2.23.3"
}
}
]
通信の確認
同一ネットワークに追加していれば、各コンテナ内から別のコンテナへ名前解決を行い通信することができます。
frontend -> backendの通信を確認。
$ docker exec -it app-frontend sh
/app # curl http://app-backend:4000
Hello!
# 接続OK
backend -> dbの通信を確認。
$ docker exec -it app-backend sh
# mysql -u root -h app-db -P 3306 --protocol tcp -ppassword
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 13
Server version: 8.3.0 MySQL Community Server - GPL
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
# 接続OK
各コンテナ間の通信を確認することができました。