目的
docker-compose
を使用して、アプリコンテナとDBコンテナを起動する。
コンテナ起動のみを目的とするため、docker-compose
の動作を確認することをメインに進める。
目標
- DBコンテナ作成
- Nodeコンテナ作成とHello, World.
- DBにテーブル作成・初期データ投入
起動方法
以下コマンドでdocker-compose.yml
をもとに起動される
docker-compose up -d
実装手順
DBコンテナを作成して、DBが作成されているか確認
docker-compose.yml
でMySQLコンテナの作成
version: '2.1'
services:
db:
# イメージの指定(オフィシャルMySQLイメージ)
image: mysql:8.4.0
# コンテナ名
container_name: mysql-container
# ポートの紐づけ
ports:
- "3306:3306"
# 環境変数の設定
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: basic_compose
TZ: "Asia/Tokyo"
# MySQLの設定をmy.cnfで指定。
# my.cnfを以下でインスタンス内`/etc/mysql/conf.d/my.cnf`に配置
volumes:
- ./SQL/my.cnf:/etc/mysql/conf.d/my.cnf
my.cnf
でMySQLの設定を指定。
[mysqld]
character_set_server = utf8mb4
collation_server = utf8mb4_ja_0900_as_cs # 照合順序
[mysql]
default-character-set = utf8mb4
[client]
default-character-set = utf8mb4
この段階でターミナルでdocker-compose up -d
を実行することでMySQLコンテナの作成と、DBの作成がされる。
docker-compose.yml
で指定したMYSQL_DATABASE
が作成されている。
$ docker exec -it e360ca59b925 bash
bash-5.1# mysql -u root -p
mysql: [Warning] World-writable config file '/etc/mysql/conf.d/my.cnf' is ignored.
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.4.0 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| basic_compose |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql>
DB追加されているが、なんかWarningが出てる。
mysql: [Warning] World-writable config file '/etc/mysql/conf.d/my.cnf' is ignored.
よくわからないけど、追加したmy.cnf
が無視されているっぽい。
調べてみると、パーミッションで全員が書き込み可能になっているから無視されているらしいので、chmod 644
などに変えてみると解決しそう。
コンテナ起動後にコマンド実行が必要になるので、めんどくさいけどMySQL用のDockerfileを作成してchmod
する。
MySQL用のDockerfile
FROM mysql:8.4.0
# my.cnfを以下でインスタンス内`/etc/mysql/conf.d/my.cnf`に配置
COPY ./my.cnf /etc/mysql/conf.d/my.cnf
# my.cnfの権限を変更
RUN chmod 644 /etc/mysql/conf.d/my.cnf
EXPOSE 3306
これにより変更を加えたdocker-compose.yml
version: '2.1'
services:
db:
# ./SQL配下にあるDockerfileからビルド
build: ./SQL
# コンテナ名
container_name: basic-mysql-container
# ポートの紐づけ
ports:
- "3306:3306"
# 環境変数の設定
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: basic_compose
TZ: "Asia/Tokyo"
こんな感じで、再度docker-compose up -d --build
する。
--build
はオプションで、ビルドの強制をする。
以下変更後のMySQLコンテナ。Warningが消えてる。
$ docker exec -it 1d077fb30dec bash
bash-5.1# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.4.0 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| basic_compose |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
nodeでhello, worldして、docker-composeで動かす
npm init
でプロジェクトを初期化
npm install express ejs --save
でexpress
とejs
をインストール
バックエンド用のapp.js
を./backend-src
配下に作成する。
// expressモジュールのロード、インスタンス化してappに代入
var express = require("express")
var app = express()
// View EngineにEJSを指定。
app.set('view engine', 'ejs');
// viewsディレクトリを変更
// デフォルトは`./views`
app.set('views', './resources/views')
// listen()メソッドでリッスンポートの指定
var server = app.listen(3000, function() {
console.log("Node.js is listening to PORT:" + server.address().port)
})
// 移行、アプリケーション処理
app.get("/", function(req, res, next) {
res.render("index.ejs")
})
./resources/views
配下に静的ファイルindex.ejs
を配置
今回はHello, Worldのみ
Hello, world.
アプリケーションコンテナビルド用のDockerfileをアプリケーションディレクトリ直下に作成する。
FROM node:18.18.0
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY ./backend-src ./backend-src
COPY ./resources ./resources
EXPOSE 3000
CMD ["node", "./backend-src/app.js"]
docker-compose.yml
にNodeコンテナを追加する。
version: '2.1'
services:
app:
# アプリケーションディレクトリ直下のDockerfileからビルド
build: .
# コンテナ名
container_name: basic-node-container
# ポートの紐づけ
ports:
- 3000:3000
# 依存関係の設定
depends_on:
- db
# 環境変数
#URLはlocalhostではなく、docker-composeで指定しているservicesのdbを指定
environment:
DATABASE_URL: mysql://root:root@db:3306/basic_compose
db:
# ./SQL配下にあるDockerfileからビルド
build: ./SQL
# コンテナ名
container_name: basic-mysql-container
# ポートの紐づけ
ports:
- "3306:3306"
# 環境変数の設定
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: basic_compose
TZ: "Asia/Tokyo"
アプリコンテナの環境変数部分はよくわかっていない。
今回はなくても問題ないため、調査は後回し。
これでdocker-compose up
を実行することでHello, World.できた。
注意点
docker-compose up
で一度ビルドしたイメージを変更しビルドし直したい場合、既にあるイメージを削除してから、もしくは--build
オプションを付ける必要がある。
views
ディレクトリをアプリケーションディレクトリ直下に配置していない場合、app.set
で指定しなおす必要がある。デフォルトではアプリケーションディレクトリ直下のviews
ディレクトリを参照する。
当たり前だが、package*.json
を配置した後、npm install
を実行しないと、依存パッケージインストールがされないため、buildでコケる。
DBにテーブル作成と初期データを投入する
やり方として、初期化sqlを実行させる。
./SQL/init
配下にsql.sql
というファイルを作成し、SQLを記述する。
-- DBの指定
USE basic_compose;
-- 既にテーブルが存在する場合、削除する
DROP TABLE IF EXISTS user;
-- テーブルの作成
CREATE TABLE user (
id int(10) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
-- 初期データの投入
INSERT INTO user (name) VALUE ("satou");
INSERT INTO user (name) VALUE ("tanaka");
INSERT INTO user (name) VALUE ("ito");
docker-entrypoint-initdb.d
にSQLファイルを配置すると、起動時に実行してくれるらしい。
Dockerfile
で上記ファイルsql.sql
をdocker-entrypoint-initdb.d
に配置する。
FROM mysql:8.4.0
# my.cnfを以下でインスタンス内`/etc/mysql/conf.d/my.cnf`に配置
COPY ./my.cnf /etc/mysql/conf.d/my.cnf
# my.cnfの権限を変更
RUN chmod 644 /etc/mysql/conf.d/my.cnf
# sql.sqlをインスタンス内の`docker-entrypoint-initdb.d`に配置
COPY ./init/sql.sql /docker-entrypoint-initdb.d/sql.sql
EXPOSE 3306
この状態でdocker-compose up -d
すると初期データが投入されたmysqlコンテナが作成される。
注意点
エラーが発生するとコンテナが立ち上がるが数秒後に落ちることがある。
エラーが発生した際はコンテナIDからdocker logs
でログを確認するか、どこでエラーが発生しているか予測して、該当部分をコメントアウト等で実行してみる。
今回の場合、SQLのシンタックスエラーなどで落ちた。
上記sql.sql
だと、毎回テーブルが削除されるため既存データまで破棄されることになる。
後日どうするべきか調査する。
まとめ
曖昧だったdocker-composeについて、複数コンテナの立ち上げのみに絞って簡単にやってみた。
最終目標はコンテナを複数立ち上げることなので、1つ1つコンテナが立ち上がるか見ながら進めたら案外うまくできた。
細かい部分は調査しきれていないので、今後も調査する必要がある。
疑問点、ご指摘ありましたらコメントお願いいたします。