Dockerで立ち上げたMastodonのDBを後から永続化する

# 概要
Mastodon、流行っていますね。私も勢いに乗ってAzure上に[インスタンス](https://mastodon.yuu26.com/about/more)を立ち上げました。
見事にデータの永続化設定を忘れたまま起動して今に至ります。

v1.2に上げるためにコンテナを一度落とす必要が出てきましたが、
どうにかデータを維持したまま再起動ができたため、メモしておきます。

![mastodon](https://camo.githubusercontent.com/61d9a02e23c4281ebe954a4518af14c931a9493b/68747470733a2f2f6d6173746f646f6e2e736f6369616c2f6f6f70732e706e67)

……飛んでいくデータを表現しているみたいで嫌ですね。


# ホスト内にデータ格納先を作成
今回は `/usr/share/mastodon` に諸々置いていたため、同じ場所に作成しました。

```shell-session:postgres用ディレクトリ作成
[root@mstdn001 ~]# mkdir /usr/share/mastodon/postgresql
```


# 対象コンテナの確認
PostgreSQLのコンテナ名を確認します。（横スクロールで見えます）

```shell-session:コンテナ名の確認
[root@mstdn001 ~]# docker ps
CONTAINER ID     IMAGE               COMMAND                  CREATED         STATUS          PORTS                              NAMES
d849f18a9e9b     gargron/mastodon    "bundle exec rails s "   3 days ago      Up 3 days       0.0.0.0:3000->3000/tcp, 4000/tcp   mastodon_web_1
c8fbcc7633de     gargron/mastodon    "bundle exec sidekiq "   3 days ago      Up 3 days       3000/tcp, 4000/tcp                 mastodon_sidekiq_1
33db6dcac1cd     gargron/mastodon    "npm run start"          3 days ago      Up 3 days       3000/tcp, 0.0.0.0:4000->4000/tcp   mastodon_streaming_1
3829643b3b41     postgres:9.6-alpine "docker-entrypoint.sh"   3 days ago      Up 3 days       5432/tcp                           mastodon_db_1
0d764d54cc62     redis:alpine        "docker-entrypoint.sh"   3 days ago      Up 3 days       6379/tcp                           mastodon_redis_1
```
postgresが動作しているのは `mastodon_db_1` ですね。


# データの救出
`docker cp` というコマンドで、実データをコンテナ内から取り出します。
`docker cp <コンテナ名>:<コンテナ内のフルパス> <ホストの相対パス>` の形で入力します。

```shell-session:postgresのデータを救出
[root@mstdn001 ~]# cd /usr/share/mastodon
[root@mstdn001 mastodon]# docker-compose pause
[root@mstdn001 mastodon]# docker cp mastodon_db_1:/var/lib/postgresql/data ./postgresql/data
```

```shell-session:コピー結果を確認
[root@mstdn001 mastodon]# ls -l ./postgresql/data/
total 56
drwx------. 5 root root    41 Apr 15 14:49 base
drwx------. 2 root root  4096 Apr 17 18:36 global
drwx------. 2 root root    18 Apr 15 14:49 pg_clog
drwx------. 2 root root     6 Apr 15 14:49 pg_commit_ts
drwx------. 2 root root     6 Apr 15 14:49 pg_dynshmem
-rw-------. 1 root root  4492 Apr 15 14:49 pg_hba.conf
-rw-------. 1 root root  1636 Apr 15 14:49 pg_ident.conf
drwx------. 4 root root    39 Apr 15 14:49 pg_logical
drwx------. 4 root root    36 Apr 15 14:49 pg_multixact
drwx------. 2 root root    18 Apr 15 15:20 pg_notify
drwx------. 2 root root     6 Apr 15 14:49 pg_replslot
drwx------. 2 root root     6 Apr 15 14:49 pg_serial
drwx------. 2 root root     6 Apr 15 14:49 pg_snapshots
drwx------. 2 root root     6 Apr 15 15:20 pg_stat
drwx------. 2 root root    63 Apr 18 21:46 pg_stat_tmp
drwx------. 2 root root    18 Apr 15 14:49 pg_subtrans
drwx------. 2 root root     6 Apr 15 14:49 pg_tblspc
drwx------. 2 root root     6 Apr 15 14:49 pg_twophase
-rw-------. 1 root root     4 Apr 15 14:49 PG_VERSION
drwx------. 3 root root    92 Apr 18 17:26 pg_xlog
-rw-------. 1 root root    88 Apr 15 14:49 postgresql.auto.conf
-rw-------. 1 root root 22205 Apr 15 14:49 postgresql.conf
-rw-------. 1 root root    24 Apr 15 15:20 postmaster.opts
-rw-------. 1 root root    85 Apr 15 15:20 postmaster.pid
```


# docker-compose.yml の修正
`docker-compose.yml` を修正して、ホストとコンテナのディレクトリを紐付けます。
`Uncomment to enable DB persistance` の下2行がコメントになっているので解除し、パスを修正します。
`- <ホストの相対パス>:<コンテナ内のフルパス>` となります。先ほどとは逆なので注意です。

```yaml:docker-compose.yml
version: '2'
services:

  db:
    restart: always
    image: postgres:9.6-alpine
### Uncomment to enable DB persistance
     volumes:
       - ./postgres/data:/var/lib/postgresql/data


#(以下略)

# 今回の内容とは関係ありませんが、
# 「image: postgres:alpine」を「image: postgres:9.6-alpine」に書き換えることで、
# 勝手にPostgresのバージョンが上がることを防いでいます。
```


# コンテナの再起動
Postgres用コンテナを再起動します。
docker-compose を利用するためディレクトリの移動を忘れずに。

```shell-session:dbコンテナを再起動
[root@mstdn001 ~]# cd /usr/share/mastodon/
[root@mstdn001 mastodon]# docker-compose unpause
[root@mstdn001 mastodon]# docker-compose up -d db
Starting mastodon_db_1
```


# 動作確認
PCや適当なクライアントから繋いでみたり、トゥートしてみて確認します。
ちゃんと動いていて、過去のデータも残っていれば完璧です。

先にdocker-compose.ymlを修正しておいて、`docker cp` からコンテナ再起動までの時間をなるべく短くした方が良いかもしれません。


# 参考情報
下記サイト等を参考にしました。ありがとうございました。

* [MastodonをDB永続化忘れて起動したけど最小限の犠牲で済ませた - new_pill’s blog](http://new-pill.hatenablog.com/entry/2017/04/17/230333)
* [Mastodon を Docker で立てるときに最低限しておくこと - chaotic valkyrie](http://cryks.hateblo.jp/entry/2017/04/16/145547)

**2017/04/19 追記**
@hidekuro さんからの[編集リクエスト](http://qiita.com/yuu26/items/d4b9df0ba2d46e6b9f69/patches)を元に、手順を一部修正しました。
アドバイスありがとうございました！