MySQL
docker
dockerfile

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

More than 3 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

参考