見出し画像

CentOSでMySQLを動かせるようにするまで ~docker docker-compose~

はじめに

こんにちは、SHIFT の開発部門に所属しているKatayamaです。今期から転属になり、開発を担当していくことになりました。

現在、基本的な事から学ぶ研修中です。開発部門では新しく学ぶことがたくさんあり、それらを自身の振り返りアウトプットとして発信していけたらと思います。記事が溜まったら、noteのマガジンにもまとめる予定です。

■前提条件

・virtualbox で CentOS のディスクイメージで Linux 環境を構築済み

# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)


■docker で MySQL Server を起動する

・docker のインストール

まずは CentOS を最新化する。

# yum update
# yum upgrade

OS requirements

The centos-extras repository must be enabled.

と書かれているので、yum リポジトリを確認して有効化されている事をチェック(基本デフォで登録済みで有効化されている)。

# cat /etc/yum.repos.d/CentOS-Base.repo

省略
#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

省略


素直にInstallation methodsでおすすめと言われている方法([Set up the repository](Set up the repository))でやる

※やり方は公式の通りで、Option の test repo の追加とは特に skip でもいい

※sudo が面倒であれば、Manage Docker as a non-root userに沿って設定をすればいい

・参考:Install Docker Engine on CentOS

・MySQL 公式 の docker image を使って MySQL Server を起動

# docker container run -d -p 3306:3306 --name mysql-container -e MYSQL_ROOT_PASSWORD=mysql mysql:5.7.35
# docker container exec -it mysql-container mysql -u root -p

※docker container exec コマンドで、起動しているコンテナ上でコマンドを実行できるので、mysql server にログインできる

※-p"mysql"のようにすると、Enter password: でパスワード入力が求められず直でログインできるがセキュリティ上よくない

・参考:docker hub MySQL
・参考:Use the Docker command line
・参考:docker container exec

・データベースを構築する

構築はあえてコマンドラインで実行したが、Navicat for MySQL で GUI 上からも構築できる。

mysql> CREATE DATABASE `todo`;
mysql> USE `todo`;
mysql> DROP TABLE IF EXISTS `todos`;
mysql> CREATE TABLE `todos` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `description` varchar(255) COLLATE utf8mb4_unicode_ci,
  `is_complete` boolean,
  `assagin_person` varchar(255) COLLATE utf8mb4_unicode_ci,
  `updated_at` datetime NOT NULL,
  `created_at` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
mysql> INSERT INTO `todos` (`title`, `is_complete`, `updated_at`, `created_at`) values ('Buy Milk', false, '2021-10-06 18:00:00', '2021-10-06 18:00:00');
mysql> INSERT INTO `todos` (`title`, `description`, `is_complete`, `updated_at`, `created_at`) values ('Buy Book', 'Plase buy book by tomorrow', true,'2021-10-06 18:00:00', '2021-10-06 18:00:00');

データベースの中を見てみると・・・

mysql> SELECT * FROM `todos`;
+----+----------+----------------------------+-------------+----------------+---------------------+---------------------+
| id | title    | description                | is_complete | assagin_person | updated_at          | created_at          |
+----+----------+----------------------------+-------------+----------------+---------------------+---------------------+
|  1 | Buy Milk | NULL                       |           0 | NULL           | 2021-10-06 18:00:00 | 2021-10-06 18:00:00 |
|  2 | Buy Book | Plase buy book by tomorrow |           1 | NULL           | 2021-10-06 18:00:00 | 2021-10-06 18:00:00 |
+----+----------+----------------------------+-------------+----------------+---------------------+---------------------+
2 rows in set (0.00 sec)

となっており、やりたい事はできている事が確認できた。

・参考:Mysql の boolean 型について調べてみた
・参考:Navicat for MySQL 評価版ダウンロード

・docker で簡単にできるが、だがしかし・・・

今のままだと作成したデータベースのスキーマ(DDL)とデータそのものを自分でコマンドで引っ張り出して保存しておき、新しい環境で mysql サーバを立ち上げるときはその sql を 1 から実行して、データベースの構築・データの insert をして…という手間が発生する。

そこで docker-compose を使って 1 コマンドで mysql の環境セットアップ(DB 構築・データの insert)が全て完結するするように設定をする。

※docker-compose にする理由は他にもあり、

・複数のコンテナを起動できる

とかの別のメリットもある(というかこっちが本当のメリットのよう)。

・参考:docker-compose とは?docker コマンドとの違いを理解しよう【Docker 入門 ⑥】
・参考:docker-compose と docker コマンドを比較しながら使い方の違いを解説
・参考:docker-compose の書き方! 分かりやすい DockerFile との違い


■docker-compose で MySQL Server を起動し操作する

・docker-compose のインストール

Install Docker Composeに沿ってやればいい。docker の方が入っていることが前提になる。

・MySQL Server を起動するための準備

docker image は MySQL 公式 のものを利用する。他には docker-compose.yml と、今回は初期化時にデータベースの初期構築もしたいので schema.sql を作成する。

# docker-compose.yml
version: "3.9"
services:
  mysql:
    image: mysql:5.7.35
    container_name: mysql-compose-container
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /password-root
    volumes:
      - ./password-root:/password-root
      - ./data/mysql:/var/lib/mysql
      - ./sql:/docker-entrypoint-initdb.d
    ports:
      - 3306:3306
