読者です 読者をやめる 読者になる 読者になる

Kuchitama Tech Note

はてな記法がいつまでたっても覚えられないので、はてなダイアリーからマークダウンが使えるこっちに引っ越してきました。

Docker上のRedashのデータをなくしてから復旧するまでの全記録

会社で、Redashを運用してるんですが、そのRedashがぶっ飛んで、もうだめだーと思ったものの、なんとか復旧出来たので、忘れないうちにやったことをまとめておきます。

結論から言うと、 ちゃんとDocker, Docker Composeの運用ノウハウ勉強してから、Redash立てようなって話です。

f:id:kuchitama:20170405144512p:plain

長いので先にまとめ

  • RedashをDockerで運用してた
  • docker-compose down したら、データが全て消えた
  • Volumeを指定してなかったのが原因
  • Volumeディレクトリから発掘して事なきを得た
  • RedashをDockerで運用するなら volumes は指定しような

経緯

会社で、Mac mini に Docker for Mac を入れて、 Redash運用してます。 コイツでプロダクションデータの可視化なんかもやってて、非エンジニアの人に色々見せるのに重宝してました。

で、何が起こったのかというと↓な感じ

何やらかしたの?

元々、 Redash のバージョンが v1.0.0-rc.2 でした。 つい先日、v1がリリースされたので、喜び勇んで、運用しているRedashのバージョンをあげようとしました。

github.com

Redashのドキュメントを見ながら実行しようとしたんですが、どうもドキュメントは、AWSとかGCPとかで運用してるの前提に記載されてるらしい。

なら、立ち上がってるDocker Container を一度落として、Redashのリポジトリをpullすれば、アップグレードできるんじゃないかって思ったんです。

そして、 docker-compose down --remove-orphans を実行しました。してしまいました。

で、改めて docker-compose -d -f docker-compose.production.yml up を実行して、ブラウザで Redashを開いたところ、 Internal Server Error の文字が…

PostgreSQL のデータを確かめるために、↓を実行すると…

$ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                           NAMES
960b42350d18        redash/nginx:latest   "nginx -g 'daemon ..."   56 minutes ago      Up 56 minutes       443/tcp, 0.0.0.0:8090->80/tcp   redash_nginx_1
e853151fdff4        redash_server         "/app/bin/docker-e..."   56 minutes ago      Up 56 minutes       0.0.0.0:5000->5000/tcp          redash_server_1
fabcbe1076ac        postgres:9.3          "docker-entrypoint..."   56 minutes ago      Up 56 minutes       5432/tcp                        redash_postgres_1
50874f74a6fe        redis:2.8             "docker-entrypoint..."   56 minutes ago      Up 56 minutes       6379/tcp                        redash_redis_1
0d6d983060b4        redash_worker         "/app/bin/docker-e..."   56 minutes ago      Up 56 minutes       5000/tcp                        redash_worker_1

$ docker exec -it fabcbe1076ac /bin/bash
root@fabcbe1076ac:/# psql -U postgres
psql (9.3.16)
Type "help" for help.
postgres=# \dt
No relations found.

な、何もない!!!!!

@kiy0taka さんの天啓

というわけで、失意にくれて、某slackチャンネルで嘆いていると、 @kiy0taka さんが色々とアドバイスをくれました

kiy0taka [9:37 AM] 
Data Volumeごと消えちゃったの?

kuchitama [9:44 AM] 
docker立ち上げ直した時に、上書きされたっぽいすね…

kiy0taka [9:45 AM] 
なんと…

kuchitama [9:46 AM] 
docker-compose down がまずかったのかな…

kiy0taka [9:48 AM] 
あーもしかしてvolumeに名前つけてなかった?

kuchitama [9:51 AM] 
これをそのまま動かしてましたね〜
マジメに compose 勉強するか
https://github.com/getredash/redash/blob/master/docker-compose.production.yml

kiy0taka [9:52 AM] 
お、まだデータあるかも

[9:56]  
postgresのvolumeが指定されてないから `docker volume ls` したどれかに残ってるかもしれない

