自分メモ。
背景
- 自宅で Redmine の為に利用していた VPS の契約満了
- 小遣い削減の為に VPS の延長無し
- Redmine 環境をどっか(Docker)に移行しなければならない
- Redmine 環境はフル Docker コンテナ環境
- とりあえずはいつでも夜逃げ(移行)出来るように準備を整えることにする
やること
- コンテナのアーカイブ
- コンテナにマウントしているデータボリュームのアーカイブ
- アーカイブしたファイルを S3 に退避
- 退避したアーカイブを展開して元の環境を再現(バックアップにとって最も重要)
構成
夜逃げ経路
荷造り
コンテナのアーカイブ
そもそも
コンテナの移行で最もシンプルな方法は移行先で Dockerfile からの再ビルドのような気もするが、今回は docker save
又は docker export
を試してみたい気持ちもあり再ビルドは検討から外す。
その前に docker save / docker export の違いについて自分の理解
save
はベースイメージを含めてcommit
した時点のコンテナイメージを丸っとアーカイブ(引数にコンテナイメージを指定する)export
はexport
した時点のコンテナをアーカイブするので元となったイメージは含まれない(ルートファイルシステムのみをアーカイブするので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
時点の状態になっている為に書き換える必要があった。
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>
荷解き
コンテナ化しておくことのメリットはあったか?
Dockerfile から再ビルドした方が良い(上記の Apache コンテナの例)
- やっぱりコンテナ内に永続化が必要な情報がなければ移行先で Dockerfile から再ビルドした方が良い
- コンテナ内には出来るだけ設定情報は持たせないようにしてコンテナ起動時に動的に設定するようにした方が良いと感じた
移転先
- 暫くはローカル docker-machine 内になりそう