ようへいの日々精進XP

よかろうもん

コンテナで簡単(かもしれない)クラウド夜逃げの準備と実践

自分メモ。

背景

  • 自宅で Redmine の為に利用していた VPS の契約満了
  • 小遣い削減の為に VPS の延長無し
  • Redmine 環境をどっか(Docker)に移行しなければならない
  • Redmine 環境はフル Docker コンテナ環境
  • とりあえずはいつでも夜逃げ(移行)出来るように準備を整えることにする

やること

  • コンテナのアーカイブ
  • コンテナにマウントしているデータボリュームのアーカイブ
  • アーカイブしたファイルを S3 に退避
  • 退避したアーカイブを展開して元の環境を再現(バックアップにとって最も重要)

構成

夜逃げ経路

f:id:inokara:20150829080937p:plain


荷造り

コンテナのアーカイブ

そもそも

コンテナの移行で最もシンプルな方法は移行先で Dockerfile からの再ビルドのような気もするが、今回は docker save 又は docker export を試してみたい気持ちもあり再ビルドは検討から外す。

その前に docker save / docker export の違いについて自分の理解

  • save はベースイメージを含めて commit した時点のコンテナイメージを丸っとアーカイブ(引数にコンテナイメージを指定する)
  • exportexport した時点のコンテナをアーカイブするので元となったイメージは含まれない(ルートファイルシステムのみをアーカイブするので build 時に定義した CMD 等は反映されない)

それぞれのメリデメとしては...

  • save だと手軽にコンテナの完全再現が出来そうだけどベースイメージが含まれるので容量がデカくなる
  • export だと容量は小さくなるがコンテナを再現しようとすると手間がかかりそう

再現にあまり手間を掛けたく無いという思いから今回は save をチョイスする。

実践

以下のように commit して save するのみ。

$ docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS               NAMES
911f5a9931a1        inokappa/apache          "/start.sh"              5 days ago          Up 5 days                               apache
a5ed8c9ed547        inokappa/redmine         "/sbin/entrypoint.sh "   5 days ago          Up 5 days           80/tcp, 443/tcp     redmine
85bfb90a711c        sameersbn/mysql:latest   "/sbin/entrypoint.sh"    10 days ago         Up 5 days           3306/tcp            mysql-redmine
$ mkdir ~/backup
$ cd ~/backup
$ docker commit apache inokappa/apache
$ docker commit redmine inokappa/redmine
$ docker commit mysql-redmine inokappa/mysql-redmine
$ docker save inokappa/mysql-redmine > mysql-redmine_image.tar
$ docker save inokappa/redmine > redmine_image.tar
$ docker save inokappa/apache > apache_image.tar

コンテナにマウントしているデータボリュームのアーカイブ

コンテナにボリュームオプション(--volume)でコンテナホストのファイルシステムをマウントしているのでこちらも以下のようにアーカイブして持ち出す。

$ cd ~/backup
$ docker run --volumes-from redmine -v $(pwd):/backup ubuntu tar zcf /backup/redmine.tar.gz /home/redmine
$ docker run --volumes-from mysql-redmine -v $(pwd):/backup ubuntu tar zcf /backup/mysql-redmine.tar.gz /var/lib/mysql

一瞬、このコマンドでどうやってバックアップするんやって思ったので少しコマンドを紐解く。

$ docker run --volumes-from <アーカイブ対象のコンテナ名> -v $(pwd):/backup ubuntu tar zcf <アーカイブファイル名> <アーカイブ対象>
  • --volumes-from オプションを利用してアーカイブ対象となるボリュームオプションを利用しているコンテナ名を指定(ボリュームが共有される)
  • $(pwd) でコンテナホストのカレントディレクトリを ubuntu コンテナの /backup にマウント
  • あとは ubuntu tar zcf <アーカイブファイル名> <アーカイブ対象> で固めるだけ

アーカイブしたファイルを Amazon S3 に退避

夜逃げとは言え、対象の出費は覚悟の上でアーカイブしたデータは Amazon S3 に退避させるので aws-cli と簡単なシェルスクリプトで S3 に退避。

#!/bin/bash

#
cd ${HOME}/backup/

echo "\`\`\`"
#
echo -e "### remove old backup data...\n"
rm -vf *.tar *.tar.gz
if [ $? = "0" ]; then echo -e "done...\n"; else exit 1; fi

#
echo -e "### save mysql-redmine image...\n"
docker commit mysql-redmine inokappa/mysql-redmine
docker save inokappa/mysql-redmine > mysql-redmine_image.tar
if [ $? = "0" ]; then echo -e "done...\n"; else exit 1; fi

