とあるシステムをDocker-Composeで構築し、運用していました。
サンプルとして、gitbucketをpostgresqlで運用したものを上げます。
中身はこんな感じです。
version: '2'
volumes:
gitbucket_postgres_data:
driver: local
gitbucket_data:
driver: local
services:
# gitbucket postgres
gitbucket_postgres:
restart: always
image: postgres:9.6
volumes:
- gitbucket_postgres_data:/var/lib/postgresql
environment:
POSTGRES_PASSWORD: passwd
POSTGRES_USER: gitbucket
POSTGRES_DB: gitbucket
POSTGRES_INITDB_ARGS: --encoding=UTF-8 --locale=C
# gitbucket
gitbucket:
restart: always
image: f99aq8ove/gitbucket
depends_on:
- gitbucket_postgres
environment:
GITBUCKET_DB_URL: "jdbc:postgresql://gitbucket_postgres/gitbucket"
GITBUCKET_DB_USER: gitbucket
GITBUCKET_DB_PASSWORD: passwd
GITBUCKET_OPTS: --prefix=/
VIRTUAL_HOST: gitbucket.example.com
VIRTUAL_PORT: 8080
volumes:
- gitbucket_data:/gitbucket
ports:
- "29418:29418"
networks:
default:
external:
name: common_link
ある日、そろそろバージョンアップするかなと、
docker-compose pull && docker-compose down && docker-compose up -d
とし、コンテナを作り替えたところ・・・
データベースが吹っ飛びました
おかしいと思い、
docker exec -it sample_gitbucket_postgres_1 /bin/bash
としたところ・・・
root@62656ba04baa:/# ls -lah /var/lib/postgresql/data/
total 128K
drwx------ 19 postgres postgres 4.0K Apr 4 11:29 .
drwxr-xr-x 3 postgres postgres 4.0K Apr 4 11:29 ..
drwx------ 6 postgres postgres 4.0K Apr 4 11:29 base
drwx------ 2 postgres postgres 4.0K Apr 4 11:31 global
drwx------ 2 postgres postgres 4.0K Apr 4 11:29 pg_clog
以下略
ファイルはあります。しかし妙です。容量があからさまに少ないです。
ではコンテナがどうなっているか見てみます。
docker inspect sample_gitbucket_postgres_1
・・・・・
"Mounts": [
{
"Name": "sample_gitbucket_postgres_data",
"Source": "/var/lib/docker/volumes/sample_gitbucket_postgres_data/_data",
"Destination": "/var/lib/postgresql",
"Driver": "local",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
},
{
"Name": "1b9b7b263e28161c2484b5a3becff652045aba3ea093cf54731c30aecb549a56",
"Source": "/var/lib/docker/volumes/1b9b7b263e28161c2484b5a3becff652045aba3ea093cf54731c30aecb549a56/_data",
"Destination": "/var/lib/postgresql/data",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
・・・・・
うん???何故かマウントされている2つデータコンテナがあります。
うち1つはどう見ても自動生成されているようです。
dockerはデータボリュームを明示的にマウントしない限りデータは永続化されないはずですが・・
作成したデータコンテナの中身を見てみます。
root@ubuntu-docker:~# ls -lah /var/lib/docker/volumes/sample_gitbucket_postgres_data/_data/data/
合計 8.0K
drwxrwxrwx 2 999 docker 4.0K 3月 15 01:56 .
drwxr-xr-x 3 999 docker 4.0K 4月 4 20:29 ..
・・・・・・(滝汗
オチ
オチとしては、マウント先ディレクトリを間違えて、/var/lib/postgresql/data
とすべきところを/var/lib/postgresql
としてしまい、たまたま普段の運用でdocker-compose stop/startだったので、作成されたボリュームとコンテナが生きていていままで動いていただけで、データコンテナの中身は空っぽでした
その結果、コンテナ吹っ飛ばした所再度新たに作成されたデータコンテナにてデータが初期化されてしまいました。
復旧へ・・
気づいたのが早かったのと、幸いデータコンテは吹っ飛ばしていなかったので、サーバ上にあるすべてのデータボリュームに対しgrepをかけて、コンテナを作り替える直前あたりのタイムスタンプがあった、PostgreSQLデータコンテナを特定。
docker-composeを正しいマウントポイントに修正後、そのまま動かすと既にデータコンテナがあるのでエラーになるので、データコンテナをdocker volume rm
で削除。docker-composeで再作成した後、今度は中身が正しくできていること、変なマウントがないことをdocker inspect
で確認をし、いったん終了させた後、データコンテナの中身をすべて、更新前ボリュームの中身でコピーし、無事復旧できました。
参考
元のPostgreSQL公式コンテナのDockerfileにはこうあります。
VOLUME /var/lib/postgresql/data
Dockerfile内でVOLUMEで述したディレクトリは、外部とのマウントポイントとなります。
それ以外のディレクトリはマウントできないわけではないのですが、特にエラーもなくこのように無視されることもあります
ドキュメントによると、
VOLUME 命令は指定した名前でマウントポイントを作成し、他のホストやコンテナから外部マウント可能なボリュームにします。
docker run コマンドは、ベース・イメージから指定した場所に、データを保存する場所として新規作成したボリュームを初期化します。
つまり、明示的にマウントしないものは、docker runした時点で自動的にボリュームが作成され、初期化されるようです。
ただし、このボリュームは明示的に指示していないのでランダムな文字列で作成され、コンテナ再作成時に別名で作られます。以前のは明示的に消さない限りは残るようですが、当時のコンテナを消してしまっていると、docker inspectで調べることもできず、特定作業は困難となります・・
最後に
ちゃんと作成したデータボリュームにデータが格納されているか確認しよう。
面倒でも、バックアップを取りましょう。
自分はコンテナはどうせ作り替えだし、データボリュームは消えないからと、どうせなら全部きれいにしてしまえとバックアップ取らずdocker image prune
したりしたので、頭の中もまっさらになりました(涙
追記
Dockerを長く運用していると不要なイメージがたまって容量を食うので、ググると最近は
docker system prune
でOK!みたいなのが結構引っかかるのですが、
これは停止中のコンテナ、関連リソースすべて吹っ飛ばします
停止中=不要とはかならずしもならないと思いますので、盲目的にググってコピペして実行しないようにしましょう。