復旧するためにやったこと

  1. Volumeの確認
  2. PostgreSQLで使ってたVolumeの特定
  3. Volumeからpg_dumpを取得
  4. Volume名を指定してVolume作成
  5. 旧Volumeからデータコピー

Volumeの確認

まずは、今残っているVolumeの確認

$ docker volume list
DRIVER              VOLUME NAME
local               03caf1bf6ea2a81c3c11e699fb994f7f6eecf17ce34a424442d6d52bc461d006
local               066d7758d45f3e3bf53e7a8e6b000a43a0ecbdfd515402118b069b1f587d3f42
local               1cd40529441b334487a45cb46766f020229d78c3ac7f49618bb727898b34e561
local               241c844e7745b0478fe084c8c289e656c7843b9538e2e1789d37e971c5700a2a
local               2626cc49fae0425de3814f341b6b0f2d4c039bb8163c8a600100752eeda61d65
local               2d9eca5a4c13a533f7afb47ecffd20726c31dbffd4ab8604b538ceecc32c6401
local               4a80807c699663692c4e20039874851efc3ea1ea1836a40bbab8b7eca062fa7d
local               6f1efb9cf644d645d34e4905bf762248b4d3405fdcda8f645214d07d4d12cb27
local               70850d1355368612e3908ec7033ed805ae8f292673597c7b2bdc0bcc7616e14a
local               72669aa7e81aef5880e9d9323baadf479d8feeb12a811f6cc8f723533b8d184d
local               748cdf747fc8ff16cf5030de1d8dc96ca4af46896988717a310cad31bee98163
local               7aad2bd160a5780b02768da17e30541e68a5ebcf23fbf74319e4e8d157ceb575
local               7c55dc6918b3620f859b8dae54c5dc4cbaa774da77e0bf1505274aa068a53202
local               9817cf6340ec933949f5d021417a885d2ef33544f849053566b6d9f13ad4c07d
local               98336ea63f91ec5cf7c19e267daed350167f8040c148b701b0f79027e76e8418
local               c1612d3c38d3dd45ae7c17675d751316f418cdbde734650fd2340a90e2e8f739
local               c6130e1ce308011c2419bdfb525ea943cc26ff10b00bf958f65e97056be93837
local               c8525c0edd65e51b87cee226a213940d9430867d8222f373eaccfcb2f5310041
local               dd70b3531d7f6a722a140c1b875cf730d81e5486a93e6e3c674ad436d7457357
local               df15a22599482c15b845d3c6fb3e3272b3d0626dee546f55f82ee5a5990f0845
local               e0b8c01f409cc73b7c1d040dde080d062b35c46e13b09063078a05e5958f5a5f
local               f2533120680c4d5377579e25054a3b235a9a8f140474470b41aab5e9220c6056

この中のどれかに、Redashのpostgresデータが残っているはず! ということで、Volumeのディレクトリを見てみようとホストの /var/lib/docker/volumes を見ようとしますが、

/var/lib/docker ディレクトリがない!!!

というのも、 Docker for MacApple の Hypervisor 上で動作しています。つまり、仮想マシンにDockerコンテナがいるわけです。 そのため、 /var/lib/docker はホストマシン上には存在していません。

と、ここで更に @kiy0taka さんからアドバイスが!

screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty

で、Hipervisor上の仮想マシンにアクセスできました。

キヨタカ兄さんマジありがとう!!!

