Edited at

Dockerコンテナ内にmysqlサーバを立てる

More than 5 years have passed since last update.


概要

Dockerコンテナ内にmysqlサーバを立てます。

mysqlアカウントを作成したり、mysqlサーバを外部に公開することも行います。

動作確認を行った環境は、ホストOS, コンテナOSともにCentOSです。


そもそもDockerとは

仮想環境構築に docker を使う - apatheia.info を読んでください!


Dockerfile

さっそくですが、以下が Dockerfile です。

コンテナイメージを作成するために必要なファイルです。

# DOCKER-VERSION 0.3.4

FROM centos:6.4

# ここは自由に変えてください
MAINTAINER Taro Tanaka

# パッケージインストール
RUN yum install -y mysql mysql-server

# mysqlサーバのセットアップ
RUN echo "NETWORKING=yes" > /etc/sysconfig/network
ADD ./setup.sql
RUN /usr/bin/mysqld_safe & \
sleep 10s && \
cat setup.sql | mysql

# 外部からmysqlサーバにアクセスできるように
RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/" /etc/mysql/my.cnf

# ポート番号 3306 を外部に公開
EXPOSE 3306

CMD ["/usr/bin/mysqld_safe"]


構文解説

Dockerfile 内で書かれている Instruction について軽く解説します。


  • FROM <image>


    • コンテナで利用するOSイメージです

    • この例では「centos:6.4」

    • 「centos』とだけ書くと、最新版を利用するようです



  • MAINTEINER <name>


    • Dockerfile の作成者



  • RUN <コマンド>


    • コンテナ環境でコマンドを実行させます



  • ADD <src> <dest>


    • ホスト環境のファイルをコンテナ環境へコピーします



  • EXPOSE <port>


    • コンテナ環境の外から参照させたいポート番号を指定します

    • mysqlサーバの場合は 3306. HTTPサーバだと通常 80 を指定します



  • CMD


    • CMD はDockerfileに1つしか記述できません。

    • 引数なしでコンテナを起動したときの、挙動を書きます

    • コンテナ起動のセクションでまた触れます



また、docker でキャッシュを活用するためには、あまり変わらないInstructionをDockerfileの上の方に記述するのがいいそうです。


MySQLセットアップ部分

MySQL固有の部分に関する部分を抜粋します。

RUN echo "NETWORKING=yes" > /etc/sysconfig/network

ADD ./setup.sql ./setup.sql

RUN /usr/bin/mysqld_safe & \
sleep 10s && \
cat setup.sql | mysql

まず1行目の /etc/sysconfig/network を生成している部分についてです。

この行がないとCentOSをコンテナOSとする場合に、mysqlが起動できないので、追加しています。

2行目はSQLスクリプトをコンテナで利用できるようにコピーしているだけです。

3行目は「mysqlサーバを起動させて、起動が完了するであろう10秒後に、セットアップ用のSQLを流し込む」という処理です。

setup.sqlにアカウント追加やデータベース作成、テーブル作成など処理を書いていて、それを実行しています

ここでの処理を見て、「1行にごちゃごちゃ詰め込むのではなく、3行に分けてRUNを書けばいいのでは?」と思われるかもしれません。

実は、ここが今回の最大のポイントです。というのも、3行に分けてRUNを書くと、setup.sqlでの処理は正しく動きません。

なぜかというと、RUNが別の行にまたぐと、ファイルシステム上での変化は記憶されるのですが、メモリやプロセスの状態変化は保持されないからです。

そのため、アカウント作成、テーブル作成といった処理を行うためには、mysqlサーバが起動している状態である必要ので、1行のRUNで処理を完結させているというわけです。


MySQLサーバをコンテナ外部からもアクセスさせる

RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/" /etc/mysql/my.cnf

デフォルトだとmysqlサーバは localhost からの接続しか許さないようになっているので、my.cnfを書き換えてあげます。

このsedコマンドでは、my.cnfの 127.0.0.1 となっている行を 0.0.0.0 に置換しています。


コンテナイメージの作成

Dockerfile の編集が完了したら、コンテナイメージを作成しましょう。

コンテナにタグをつけておくと、参照しやすいです(-t オプション).

また、タグ名は <自分のユーザ名>/<コンテナ名> とするのが良い習慣だそうです。

$ sudo docker build -t gologo13/mysql . 


コンテナ起動

コンテナイメージの作成に成功すれば、次はコンテナの起動です。

以下のように引数なしでdocker runを実行すれば、Dockerfileに書いた CMDの内容/usr/bin/mysqld_safeが実行されます。

docker run することで、mysqlサーバのデーモンプロセスの起動完了です!

$ sudo docker run -i -p 3306:3306 -t gologo13/mysql

また、コンテナ内でコマンドを実行したい場合は、シェルを立ち上げることもできます。この時、CMD で記述した内容は実行されません。

$ sudo docker run -i -p 3306:3306 -t gologo13/mysql /bin/bash


MySQLサーバへのアクセス

最後に、dockerコンテナ内でmysqlサーバにアクセスします。

以下の様なスクリプトを作っておくと、アクセスが楽になります。

処理的には、コンテナIDを取得して、そのコンテナの詳細情報からIPアドレスを取得しています。

$ cat mysql_client.sh

#!/bin/sh

# docker build 時に指定したタグ名
TAG="gologo/mysql"

CONTAINER_ID=$(docker ps | grep $TAG | awk '{print $1}')

IP=$(docker inspect $CONTAINER_ID | python -c 'import json,sys;obj=json.load(sys.stdin);print obj[0]["NetworkSettings"]["IPAddress"]')

# アカウントとパスワードは適宜変更してください
mysql -u admin -ppassword -h $IP

あとは実行すればおしまいです。

$ chmod u+x mysql_client.sh

$ sudo mysql_client.sh


参考