Docker 環境で MySQL を使用する：Dockerfile

# Docker 環境で MySQL を使用する：Dockerfile

こんにちは、@studio_meowtoon です。今回は、WSL の Ubuntu 24.04 の Docker 環境で MySQL を使用する手順を紹介します。
![mysql_on_docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/51e87d39-a79b-a8d3-dd8b-38b1215933eb.png)

## 目的

Windows 11 の Linux でクラウド開発します。

こちらから記事の一覧がご覧いただけます。

https://qiita.com/studio_meowtoon/items/6119ab05d8b13527efd8

## 実現すること

ローカル環境の Ubuntu の Docker 環境で、MySQL コンテナーを起動します。

**MySQL をコンテナーとして起動**
```mermaid
flowchart LR
    terminal --> app[mysql]
    subgraph Ubuntu
        subgraph Docker
            subgraph container[mysql-todo]
                subgraph mysql
                    app[db_todo]
                end
            end
        end
    end
style Ubuntu fill:#FFBCA4, stroke:#E0460F
style Docker fill:#EEFDFF, stroke:#74B9DC
style container fill:#FFD7E4, stroke:#E13C73
style mysql fill:#FFFFDE, stroke:#B4AE43
style app fill:#ECECFF, stroke:#9674DC
```

**実行環境**

|要素|概要|
|:--|:--|
|terminal|ターミナル|
|Ubuntu|OS|
|Docker|コンテナー実行環境|

**データベース コンテナー**

|要素|概要|
|:--|:--|
|mysql-todo|データベースコンテナー|
|mysql|DB サーバー|
|db_todo|データベース|

## 技術トピック

### MySQL とは？

<details>
<summary>こちらを展開してご覧いただけます。</summary>

### [MySQL](https://dev.mysql.com/doc/refman/8.0/ja/what-is-mysql.html)

:::note info
MySQL は、オープンソースのリレーショナルデータベース管理システム (RDBMS) で、世界中で広く利用されているデータベースソフトウェアです。

|特徴|
|:--|
|MySQL は、高いパフォーマンス、拡張性、信頼性、および簡単な使用と管理性が特徴であり、Web アプリケーションや企業アプリケーションなど、さまざまな用途で使用されています。|
|MySQL は、クライアント/サーバーシステムとして動作し、多くのプログラムやWebアプリケーションから利用できます。|
|また、MySQL はオープンソースであるため、コミュニティによって開発されており、多くの開発者やユーザーが貢献しています。|
|MySQL は現在、Oracle Corporation が所有しており、Oracle Corporation から商用ライセンスも提供されています。|

:::

</details>

## 開発環境

+ Windows 11 Home 23H2 を使用しています。  

