dockerならローカルに複数バージョンの使い捨てのMySQLサーバをたてられるので便利なのです。
標準スキルになっていきそうな勢いのdocker。今回はmacのローカル環境にdockerを使ってmysqlサーバをたててみようと思います。
今までmysqlのサイトからインストーラーをDLしてMySQLサーバをインストールしていましたが、複数バージョンインストールしたい場合等に困っていました。dockerならver5.6のコンテナ、ver5.7のコンテナ、と簡単に作成・破棄できてしまいます。ローカル環境に色々インストールしたりして環境を汚す量も減らす事ができます。
では簡単に手順を書いてみます。
この記事でやること
目的
以下を何とかしたいのです。
- ローカルのmacに複数のMySQLサーバを「簡単に職人芸不要で」たてたい。
- ローカルの環境をなるべく汚したくない。
プロジェクトによってMySQLのバージョンが異なる場合が多かったり、最新バージョンをいち早く試してみたい時に、いちいちローカルにMySQLサーバをたてるのはいやですね。ローカルの環境も汚れるし、複数バージョンを動かすのに職人芸的な設定をするのも嫌です。多分途中で職人芸を忘れて維持できなくなるかもしれないです。また、ローカルのマシンを新調したりしたらまたインストール・環境設定のやり直しかと思うと気が滅入ります。
手段
- docker-machineでdockerホストを作成する。
- mysql5.7のコンテナを作成する。
- macのローカルからコンテナ上のmysql5.7に対してリモートで操作する。
今回はdockerホスト作成にdocker-machineを使います。VagrantにCoreOSをインストールしてdockerしてもいいですが、やはりdocker-machineが楽だと思います。
ローカルにdocker環境を構築する
virtualboxまたはVMWareFusionをインストール
仮想環境をローカルに構築する際に、virtualboxやVMWareFusionが必要になります。
まずは無料のvirtualboxで試すのがいいと思います。もう既にVMWareFusionを購入していれば、それをそのまま使用できます。
VMWarePlayerではだめです。仮想環境を作成できるVMWareでなければなりません。VMWareFusion・VMWareFusion pro等なら大丈夫です。
docker-toolboxのインストール
docker関連のソフトウェア一式が入っているのがdocker-toolboxです。特に理由が無ければこれをインストールするのが一番楽です。
https://www.docker.com/docker-toolboxwww.docker.com
docker-machineでdockerホストを作成する
docker-machineは、dockerホストOSの環境を構築するためのソフトウェアです。docker-toolboxをインストールするとdocker-machineもインストールされます。
docker-machineでホストを作成し、ホストOSにdockerコンテナを作成していきます。
docker-machineには以下のように最初から「default」という名前で仮想環境が作成されていますが、新たに使い捨て用にホストOSを作成します。環境の名前を「dev」として進めています。
tree:~ tree$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM
default - virtualbox Stopped
virtualboxの場合
docker-machine create --driver virtualbox dev
VMWareFusionの場合
docker-machine create --driver vmwarefusion dev
このコマンドは、virtualboxまたはvmwarefusionに対して仮想環境を構築するコマンドです。私の環境はVMWareFusion pro v8なので、実際vmwareを開いてみると、以下のように作成されていました。
docker-machineに作成したホストOSの存在・状態を確認する
tree:~ tree$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM default - virtualbox Stopped dev - vmwarefusion Running tcp://172.16.53.131:2376
devができていますね。dockerホスト作成と同時にOSの起動処理も行われており、STATEがRunningになっている事が解ります。
豆知識:dockerホストのOSは何が使われているの?
tree:~ tree$ docker-machine ssh dev cat /etc/issue Core Linux
Core Linux(TinyCoreLinux?)だそうです。
ローカルの環境変数を設定
docker-machine create した際に表示されるログに、以下の一文があります。
To see how to connect Docker to this machine, run: docker-machine env dev
「dockerホスト上のコンテナに接続するための方法は、このマシンで docker-machine env dev を実行して確認してね」と言っています。
では「docker-machine env dev」を実行してみましょう。
tree:~ tree$ docker-machine env dev export DOCKER_TLS_VERIFY="1" export DOCKER_HOST="tcp://172.16.53.131:2376" export DOCKER_CERT_PATH="/Users/tree/.docker/machine/machines/dev" export DOCKER_MACHINE_NAME="dev" # Run this command to configure your shell: # eval "$(docker-machine env dev)"
どうやら環境変数を標準出力しただけのようですね。まだ環境変数は設定できていません。こちらもコマンド実行時のログの最後に「Run this command to configure your shell:」と書いてあるので、今度は「eval "$(docker-machine env dev)"」を実行してみます。
tree:~ tree$ eval "$(docker-machine env dev)" tree:~ tree$
特にログは出ません。ではローカルの環境変数がどうなったのかを確認してみます。
tree:~ tree$ env | grep -i docker DOCKER_HOST=tcp://172.16.53.131:2376 DOCKER_MACHINE_NAME=dev DOCKER_TLS_VERIFY=1 DOCKER_CERT_PATH=/Users/tree/.docker/machine/machines/dev
おお、先ほどの「docker-machine env dev」の結果が反映されましたね。しかしこの環境変数は一時的な設定なので、ターミナルソフトを再起動しただけで消えてしまいます。今回はお試しなので、その辺りはまた今度にしましょう。
この環境変数が設定されると、ローカルのターミナルでdockerコマンドを実行すると、そのコマンドはmacのローカルのdockerではなくdocker-machineで作成したdockerホストに向けて実行され、更にdockerホスト上のコンテナに伝搬されます。つまりdockerホストを意識せず、直接ローカル環境からコンテナに対してコマンドが実行できるようになります。従って、dockerホストにsshしてdockerコマンドを実行、等といった事をしなくてよくなります。これは大変便利ですね。
なお、docker-machine createで作成されるホストOSのIPはコロコロ変わるため、ホストOSを新たに作成した場合は都度「$(docker-machine env dev)」します。
dockerのイメージをダウンロードする
先ほど作成したdockerホスト上に、dockerコンテナと呼ぶOSをインストールするために、dockerのイメージをダウンロードする必要があります。
今回使用するのは、MySQL公式のdockerイメージです。
今回はMySQL5.7を使います。docker-machineのdevが起動している状態で、ローカルのmacで以下のコマンドを実行します。
docker pull mysql:5.7
pull(ダウンロード)すると、以下のようにダウンロードが始まります。そこそこのファイルサイズなので、回線が細いとかなり時間がかかります。
tree:~ tree$ docker pull mysql:5.7 5.7: Pulling from library/mysql 1565e86129b8: Downloading [=================================> ] 34.08 MB/51.35 MB a604b236bcde: Download complete 2a1fefc8d587: Download complete f9519f46a2bf: Download complete 35e21079caee: Download complete b08f3d26d732: Download complete ced60f6188d8: Download complete 93148df18c31: Download complete 8587beca5034: Download complete 2593a05c664f: Downloading [=============================================> ] 57.85 MB/63.42 MB 1483cfdf29e5: Download complete 1366ffba5c3b: Download complete 4e07f9c5fa5e: Download complete 1c19ce71381b: Download complete d6a18d40a940: Download complete 0f1a7d5b17f5: Download complete
MySQLのdockerコンテナを作成する
コンテナにマウントするファイルの用意
コンテナ作成前に、コンテナに対してこちらで用意したmy.cnfを反映したいので、ローカルにmy.cnfを作成します。試しに「/usr/local/docker/mysql/conf.d/my.cnf」と作成してもコンテナにマウントできなかった(恐らくSIPの問題?)なので、ホーム直下等に用意します。
# マウントするためのフォルダを作成 mkdir -pv $HOME/docker/mysql/conf.d # my.cnfの作成 cat << EOF > $HOME/docker/mysql/conf.d/my.cnf [client] port=3306 default-character-set = utf8mb4 [mysqld] port=3306 character-set-server = utf8mb4 skip-character-set-client-handshake skip-name-resolve lower_case_table_names = 1 default-storage-engine = InnoDB innodb_file_format = Barracuda innodb_file_per_table = 1 EOF
my.cnfの内容は任意に変更して下さい。とりあえず文字コードは変更しておきたいですね。
豆知識:MySQLコンテナが用意しているデフォルトのmy.cnf
公式のMySQLコンテナのmy.cnfですが、/etc/my.cnfではなくて、/etc/mysql/my.cnf に配置されています。
my.cnfはちょっと行数が多いので抜粋すると、以下が記述されている点に注目です。
# * IMPORTANT: Additional settings that can override those from this file! # The files must end with '.cnf', otherwise they'll be ignored. # !includedir /etc/mysql/conf.d/
/etc/mysql/conf.d/ 配下に置かれたファイルを動的に読み込む設定がされており、/etc/mysql/my.cnfの設定を上書きして値を読みこませる事ができるようになります。従って/etc/mysql/my.cnfを直接編集するのではなく、/etc/mysql/conf.d/my.cnfに上書きしたい値を記述する事になります。
MySQLのコンテナを作成・起動する
コンテナ作成コマンドは以下です。
docker run --name mysql5.7 -p 3307:3306 -v ~/docker/mysql/conf.d:/etc/mysql/conf.d -e MYSQL_DATABASE=hoge -e MYSQL_USER=worker -e MYSQL_PASSWORD=worker -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
はい。一気に意味不明になりましたね。オプションが非常に多いです。
コマンドを分解してそれぞれ見ていきます。
run | コンテナを起動する。 |
--name | コンテナに名前を付ける。ここでつけた名前で今後dockerコマンドを実行します。 |
-p | ポートフォワードします。左がホストのportで右がコンテナのportです。ホストの3307に接続するとコンテナの3306に接続されます。 |
-v | ローカルのディレクトリをコンテナにマウントします。macの場合は/usr/local配下SIPが絡むので避けましょう。 |
-e | コンテナに対して環境変数を設定します。複数設定する事ができます。 |
-d | デーモン起動。通常dockerコマンド終了時にコンテナは破棄されますが、今回はデーモン起動してコンテナを常駐起動させています。 |
mysql:5.7 | どのイメージで起動するかを指定します。「リポジトリ名:タグ名」の書式です。docker images実行時の「REPOSITORY」と「TAG」です。 |
ポートフォワードを3307:3306としたのは、既にローカルにDMG形式等でMySQLがインストールされている場合等を考慮したためです。3307も既に使用しているなら、任意に割り当てて下さい。
ここで設定した「-e」の環境変数ですが、これは公式のMySQLイメージが「こういう環境変数を指定すると、コンテナ起動時に指定したデータベース作成・ユーザ作成するよ」みたいなルールがあるためです。今回は「hoge」というデータベースを作成し、workerというユーザをworkerというパスワードで作成する、という設定をしています。変数の詳細は以下の公式サイトをご覧下さい。
では実際にコマンドを実行し、「docker ps」で実行中のコンテナを確認してみます。
# コンテナの起動(作成) tree:conf.d tree$ docker run --name mysql5.7 -p 3307:3306 -v ~/docker/mysql/conf.d:/etc/mysql/conf.d -e MYSQL_DATABASE=hoge -e MYSQL_USER=worker -e MYSQL_PASSWORD=worker -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7 af659f14b7673209e99b56be39e8427c538164f06e202635e4efd1309076db2e # 起動したコンテナの状態を確認 tree:conf.d tree$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES af659f14b767 mysql:5.7 "/entrypoint.sh mysql" 12 minutes ago Up 12 minutes 0.0.0.0:3307->3306/tcp mysql5.7
いますね。
ローカルからdockerコンテナのMySQLに接続してみる
dockerコンテナをrunしたので、こちらで用意したmy.cnfを読み込んで、MySQLサーバが起動されました。ではローカルのmacから作成したMySQLコンテナにリモートで接続してみます。
mysql -h$(docker-machine ip dev) -P3307 -uworker -pworker hoge
これで接続できます。しかし、コンテナ側のMySQLプロセスが完全に起動するまでは接続できないので、コンテナ起動直後に接続しようとしても以下のようになる場合があります。その場合はほんの少し時間をおいて接続しましょう。
tree:conf.d tree$ mysql -h$(docker-machine ip dev) -P3307 -uworker -pworker hoge mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 2003 (HY000): Can't connect to MySQL server on '172.16.53.131' (61)
ローカルから直接コンテナのMySQLに接続できるのは、ローカルで「-h」で指定したIP(docker-machineで作成したdockerホスト)にport=3307で接続すると、dockerホストが3307->3306というポートフォワードをし、dockerコンテナに中継して接続してくれるためです。
「-h$(docker-machine ip dev)」としているのは、dockerホストを再作成した場合等はIPが変わってしまうため、動的にIPを指定するためにそのように設定しています。
my.cnfが反映されているか確認する
my.cnfがマウントされているか
tree:conf.d tree$ docker exec -it mysql5.7 cat /etc/mysql/conf.d/my.cnf [client] port=3306 default-character-set = utf8mb4 [mysqld] port=3306 character-set-server = utf8mb4 skip-character-set-client-handshake skip-name-resolve lower_case_table_names = 1 default-storage-engine = InnoDB innodb_file_format = Barracuda innodb_file_per_table = 1
また新たなコマンド「exec」が出てきましたね。
exec | 起動中のdockerコンテナに対してコマンドを直接実行する。 |
-it | -iはinteractive、対話式のコマンドを実行できるようにする。-tはtty、コマンドの入出力を可能にする。 |
mysql5.7 | docker run --name で指定したコンテナ名です。 |
cat /etc/mysql/conf.d/my.cnf | コンテナに対して実行したいコマンド。 |
今回はコンテナに直接コマンドを実行して確認してみました。もしコンテナにsshして色々確認してみたい場合は以下のコマンドでsshします。
docker exec -it mysql5.7 bash
最後のbashは、「ログインシェルを/bin/bashとしてコンテナにログインする」という意味になります。以下と同じです。
docker exec -it mysql5.7 /bin/bash
これでコンテナに直接sshする事も可能です。
MySQLの文字コードはちゃんと指定したUTF系になっているか確認
tree:conf.d tree$ mysql -h$(docker-machine ip dev) -P3307 -uworker -pworker hoge --table -e "show variables like 'char%'" mysql: [Warning] Using a password on the command line interface can be insecure. +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | utf8mb4 | | character_set_connection | utf8mb4 | | character_set_database | utf8mb4 | | character_set_filesystem | binary | | character_set_results | utf8mb4 | | character_set_server | utf8mb4 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+
よし、文字コードが全てUTF系になりましたね。これで心置きなくテストできます!
おまけ
コンテナの破棄
docker rmコマンドでコンテナを破棄(削除)できます。
rmの引数にコンテナのidが必要なので、まずはdocker psで削除したいコンテナのidを確認します。
tree:conf.d tree$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES af659f14b767 mysql:5.7 "/entrypoint.sh mysql" 50 minutes ago Up 50 minutes 0.0.0.0:3307->3306/tcp mysql5.7
起動中のコンテナを強制破棄する際は「-f」を付けます。
docker rm -f af659f14b767
これで削除できます。しかしidは実は前方一致で省略する事ができます。
tree:conf.d tree$ docker rm -f af af
こんな感じに削除できるので、きっちり入力する必要はありません。ちなみに先頭1文字でも削除できます。
virtualboxとvmwareのドライバ、どっちが速い?
私はVMWareFusion pro v8をブラックフライデーのセールで40%引きで購入しているので、比較してみました。速度の計測には「time」コマンドで行います。
virtualbox v5の場合
tree:~ tree$ time docker-machine create --driver virtualbox dev Running pre-create checks... Creating machine... Waiting for machine to be running, this may take a few minutes... Machine is running, waiting for SSH to be available... Detecting operating system of created instance... Provisioning created instance... Copying certs to the local machine directory... Copying certs to the remote machine... Setting Docker configuration on the remote daemon... To see how to connect Docker to this machine, run: docker-machine env dev real 0m52.265s user 0m0.226s sys 0m0.142s
VMWareFusion pro v8の場合
tree:~ tree$ time docker-machine create --driver vmwarefusion dev Running pre-create checks... Creating machine... Waiting for machine to be running, this may take a few minutes... Machine is running, waiting for SSH to be available... Detecting operating system of created instance... Provisioning created instance... Copying certs to the local machine directory... Copying certs to the remote machine... Setting Docker configuration on the remote daemon... To see how to connect Docker to this machine, run: docker-machine env dev real 0m37.940s user 0m0.294s sys 0m0.131s
virtualboxが52秒なのに対し、VMWareは37秒で作成できました。今回はpro版なので、最も安価なVMwareFusionの場合はもう少し遅くなると思いますが、恐らくVMWareの方が平均して高速だと思われます。
ホストOSの作成だけでなく、コンテナ上でのアプリケーション速度もVMWareの方が速いんじゃないかと思います。
qiita.com
快適に操作したいなら、お金出してVMWareFusion(できればpro版)の方がいいかもしれませんね。
便利な使い方
便利といえるか怪しいですが、私の場合はローカルのmacのdocker-machineでmysql専用ホストを用意しています。
mysqlホスト上に、MySQL v5.5, v5.6, v5.7 の3つのバージョンを用意しています。業務では複数のMySQLを使うプロジェクトがあり、それぞれバージョンが異なる場合が多々有ります。実際の業務では色々なプロジェクトが複数のバージョンのMySQLが使われている事が多いので、全バージョン揃っていると何かと便利です。
雑感
まだ作成するコンテナが1個なのでdocker runで頑張れますが、コンテナが増えてくるともう訳が分からなくなってきます。その場合はdocker-composeを使う事になりますが、それはまた今度ということで。
私も最初は「docker?どうせインフラ屋向けのものだろ。developerには不要」とか考えて敬遠してましたが、使ってみると以外と簡単でした。しかしネット上に既にある記事のほとんどは「とりあえずこのコマンドを実行すると何となくうまくいきますよ」的なコマンドを羅列しただけの記事が多いので、「ここでこのコマンドを実行するのはどうして解ったの?」と思ったり「ここでコマンド実行するのは何故?」とか思う事が多かったので、今回記事にしてみました。記事にする事で自分自身の理解も結構深まってきた感じがします。
皆docker! docker!と騒いでいますが、今既にあるオンプレミスでインフラベンダーがインフラを握っている環境では簡単に導入できるものではないので、まずはローカル環境で活用していく方法でdockerに慣れていくといいのかな、と思いました。ローカルで暫く触ってdockerに慣れて、そのうちproduction・qa等の環境はオンプレだけど、社内develop環境はdockerに移行、みたいな感じで徐々にdockerに移行できるのが理想ですね。最終的にインフラベンダーを消し飛ばし、オンプレ環境を脱却してamazon ecs等に移行できれば最高ですが、そこまでいける環境なんて中々無いですよね。新規案件ならできそうですが、既存の保守案件ではまず不可能です。
私はその「現場へのdocker導入は現実に考えて無理」な環境なので、ローカル環境やdevelop環境に導入して抗ってみたいなと思ってます。
www.bunkei-programmer.net
docker-compose用の記事も書きましたよ!!
これでMySQLサーバ v5.5, 5.6, 5.7 を docker-compose up するだけで作成できちゃいます!!
www.bunkei-programmer.net