0
0

docker-composeでNode.jsコンテナとMySQLコンテナを立ち上げる

Last updated at Posted at 2024-05-14

目的

docker-composeを使用して、アプリコンテナとDBコンテナを起動する。
コンテナ起動のみを目的とするため、docker-composeの動作を確認することをメインに進める。

目標

  • DBコンテナ作成
  • Nodeコンテナ作成とHello, World.
  • DBにテーブル作成・初期データ投入

起動方法

以下コマンドでdocker-compose.ymlをもとに起動される

docker-compose up -d

実装手順

DBコンテナを作成して、DBが作成されているか確認

docker-compose.ymlでMySQLコンテナの作成

yml docker-compose.yml
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の設定を指定。

cnf ./SQL/my.cnf
[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

Dockerfile ./SQL/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

yml 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 --saveexpressejsをインストール

バックエンド用のapp.js./backend-src配下に作成する。

js ./backend-src/app.js
// 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のみ

ejs ./resources/views/index.ejs
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コンテナを追加する。

yml docker-compose.yml
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を記述する。

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.sqldocker-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つコンテナが立ち上がるか見ながら進めたら案外うまくできた。
細かい部分は調査しきれていないので、今後も調査する必要がある。

疑問点、ご指摘ありましたらコメントお願いいたします。

0
0
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
0
0