:::note info
[WSL](https://learn.microsoft.com/ja-jp/windows/wsl/about) の Ubuntu を操作しますので macOS の方も参考にして頂けます。
:::

<details>

WSL (Microsoft Store アプリ版) [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/cd0c4a607d451dbf5430)

```sh
> wsl --version
WSL バージョン: 2.2.4.0
カーネル バージョン: 5.15.153.1-2
WSLg バージョン: 1.0.61
```

Ubuntu [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/cd0c4a607d451dbf5430)

```sh
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04 LTS
Release:        24.04
Codename:       noble
```

Docker [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/3bceee25ac67cc73ebbe)

```sh
$ docker --version
Docker version 27.0.3, build 7d4bcd8
```

</details>

:::note warn
この記事では基本的に **Ubuntu のターミナルで操作**を行います。**Vim を使用してコピペする方法**をはじめて学ぶ人のために、以下の記事で手順を紹介しています。ぜひ挑戦してみてください。
:::

https://qiita.com/studio_meowtoon/items/7771ad48676926e41463

## Docker 環境で MySQL を使用する手順：共通手順

### Docker ネットワークを作成します

```sh
$ docker network create net-todo
```

<details>
<summary>説明を開きます。</summary>

|要素|説明|
|:--|:--|
|docker network create|Docker 内でコンテナー間通信を可能にするためのネットワークを作成するコマンドです。|
|net-todo|net-todo という名前の Docker ネットワークが作成されます。|

</details>

:::note warn
今後、このデータベースコンテナーとの間でコンテナー間通信を行うために、**ユーザ定義ネットワーク**を作成しています。
:::

## Docker 環境で MySQL を使用する手順：コマンド編

:::note alert
記事後半の **[Docker 環境で MySQL を使用する手順：Dockerfile 編](https://qiita.com/studio_meowtoon/items/ce1c853893388c106d22#docker-%E7%92%B0%E5%A2%83%E3%81%A7-mysql-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E6%89%8B%E9%A0%86dockerfile-%E7%B7%A8)** ではこちらの作業を自動化します。
:::

### コンテナーを作成・起動します

```sh
$ docker run -d \
   --publish 3306:3306 \
   --name mysql-todo \
   --net net-todo \
   --volume db_todo_mysql:/var/lib/mysql \
   --env MYSQL_ROOT_PASSWORD=password \
   mysql:8.0-debian
```

<details>
<summary>説明を開きます。</summary>

|要素|説明|
|:--|:--|
|docker run|新しいコンテナーを作成して実行するコマンドです。|
|-d|-d オプションは、コンテナーをバックグラウンドで実行します。|
|--publish 3306:3306|--publish オプションは、ホストとコンテナー間のポートマッピングを行います。ホスト側のポート 3306 をコンテナーのポート 3306 にマッピングしています。|
|--name mysql-todo|--name オプションは、コンテナーに mysql-todo という名前を付けます。これにより、あとでコンテナーを識別しやすくなります。|
|--net net-todo|--net オプションは、コンテナーで使用する Docker ネットワークを指定します。|
|--volume db_todo_mysql:/var/lib/mysql|--volume オプションは、Docker ボリュームを作成し、コンテナー内の /var/lib/mysql ディレクトリにマウントします。db_todo_mysql という名前のボリュームが作成されます。これにより、データベースのデータが永続化されます。|
|--env MYSQL_ROOT_PASSWORD=password|--env オプションは、コンテナー内で使用される環境変数を指定します。MYSQL_ROOT_PASSWORD 環境変数に password を設定することで、MySQL ルートユーザーのパスワードを設定します。|
|mysql:8.0-debian|MySQL 8.0 の Docker イメージを指定しています。このイメージを基にしてコンテナーが作成され、MySQL データベースが実行されます。|

</details>

:::note warn
このコンテナーを停止する場合には、以下のコマンドを実行します。

```sh
$ docker stop mysql-todo
```

次にこのコンテナーを起動する場合には、以下のコマンドを実行します。

```sh
$ docker start mysql-todo
```

:::

### コンテナー内の MySQL に接続します

コンテナーに接続します。
※ コンテナーから出るときは ctrl + D を押します。

```sh
$ docker exec -it mysql-todo /bin/sh
```

<details>
<summary>説明を開きます。</summary>

|要素|説明|
|:--|:--|
|docker exec|実行中のコンテナー内でコマンドを実行するコマンドです。|
|-it mysql-todo|対話的なシェルセッションを開始するためのフラグです。これにより、mysql-todo コンテナー内のシェルに対して入出力が可能になります。|
|/bin/sh|コンテナー内で実行するコマンドを指定します。ここではコンテナー内のデフォルトシェルである /bin/sh を起動しています。|

</details>

MySQL のバージョンを確認します。

```cs
# mysql --version
mysql  Ver 8.0.39 for Linux on x86_64 (MySQL Community Server - GPL)
```

MySQL に接続します。  
※ MySQL から出るときは ctrl + D を押します。

```cs
# mysql -uroot -ppassword
mysql>
```

データベースの一覧表示をします。

```cs
mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.03 sec)
```

一度 MySQL から出ます。

:::note info
ここまでの手順で、ローカル環境の **Docker** で **MySQL のコンテナー**を起動することができました。
:::

### データベースの作成

:::note warn
今後、ToDo リストアプリを作成する為に、以下の仕様のデータベース テーブルを作成します。
:::

**ToDo リストテーブル**
```mermaid
erDiagram
todos {
    INT_AUTO_INCREMENT id "PRIMARY_KEY"
    TEXT content "内容"
    TIMESTAMP created_date "作成日時"
    TIMESTAMP completed_date "完了日時"
}
```

コンテナーに接続します。  
※ コンテナーから出るときは ctrl + D を押します。

```sh
$ docker exec -it mysql-todo /bin/sh
```

#### テキストエディターのインストール

:::note alert
コンテナー内の MySQL に SQL を適用する方法はいくつかあります。この記事では学習の目的で vim を使用した方法を紹介しています。
:::

vim をインストールします。

```cs
# apt update
# apt install vim
# vim -version
VIM - Vi IMproved 9.0 (2022 Jun 28, compiled May 04 2023 10:24:44)
```

vimrc ファイルを編集します。

```cs
# vim ~/.vimrc
```

以下の設定を追記します。

```sh
:set encoding=utf-8
```

#### debian コンテナーに UTF-8 を設定

.bashrc ファイルを修正します。

```cs
# vim ~/.bashrc
```

以下を追記します。

```sh
export LANG=ja_JP.UTF-8
```

変更を反映します。

```cs
# . ~/.bashrc
```

環境変数を確認します。

```cs
# echo $LANG
ja_JP.UTF-8
```

#### データベースとテーブルを作成

先にデータベースを作成します。  
※ db_todo という名前のデータベースを作成します。

```cs
# mysql -uroot -ppassword -e "CREATE DATABASE db_todo;"
```

SQL ファイルを作成します。

```cs
# mkdir -p ~/tmp/mysql-base
# cd ~/tmp/mysql-base
# vim create_table.sql
```

ファイルの内容

```sql:create_table.sql
USE db_todo;

CREATE TABLE todos (
    id INT AUTO_INCREMENT PRIMARY KEY,
    content TEXT NOT NULL,
    created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    completed_date TIMESTAMP
);
```

MySQL に SQL ファイルを取り込みます。

```cs
# mysql -uroot -ppassword db_todo < create_table.sql
```

テーブルの内容を表示してみます。

```cs
# mysql -uroot -ppassword
mysql> USE db_todo;
mysql> SELECT * FROM todos;
Empty set (0.00 sec)
mysql> exit
Bye
```

:::note info
ここまでの手順で MySQL の**コンテナー**に**データベース**と**テーブル**を作成することができました。
:::

### データの挿入

SQL ファイルを作成します。

```cs
# vim insert_table.sql
```

ファイルの内容

```sql:insert_table.sql
USE db_todo;

INSERT INTO todos (content, completed_date)
VALUES
    ('食材を買う', NOW()),
    ('報告書を仕上げる', NOW()),
    ('運動する', NOW()),
    ('本を読む', NULL),
    ('請求書を支払う', NULL),
    ('家を掃除する', NULL),
    ('プレゼンの準備する', NULL),
    ('コードを書く', NULL);
```

MySQL に SQL ファイルを取り込みます。

```cs
# mysql -uroot -ppassword db_todo < insert_table.sql
```

テーブルの内容を表示してみます。

```cs
# mysql -uroot -ppassword
mysql> USE db_todo;
mysql> SELECT * FROM todos;
+----+-----------------------------+---------------------+---------------------+
| id | content                     | created_date        | completed_date      |
+----+-----------------------------+---------------------+---------------------+
|  1 | 食材を買う                  | 2024-08-11 11:02:02 | 2024-08-11 11:02:02 |
|  2 | 報告書を仕上げる            | 2024-08-11 11:02:02 | 2024-08-11 11:02:02 |
|  3 | 運動する                    | 2024-08-11 11:02:02 | 2024-08-11 11:02:02 |
|  4 | 本を読む                    | 2024-08-11 11:02:02 | NULL                |
|  5 | 請求書を支払う              | 2024-08-11 11:02:02 | NULL                |
|  6 | 家を掃除する                | 2024-08-11 11:02:02 | NULL                |
|  7 | プレゼンの準備する          | 2024-08-11 11:02:02 | NULL                |
|  8 | コードを書く                | 2024-08-11 11:02:02 | NULL                |
+----+-----------------------------+---------------------+---------------------+
8 rows in set (0.00 sec)
```

:::note info
ここまでの手順で MySQL の**コンテナー**の**テーブル**にデータを挿入することができました。
:::

## Docker 環境で MySQL を使用する手順：Dockerfile 編

:::note warn
こちらの内容は、これまで上で説明してきた作業を **Dockerfile** で**自動化**するための手順になります。いったん上で作成したコンテナーを停止してコンテナイメージを削除します。

```sh
$ docker stop mysql-todo
$ docker rm mysql-todo
$ docker rmi mysql-base
```

:::

プロジェクトフォルダーを作成・移動します。

```sh
$ mkdir -p ~/tmp/mysql-base
$ cd ~/tmp/mysql-base
```

SQL ファイルを作成します。

```cs
# vim init_db.sql
```

ファイルの内容

```sql:init_db.sql
DROP DATABASE IF EXISTS db_todo;
CREATE DATABASE db_todo;
USE db_todo;

CREATE TABLE todos (
    id INT AUTO_INCREMENT PRIMARY KEY,
    content TEXT NOT NULL,
    created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    completed_date TIMESTAMP
);

INSERT INTO todos (content, completed_date)
VALUES
    ('食材を買う', NOW()),
    ('報告書を仕上げる', NOW()),
    ('運動する', NOW()),
    ('本を読む', NULL),
    ('請求書を支払う', NULL),
    ('家を掃除する', NULL),
    ('プレゼンの準備する', NULL),
    ('コードを書く', NULL);
```

Dockerfile を作成します。

```sh
$ vim Dockerfile
```

ファイルの内容

```Dockerfile:Dockerfile
# set up the container.
FROM mysql:8.0-debian

# set utf-8 encoding and mysql root password.
ENV LANG=ja_JP.UTF-8
ENV MYSQL_ROOT_PASSWORD=password

# copy the init sql file to the init dir.
COPY init_db.sql /docker-entrypoint-initdb.d/
```

<details>
<summary>vim をインストールする ver はこちら。</summary>

```Dockerfile:Dockerfile
# set up the container.
FROM mysql:8.0-debian

# install vim.
RUN apt-get update && \
    apt-get install -y vim && \
    rm -rf /var/lib/apt/lists/* && \
    apt-get clean

# add encoding setting to .vimrc file.
RUN echo ':set encoding=utf-8' >> /root/.vimrc

# set utf-8 encoding and mysql root password.
ENV LANG=ja_JP.UTF-8
ENV MYSQL_ROOT_PASSWORD=password

# copy the init sql file to the init dir.
COPY init_db.sql /docker-entrypoint-initdb.d/
```

</details>

コンテナイメージをビルドします。

```sh
$ docker build \
    --no-cache \
    --tag mysql-base:latest .
```

コンテナイメージを確認します。

```sh
$ docker images | grep mysql-base
mysql-base   latest    b03cad044a15    9 seconds ago   611MB
```

コンテナーを起動します。

```sh
$ docker run -d \
   --publish 3306:3306 \
   --name mysql-todo \
   --net net-todo \
   --volume db_todo_mysql:/var/lib/mysql \
   mysql-base
```

:::note info
ここまでの手順で MySQL の**コンテナー**を作成し、**データベース**と**テーブル**を作成、また**テーブル**にデータを挿入することができました。
:::

## GUI クライアントから確認

https://www.mysql.com/jp/products/workbench/

MySQL を GUI から操作する統合ビジュアルツールとして MySQL Workbench があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/6193d82d-fd8e-74a3-f053-b12ef569b3ad.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/67208297-de83-938e-5b91-c8cea5892076.png)
これらのツールを活用することにより、より手軽に MySQL を操作できます。

## まとめ

ローカル環境の Ubuntu の Docker 環境で、MySQL コンテナーを起動することができました。

:::note warn
クラウド開発においては、**Dockerfile の理解**は重要です。自動ビルドツールもありますが、手動で書く必要があるケースもあります。**Ubuntu** を使うと **Linux の知識**も身に付きます。最初は難しく感じるかもしれませんが、徐々に進めていけば自信を持って書けるようになります。
:::

どうでしたか？　MySQL の操作には、この他にもたくさんのコマンドがあります。みなさんも少しづつ試してみてください。今後も開発環境などを紹介しますので、ぜひお楽しみにしてください。

## おまけ

AUTO_INCREMENT インデックス値をリセットする方法

```sql:SQL として実行してください。
USE db_todo;
ALTER TABLE todos AUTO_INCREMENT = 1;
```

## 推奨コンテンツ

https://qiita.com/studio_meowtoon/items/9bbf97d2e0668f157bb7

https://qiita.com/studio_meowtoon/items/a925fa0c9c989b000323

## 関連記事

https://qiita.com/studio_meowtoon/items/613291e1d3c88d3ef12e