/* schema.sql */
DROP DATABASE IF EXISTS `todo`;
CREATE DATABASE IF NOT EXISTS `todo`;
USE `todo`;

DROP TABLE IF EXISTS `todos`;
CREATE TABLE `todos` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `is_complete` tinyint(1) DEFAULT NULL,
  `assagin_person` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `updated_at` datetime NOT NULL,
  `created_at` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

・参考:Get started with Docker Compose
・参考:Overview of docker-compose CLI
・参考:Docker Secrets

・docker-compose で MySQL Server を起動

docker-compose up -d コマンドでコンテナが起動する。

実際に MySQL Server に接続してデータベースとテーブルが作成されているか?を確認すると・・・

# docker container exec -it mysql-compose-container mysql -u root -p

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| todo               |
+--------------------+
5 rows in set (0.00 sec)

mysql> USE `todo`;

mysql> SHOW CLOUMNS FROM `todos`;
+----------------+------------------+------+-----+---------+----------------+
| Field          | Type             | Null | Key | Default | Extra          |
+----------------+------------------+------+-----+---------+----------------+
| id             | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| title          | varchar(255)     | NO   |     | NULL    |                |
| description    | varchar(255)     | YES  |     | NULL    |                |
| is_complete    | tinyint(1)       | YES  |     | NULL    |                |
| assagin_person | varchar(255)     | YES  |     | NULL    |                |
| updated_at     | datetime         | NO   |     | NULL    |                |
| created_at     | datetime         | NO   |     | NULL    |                |
+----------------+------------------+------+-----+---------+----------------+
7 rows in set (0.03 sec)

mysql> SELECT * FROM `todos`;
Empty set (0.00 sec)

というようにデータベース・テーブルが作成できている事が確認できる ここにデータベースを構築するで insert したデータを入れて、その後 docker-compose down で作成したコンテナを消して再度 docker-compose up -d を実行すると・・・

# docker-compose down
# docker-compose up -d
# docker container exec -it mysql-compose-container mysql -u root -p
mysql> USE `todo`;
mysql> SELECT * FROM `todos`;
+----+----------+----------------------------+-------------+----------------+---------------------+---------------------+
| id | title    | description                | is_complete | assagin_person | updated_at          | created_at          |
+----+----------+----------------------------+-------------+----------------+---------------------+---------------------+
|  1 | Buy Milk | NULL                       |           0 | NULL           | 2021-10-06 18:00:00 | 2021-10-06 18:00:00 |
|  2 | Buy Book | Plase buy book by tomorrow |           1 | NULL           | 2021-10-06 18:00:00 | 2021-10-06 18:00:00 |
+----+----------+----------------------------+-------------+----------------+---------------------+---------------------+
2 rows in set (0.00 sec)

のように、ちゃんとデータも保存されてコンテナを破棄する前の状態と全く同じ状態で MySQL Server を立ち上げることができた。

これはMySQL Server を起動するための準備の volumes キーに書いた内容のおかげでこうなっている。

・./sql:/docker-entrypoint-initdb.d
  docker Hub の MySQL 公式に書かれている(Initializing a fresh instance)ように、/docker-entrypoint-initdb.d 以下に初期化用の SQL(DDL)などを置くことで、最初に image を起動したときにデータベースの初期構築をしてくれるので、ここに schema.sql を今回は配置しておく事で todo というデータベースと todos というテーブルが初期化時に構築される。

ついでに volumes に定義されている他の内容も見ると・・・

・./password-root:/password-root
 パスワードをホスト(今回だと CentOS)の docker-compose.yaml があるルートディレクトリの password-root から読み取るようにしている(docker コンテナ内の password-root というファイルの中身は、ホストの password-root の中身と一致させるという事)。

・./data/mysql:/var/lib/mysql
  mysql のデータはデフォルトでは /var/lib/mysql 以下に格納されることになるが、これをホスト側にコピーしておくことで、この中身を使って docker-compose up でコンテナを構築する時に自動的にテーブルにデータを反映させておくことができる。

※volumes はデータの永続化を目的とした機能

・参考:docker-compose up
・参考:docker-compose down
・参考:Volume configuration reference

■Tips

・MySQL 用語

DDL(Data Definition Language)とは、データ定義言語と呼ばれ、データベース内の表・ビュー・インデックスなどの各種オブジェクトの作成や変更をするための SQL 文

・参考:MySQL 事始 SQL 文(5) DDL

・yaml

インデントに space のみしか使えない(tab は NG)

・参考:yaml.scanner.ScannerError: while scanning for the next token found character '\t' that cannot start any token

■まとめとして

docker, docker-composeの違いを少しは理解できたが、実際にdockerで複数のコンテナを立ち上げてネットワークを作って…という苦労と、docker-composeならこうなってうれしい!という部分を実感できていないので、それは今後やってみたい。 また、AWSのECSにアプリをDeployし、Auroraに接続して…とかももやってみたい。

★マガジンができました AWS DevOpsソリューション

__________________________________

執筆者プロフィール:Katayama Yuta
SaaS ERPパッケージベンダーにて開発を2年経験。 SHIFTでは、GUIテストの自動化やUnitテストの実装などテスト関係の案件に従事したり、DevOpsの一環でCICD導入支援をする案件にも従事。 最近開発部門へ移動し、再び開発エンジニアに。座学で読み物を読むより、色々手を動かして試したり学んだりするのが好きなタイプ。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/