/ # cd /var/lib/docker/volumes/
/var/lib/docker/volumes # ls
03caf1bf6ea2a81c3c11e699fb994f7f6eecf17ce34a424442d6d52bc461d006
066d7758d45f3e3bf53e7a8e6b000a43a0ecbdfd515402118b069b1f587d3f42
1cd40529441b334487a45cb46766f020229d78c3ac7f49618bb727898b34e561
241c844e7745b0478fe084c8c289e656c7843b9538e2e1789d37e971c5700a2a
2626cc49fae0425de3814f341b6b0f2d4c039bb8163c8a600100752eeda61d65
2d9eca5a4c13a533f7afb47ecffd20726c31dbffd4ab8604b538ceecc32c6401
4a80807c699663692c4e20039874851efc3ea1ea1836a40bbab8b7eca062fa7d
6f1efb9cf644d645d34e4905bf762248b4d3405fdcda8f645214d07d4d12cb27
70850d1355368612e3908ec7033ed805ae8f292673597c7b2bdc0bcc7616e14a
72669aa7e81aef5880e9d9323baadf479d8feeb12a811f6cc8f723533b8d184d
748cdf747fc8ff16cf5030de1d8dc96ca4af46896988717a310cad31bee98163
7aad2bd160a5780b02768da17e30541e68a5ebcf23fbf74319e4e8d157ceb575
7c55dc6918b3620f859b8dae54c5dc4cbaa774da77e0bf1505274aa068a53202
9817cf6340ec933949f5d021417a885d2ef33544f849053566b6d9f13ad4c07d
98336ea63f91ec5cf7c19e267daed350167f8040c148b701b0f79027e76e8418
c1612d3c38d3dd45ae7c17675d751316f418cdbde734650fd2340a90e2e8f739
c6130e1ce308011c2419bdfb525ea943cc26ff10b00bf958f65e97056be93837
c8525c0edd65e51b87cee226a213940d9430867d8222f373eaccfcb2f5310041
dd70b3531d7f6a722a140c1b875cf730d81e5486a93e6e3c674ad436d7457357
df15a22599482c15b845d3c6fb3e3272b3d0626dee546f55f82ee5a5990f0845
e0b8c01f409cc73b7c1d040dde080d062b35c46e13b09063078a05e5958f5a5f
f2533120680c4d5377579e25054a3b235a9a8f140474470b41aab5e9220c6056
metadata.db

postgreで使ってたVolumeの特定

この中から、Postgresコンテナ で利用してたVolumeを特定します

/var/lib/docker/volumes # find . | grep pg_clog 
./241c844e7745b0478fe084c8c289e656c7843b9538e2e1789d37e971c5700a2a/_data/pg_clog
./241c844e7745b0478fe084c8c289e656c7843b9538e2e1789d37e971c5700a2a/_data/pg_clog/0000
./7aad2bd160a5780b02768da17e30541e68a5ebcf23fbf74319e4e8d157ceb575/_data/pg_clog
./7aad2bd160a5780b02768da17e30541e68a5ebcf23fbf74319e4e8d157ceb575/_data/pg_clog/0000
./2626cc49fae0425de3814f341b6b0f2d4c039bb8163c8a600100752eeda61d65/_data/pg_clog
./2626cc49fae0425de3814f341b6b0f2d4c039bb8163c8a600100752eeda61d65/_data/pg_clog/0000
./7c55dc6918b3620f859b8dae54c5dc4cbaa774da77e0bf1505274aa068a53202/_data/pg_clog
./7c55dc6918b3620f859b8dae54c5dc4cbaa774da77e0bf1505274aa068a53202/_data/pg_clog/0000
./e0b8c01f409cc73b7c1d040dde080d062b35c46e13b09063078a05e5958f5a5f/_data/pg_clog
./e0b8c01f409cc73b7c1d040dde080d062b35c46e13b09063078a05e5958f5a5f/_data/pg_clog/0000
./c8525c0edd65e51b87cee226a213940d9430867d8222f373eaccfcb2f5310041/_data/pg_clog
./c8525c0edd65e51b87cee226a213940d9430867d8222f373eaccfcb2f5310041/_data/pg_clog/0000
./98336ea63f91ec5cf7c19e267daed350167f8040c148b701b0f79027e76e8418/_data/pg_clog
./98336ea63f91ec5cf7c19e267daed350167f8040c148b701b0f79027e76e8418/_data/pg_clog/0000
./1cd40529441b334487a45cb46766f020229d78c3ac7f49618bb727898b34e561/_data/pg_clog
./1cd40529441b334487a45cb46766f020229d78c3ac7f49618bb727898b34e561/_data/pg_clog/0000

候補は8件に絞られました。

そこから、どれが運用してたRedashのPostgresのボリュームなのかを特定するために↓で1つずつ調べて回ります。 1つずつVolumeをバインドした Postgres のコンテナを立ち上げて、DBの中身を確認していく地道な作業です

