Dockerでデータ入りのMySQLボリュームイメージをつくる

普段お仕事でRailsアプリケーションを作ってて、今はチーム内共通のMySQLサーバーをみんなが参照している。
これをDocker化してうまくみんなにイメージを配布したかった。

前職ではMySQLにデータが投入済みのDockerイメージを作成して、コマンド一発でデータが入った状態のMySQLコンテナが立ち上がるようになっていたので、そのやり方を元同僚に聞いて再現してみることにした。

構成

docker-composeを使って

  • 公式のMySQLコンテナ
  • volume用コンテナ

の2つを立ち上げて利用する。

流れ

まずはデータ入りDockerイメージ作成

  • 公式MySQLイメージからコンテナを立ち上げてdumpデータ投入
  • データ入りのファイルをホストに/var/lib/mysql以下をコピー
  • 新規でホストからコンテナに↑の手順でコピーしてきたデータをCOPYするDockerfileを作成
  • docker buildすれば出来上がり

続いてデータ入りのイメージから、データ投入済みMySQLコンテナを立ち上げる

  • さっき docker buildしたimageを起動
  • ↑で起動したコンテナをvolume指定して、公式MySQLイメージからMySQLコンテナを起動

順を追って詳細説明していきます。

データ入りDockerイメージ作成

公式イメージからMySQLコンテナの起動
起動したらDB作成とデータ投入

$ docker run -d --name db -e 'MYSQL_ALLOW_EMPTY_PASSWORD=yes' -p 3306:3306 mysql:latest

データ入りのファイルをホストにコピー

$ mkdir -p ./data/var/lib
$ docker cp db:/var/lib/mysql ./data/var/lib

Dockerfileの作成

FROM busybox
RUN mkdir -p /var/lib/mysql
COPY data/var/lib/mysql /var/lib/mysql
RUN chown -R 999:999 /var/lib/mysql
VOLUME /var/lib/mysql
CMD tail -f /dev/null

最後に

$ docker build .

データ投入済みMySQLコンテナを立ち上げる

docker-compose.ymlをつくって $ docker-compose up

version: '2'
services:
  db-storage:
    image: {さっきつくったdocker image}
    volumes:
      - /var/lib/mysql
  db:
    image: mysql:latest
    ports:
      - 3306:3306
    volumes_from:
      - db-storage

storage用のimageをDockerHubなどのレジストリにpushしておけば、他の開発者はプロジェクトのリポジトリをcloneして docker-compose upするだけでデータ入りのDBが即座に立ち上がる。

雑感

最初これを作ろうとしたとき VOLUME指定をするとimageにデータが保存されなくて困っていたところ、元同僚から「Dockerfileの中でVOLUMEを指定する前に追加したデータはimageに含まれるんですよ」というアドバイスをもらい無事に実現できたのでありがとうありがとうという感じ。

とりあえずやりたいことは実現できたが、微妙にやり切れてないのがdocker-compose.ymlをversion: 3で書くことで、version3から volumes_fromが消えていてうまく書けなかったりしている。

ちょうど趣味プロジェクトでまあまあのデータ量のDBを扱うアプリケーションを作ろうとしていたので、Docker化をして友達の開発者とかに「こんな感じで動くよ」ってすぐに見せられて便利。
Docker imageにでっかいデータをのっけることの筋が良い悪い話はいったん置いといてください。

github.com