DockerでMySQLのデータを保存する方法


どうもこんにちは
久しぶりにDockerのことについて書きたいと思います、前回のDockerエントリが[8/30](http://qiita.com/TakashiOshikawa/items/e23f24afd21e05a3fa22 "MacでDockerを使ってみる")ですね、はい。

今回はタイトル通りDockerでMySQLコンテナを立ち上げてデータを保存してみます。




<h2>きっかけ</h2>
僕が個人的にサービスを作ろうとした時に、環境を全部dockerコンテナで管理出来るようにしようと思ったところ「MySQLのデータってコンテナ内部に保存できるの？てかして良いの？」という疑問が出てきたので解決方法を調べてみました。




参考資料はこちら
[Docker でデータのポータビリティをあげ永続化しよう](http://qiita.com/mopemope/items/b05ff7f603a5ad74bf55 "Docker でデータのポータビリティをあげ永続化しよう")
[Dockerのbusyboxは永続コンテナと言いながらexport/saveコマンドでは持ち運びできないよ](http://qiita.com/kumechang/items/fc108b1ec4683f3765d8 "Dockerのbusyboxは永続コンテナと言いながらexport/saveコマンドでは持ち運びできないよ")
[DockerとData Volume Containerのお話](http://qiita.com/kxphotographer/items/4788a25d9ebe6a434e46 "DockerとData Volume Containerのお話")





<h2>やること</h2>
1.busyboxイメージを使ってデータ保存用のコンテナを立ち上げる
2.データ保存用コンテナを指定してMySQLコンテナを立ち上げる
3.MySQLにデータを追加する
4.busyboxでデータが指定ディレクトリに追加されているか確認
5.保存したデータを1.で立ち上げたコンテナとは別コンテナで扱う
6.嬉しむ

では見ていきましょう


<h2>実践</h2>
<h3>busyboxを立ち上げる</h3>
保存するイメージはUbuntuやCentOSでもいいのですが、特に気にしないのであればbusyboxで行います。
これは上記の2つよりも軽量でストレージにしたい場合に使うことが多いようです。

busyboxのDockerfileを作成します
ファイル名はDockerfileです。

```:Dockerfile
FROM busybox
VOLUME /var/lib/mysql
CMD /bin/sh
```


これを元にイメージを作成します。


※現在のイメージたち
![スクリーンショット 2015-12-31 18.39.11.png](https://qiita-image-store.s3.amazonaws.com/0/36871/a48c5ae6-70ba-cb44-6ab9-0641c16d7362.png "スクリーンショット 2015-12-31 18.39.11.png")

<br>
イメージビルド
```docker build -t strage_image .```
歌いながら待ちます(白いブラウス似合う女の子〜なぜいつも悲しそうなの〜)
...
<br>

※strage_imageが追加されたのが分かる
![スクリーンショット 2015-12-31 18.47.27.png](https://qiita-image-store.s3.amazonaws.com/0/36871/4b638618-01e8-787f-3985-bb1d3f7a4fbf.png "スクリーンショット 2015-12-31 18.47.27.png")

<br>
<br>
このイメージからコンテナを作成します。

```docker run -it -v /var/lib/mysql --name strage_container strage_image```

`-v 指定ディレクトリ`でこのコンテナが他のコンテナから指定された時に関連付けられるディレクトリになります。
※DockerfileのVOLUMEにこのディレクトリを記述している場合、このパラメータは不要ですが今回は付けています。

![スクリーンショット 2015-12-31 18.58.18.png](https://qiita-image-store.s3.amazonaws.com/0/36871/a05b51c1-5f0b-fda1-cccf-b742d1ba4b2b.png "スクリーンショット 2015-12-31 18.58.18.png")

strage_containerが作成されました。



<h3>MySQLコンテナを立ち上げる</h3>
先ほどのstrage_containerをデータ保存先に指定してコンテナを立ち上げます。

```docker run --volumes-from strage_container --name mysql_container -e MYSQL_ROOT_PASSWORD=pass -d -p 3306:3306 mysql```


これでstrage_containerと/var/lib/mysqlディレクトリが共有された状態になりました。


<br>
<h3>MySQLコンテナにデータを追加(テキストファイル)</h3>一旦テストファイルを配置して本当にstrage_containerと共有出来ているか確かめてみます。
mysql_containerにファイル配置

![スクリーンショット 2015-12-31 19.13.47.png](https://qiita-image-store.s3.amazonaws.com/0/36871/aaf4fada-0086-f274-f7b8-3f9facdb9b53.png "スクリーンショット 2015-12-31 19.13.47.png")




<br>
<h3>ストレージコンテナでデータの確認(テキストファイル)</h3>strage_containerでファイルが配置されているか確認
コンテナスタート
`docker start strage_container`

接続
`docker attach strage_container`

![スクリーンショット 2015-12-31 19.28.49.png](https://qiita-image-store.s3.amazonaws.com/0/36871/4440b41b-d357-cab9-e34a-7097e441f82c.png "スクリーンショット 2015-12-31 19.28.49.png")

確かにstrage_containerでもtest.txtが確認出来ましたね。


<br>
<h3>ストレージコンテナにデータを追加(DBのデータ)</h3>次はテーブルを作成してinsertしてそのデータを共有してみます。
※先ほどのtest.txtはstrage_containerから削除しておきましょう。
/var/lib/mysql/にファイルがあるとMySQLを起動しようとした時にエラーが出ます。
![スクリーンショット 2015-12-31 20.01.12.png](https://qiita-image-store.s3.amazonaws.com/0/36871/8d1d8970-a18c-f72a-a3b2-12803e835ebd.png "スクリーンショット 2015-12-31 20.01.12.png")

コンテナのbashを抜けた状態&コンテナはstartしている状態で

```docker exec -it mysql_container bash```

![スクリーンショット 2015-12-31 19.42.46.png](https://qiita-image-store.s3.amazonaws.com/0/36871/584ca85f-2e6f-34f5-8945-1b6a176b6828.png "スクリーンショット 2015-12-31 19.42.46.png")

MySQL接続
```mysql -u root -p```
passwordは先程runした時MYSQL_ROOT_PASSWORDに設定した値です。
今回はpassと入力してください。
![スクリーンショット 2015-12-31 20.07.13.png](https://qiita-image-store.s3.amazonaws.com/0/36871/28eeb0e0-30c5-4f14-9eaa-7e9b85cc43e5.png "スクリーンショット 2015-12-31 20.07.13.png")

<br>
INSERT文を実行してデータを追加していきたいと思います。

まずは適当にDBとテーブルを作成

```SQL
CREATE SCHEMA IF NOT EXISTS `docker_scheme` DEFAULT 
CHARACTER SET utf8 ;
USE `docker_scheme` ;

DROP TABLE IF EXISTS `docker_scheme`.`users` ;

CREATE TABLE IF NOT EXISTS `docker_scheme`.`users` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `nick_name` VARCHAR(32) NOT NULL DEFAULT '',
  `age` INT NOT NULL DEFAULT 18,
  `introduce` VARCHAR(2048) NOT NULL DEFAULT '',
  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  INDEX `AGE` (`age` ASC))
ENGINE = InnoDB;
```

上記のクエリを実行して
![スクリーンショット 2015-12-31 20.14.04.png](https://qiita-image-store.s3.amazonaws.com/0/36871/26accd91-6594-5af4-a7bd-96725f8746b6.png "スクリーンショット 2015-12-31 20.14.04.png")

DBとテーブルが作成されたことを確認しましょう。

次にこのクエリを実行してデータを入れます。
データ自体は何でもいいです。

```SQL
INSERT INTO users(`nick_name`, `age`, `introduce`)
  VALUES('takashi', 21, 'Server side programmer');
```

データが入ったのが確認出来ました。
![スクリーンショット 2015-12-31 20.19.08.png](https://qiita-image-store.s3.amazonaws.com/0/36871/05fe6d3e-84f2-b7d4-1412-83d0e3b809f5.png "スクリーンショット 2015-12-31 20.19.08.png")

<br>
<h3>ストレージコンテナでデータの確認(DBのデータ)</h3>
ここで一旦, mysql_containerから出てstrage_containerの中身を確認してみます。
![スクリーンショット 2015-12-31 20.22.06.png](https://qiita-image-store.s3.amazonaws.com/0/36871/d7a91bd8-5b40-8d36-9d75-022e1107c3fe.png "スクリーンショット 2015-12-31 20.22.06.png")

色々出来ていますね、良さそうです。




<br>
<h3>strage_containerに保存したデータをmysql_containerとは別のコンテナでデータを扱う</h3>先程はmysql_containerという名前のコンテナからデータを入れていました。
次はmysql_container2というコンテナを立ち上げてここで先ほどINSERTしたデータがSELECT出来るか確かめてみましょう。

```docker run --volumes-from strage_container --name mysql_container2 -e MYSQL_ROOT_PASSWORD=pass -d -p 3306:3306 mysql```

※mysql_containerはstopしておいてください
```docker exec -it mysql_container2 bash```

![スクリーンショット 2015-12-31 20.30.00.png](https://qiita-image-store.s3.amazonaws.com/0/36871/cfa66d0d-a9d1-b99d-b34a-05d295b77c53.png "スクリーンショット 2015-12-31 20.30.00.png")

<br>
DBとテーブルが存在するか確認します。
![スクリーンショット 2015-12-31 20.33.00.png](https://qiita-image-store.s3.amazonaws.com/0/36871/f51d2298-f3a3-49d8-3998-6e75dc2a6e6a.png "スクリーンショット 2015-12-31 20.33.00.png")

<br>
ありましたね、最後にSELECT文を投げてみます。

```SQL
SELECT * FROM user;
```

![スクリーンショット 2015-12-31 20.34.39.png](https://qiita-image-store.s3.amazonaws.com/0/36871/e9a2fc5c-34e4-3526-e900-99b5c04fdb15.png "スクリーンショット 2015-12-31 20.34.39.png")

こちらも大丈夫そうです。
これで特定のMySQLコンテナに依存しないデータの保存ができるようになりました。


<br>
<h2>最後に</h2>
今回は異なるコンテナで1つのストレージのデータを扱う方法を試しましたが、実際同じデータを幾つものコンテナから扱っても嬉しさはそこまでありません(大量のリクエストがある時に負荷分散が出来る？)

実際は同じデータを異なる環境に移行するときにコンテナベースで簡単にやりたいとか、本番と同じテストデータを用意したいという時に使いたいところです。
ただストレージコンテナはexportやsaveしてもコンテナ内には保存されないらしいですね笑

参考はここで
[Dockerのbusyboxは永続コンテナと言いながらexport/saveコマンドでは持ち運びできないよ](http://qiita.com/kumechang/items/fc108b1ec4683f3765d8 "Dockerのbusyboxは永続コンテナと言いながらexport/saveコマンドでは持ち運びできないよ")

最後が雑な感じになってしまいましたがとりあえず今日はここまで〜
<br>