$ docker run -d -v {絞り込んだvolumeのID}:/var/lib/postgresql/data -p 5432:5432 postgres:9.3
$ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                           NAMES
295afcefc16c        postgres:9.3          "docker-entrypoint..."   11 seconds ago      Up 6 seconds        0.0.0.0:5432->5432/tcp          objective_feynman

$ docker exec -it {↑のコンテナID} /bin/bash

# psql -U postgres

postgres=# \dt

postgres=# select * from users;

postgres=# \q

# exit

$ docker kill {↑のコンテナID}

この繰り返しで、Redashのデータが入っていたVolumeが特定できました。

Volumeからpg_dumpを取得

データが入っていたVolumeが特定できたので、今後なにが起こってもいいようにまずはデータをバックアップしておきます。 DBのデータを確認したのと同じ要領で、Postgresのコンテナを立ち上げて、pg_dumpを実行して、docker cp でファイルをホストマシンに保存しました。

$ docker run -d -v {絞り込んだvolumeのID}:/var/lib/postgresql/data -p 5432:5432 postgres:9.3
$ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                           NAMES
295afcefc16c        postgres:9.3          "docker-entrypoint..."   11 seconds ago      Up 6 seconds        0.0.0.0:5432->5432/tcp          objective_feynman

$ docker exec -it {↑のコンテナID} /bin/bash

# pg_dump -U postgres postgres | gzip > /usr/local/redash_backup.gz

# exit

$ docker cp 295afcefc16c:/usr/local/redash_backup.gz ~/Desktop

Volume名を指定してVolume作成

まずは、2度とVolumeが変わってしまわないように、Volume名を指定します。 ここでも、 @kiy0taka さんのアドバイス

このgistにあるように、 postgresvolumes と一番下にあるトップレベルの volumes を指定しました。 この辺の設定は↓に記載が有ります。

docs.docker.com

そんでもって、一旦 docker-compose up して、 down します。 これで、名前のついたVolumeが作られます。

$docker-compose -f docker-compose.production.yml up -d
Creating network "redash_default" with the default driver
Creating volume "redash_postgres_data" with default driver
Creating redash_worker_1
Creating redash_redis_1
Creating redash_postgres_1
Creating redash_server_1
Creating redash_nginx_1

$ docker volume list
DRIVER              VOLUME NAME
# ...中略...
local               redash_postgres_data

これで、何度 docker-compose up しても、同じVolumeが RedashのPostgresコンテナにバインドされます。

旧Volumeからデータコピー

新しい redash_postgres_data Volumeを常に利用するようになったので、このVolumeを元のVolumeで上書きしました。 まず、コンテナを落として、Hipervisor上でファイルを上書きしてしまいます。

$ docker-compose down --remove-orphans                 
Stopping redash_server_1 ... done
Stopping redash_redis_1 ... done
Stopping redash_postgres_1 ... done
Stopping redash_worker_1 ... done
Removing orphan container "redash_nginx_1"
Removing redash_server_1 ... done
Removing redash_redis_1 ... done
Removing redash_postgres_1 ... done
Removing redash_worker_1 ... done
Removing network redash_default

$ screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty

/ # cd /var/lib/docker/volumes/
/var/lib/docker/volumes cp -R 7aad2bd160a5780b02768da17e30541e68a5ebcf23fbf74319e4e8d157ceb575/_data/ redash_postgres_data/

(Ctrl+a):kill

これで、docker-compose up して、ブラウザでRedashを開いてみると、ちゃんと表示されました。

f:id:kuchitama:20170405142923j:plain

た、助かったぁぁぁ

composeをちゃんと身に着けたいので

この辺読んでみよう(目次にcomposeの項目がある)

Docker入門

Docker入門

Docker

Docker

最後に

ほんとに @kiy0taka さんありがとうございました

人って温かい。。。

そういえば、 @kiy0taka 兄さんには、社会人なりたてのころにもこんなこと教えてもらったりしてたなぁ

kuchitama.hateblo.jp

追加

バックアップとリストアの手順をまとめました

kuchitama.hateblo.jp