(snip)

echo "### backup mysql-redmine data...\n"
docker run --volumes-from mysql-redmine -v $(pwd):/backup ubuntu tar zcf /backup/mysql-redmine.tar.gz /var/lib/mysql
if [ $? = "0" ]; then echo -e "done...\n"; else exit 1; fi

#
echo -e "### sync s3 bucket...\n"
/usr/local/bin/aws s3 --quiet sync ./ s3://${BUCKET_NAME}/${BACKUP_PATH}/
if [ $? = "0" ]; then echo -e "done...\n"; else exit 1; fi

echo "\`\`\`"

IAM ユーザーを作ってバケットへのアクセス権のみを与えておく。

退避したアーカイブを展開して元の環境を再現

動作確認済み

  • 以下の手順にて元の環境が再現したことを確認済み

docker load でイメージを復元

$ cd ~/backup
$ docker load < mysql-redmine_image.tar
$ docker load < redmine_image.tar
$ docker load < apache_image.tar
$ docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
inokappa/mysql-redmine   latest              d17bc3b376e8        8 minutes ago       294.2 MB
inokappa/redmine         latest              1f9c7c2e0fb1        8 minutes ago       608.3 MB
inokappa/apache          latest              8f84d20f2c48        8 minutes ago       228.7 MB

Database コンテナの復元

  • コンテナ起動
$ cd ~/backup
$ docker run --name=mysql-redmine -d   \
  --env='DB_NAME=redmine_production'   \
  --env='DB_USER=${USER}' \
  --env='DB_PASS=${PASSWORD}' \
  --volume=/srv/docker/redmine/mysql:/var/lib/mysql \
inokappa/mysql-redmine
  • データの復元
$ cd ~/backup
$ docker run --volumes-from mysql-redmine -v $(pwd):/backup ubuntu tar xvf /backup/mysql-redmine.tar
  • コンテナ stop / start
$ docker stop mysql-redmine
$ docker start mysql-redmine

Redmine コンテナの復元

  • コンテナ起動
$ cd ~/backup
$ docker run --name=redmine -d \
  --link=mysql-redmine:mysql \
  --env='REDMINE_PORT=80' \
  --env='REDMINE_HTTPS=true' \
  --env='DB_NAME=redmine_production' \
  --env='DB_USER=${USER}' \
  --env='DB_PASS=${PASSWORD}' \
  --volume=/srv/docker/redmine/redmine:/home/redmine/data \
inokappa/redmine

初回起動時は exit1 するけどデータを復元すると正常に起動するので慌てない。

  • データの復元
$ cd ~/backup
$ docker run --volumes-from redmine -v $(pwd):/backup ubuntu tar xvf /backup/redmine.tar
  • コンテナ stop / start
$ docker stop redmine
$ docker start redmine

Apache コンテナの復元(やっちゃいけないダメな例)

  • コンテナ起動
docker run -d  --name=apache \
  --net=host \
  --env=REDMINE_PORT_80_TCP_ADDR=`docker inspect --format="{{ .NetworkSettings.IPAddress }}" redmine` \
  -p 80:80 -p 443:443\
   --log-driver=syslog --log-opt syslog-facility=daemon --log-opt syslog-tag="apache" 
inokappa/apache

起動はしているけど Apache も起動しているけど... httpd.conf 内で定義している redmine コンテナの IP が docker commit 時点の状態になっている為に書き換える必要があった。

  • httpd.conf 内で定義している redmine コンテナの IP を書き換える(やっちゃいけないダメな例)
docker exec apache sed -i "s/172.17.0.3/`docker inspect --format="{{ .NetworkSettings.IPAddress }}" redmine`/g" /etc/apache2/sites-available/redmine.conf
  • /start.sh プロセスの再起動(/start.sh がコンテナ起動時に実行されるので )
docker exec apache kill -HUP </start.sh の PID>

荷解き

コンテナ化しておくことのメリットはあったか?

  • あったと思う(単純に VMツールをインストールして設定 < < コンテナを丸っと移行)
  • データベースのデータについては外出し(コンテナホストのディスクをマウント)しておいても移行は辛くなかった

Dockerfile から再ビルドした方が良い(上記の Apache コンテナの例)

  • やっぱりコンテナ内に永続化が必要な情報がなければ移行先で Dockerfile から再ビルドした方が良い
  • コンテナ内には出来るだけ設定情報は持たせないようにしてコンテナ起動時に動的に設定するようにした方が良いと感じた

移転先

  • 暫くはローカル docker-machine 内になりそう