docker-composeで構築したgrowiを移行したときの手順

**docker-compose**で**growi**の動作環境を構築して使用していたのですが、
急遽別のPC上に移行する予定ができたため、その時の手順を備忘として記事にしたいと思います。

# 大まかな移行の流れ
1. データボリュームのバックアップ取得（移行元）
2. データボリュームのバックアップを復元（移行先）  
→データのみを移行する。移行元からデータを抽出し、それを移行先のコンテナ内の然るべき場所にコピーしてあげるイメージ。

# コンテナのイメージバックアップは何故不要なのか
本来であればコンテナのイメージバックアップをとるような仕組みはよろしくない。バックアップを必要とすることはあってはならない。docker-composeファイルやDockerfileですべて完結されるべきでファイルさえあれば常に同じ環境が構築（他人へ再配布）できるような仕組みが良いとされている。よって今回はイメージのバックアップは不要と考えた。というよりイメージは最新のgrowiを[こちら](https://github.com/weseek/growi-docker-compose)からインストールすれば問題ない。

# コンテナのデータボリュームバックアップは何故必要なのか
コンテナイメージにはデータボリュームが含まれない。
よって、ボリュームは別途バックアップをとる必要がある。
データボリュームのバックアップをしないと、mongoDB上のデータやgrowiに保存したファイル群が移行できない。

**今回は登録した文字列データ（mongoDB）と、画像やファイルデータ（growi）の移行をします。**

# 移行元での作業
## コンテナID,コンテナ名の確認
```sh
# プロセスの表示（コンテナID、コンテナ名の確認）
> docker ps

CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                    NAMES
25cd411382ae        growi_app                  "/docker-entrypoint.…"   5 weeks ago         Up 14 seconds       0.0.0.0:3000->3000/tcp   growi_app_1
d05394ccca69        elasticsearch:5.3-alpine   "/docker-entrypoint.…"   6 weeks ago         Up 15 seconds       9200/tcp, 9300/tcp       growi_elasticsearch_1
ba9fd7329905        mongo:3.4                  "docker-entrypoint.s…"   2 months ago        Up 15 seconds       27017/tcp                growi_mongo_1
```

## コンテナの停止
```sh
> docker-compose stop

# 確認
> docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```


## データボリュームのバックアップ
事前にカレントディレクトリに`backup`フォルダを作成しておく。
バックアップのコマンド例は下記

```sh
docker run --volumes-from <コンテナID> --mount type=bind,src="$(pwd)/backup",dst=/backup -it <イメージ名> tar cvf /backup/圧縮ファイル名.tar <マウントポイント>
```

`<マウントポイント>`に関しては、`docker inspect <コンテナID>`コマンドで出てくる`"Mounts"`にある`"Destination"`に記載されているPAHTを指定した。

実際に使用したコマンドは下記

```sh
# mongoDB
> docker run --volumes-from ba9fd7329905 --mount type=bind,src="$(pwd)/backup",dst=/backup -it mongo:3.4 tar cvf /backup/20180927growi_mongo_db.tar /data/db

# growi
> docker run --volumes-from 25cd411382ae --mount type=bind,src="$(pwd)/backup",dst=/backup -it growi_app tar cvf /backup/20180927growi_growi_data.tar /data
```

tarファイルが生成されているはずなので、これをUSBか何かで移行先のPCに移動させる。
（移行先のPCも移行元と同じフォルダ階層にしておくと分かりやすくて良いと思った）

これで移行元での作業は終了。

# 移行先での作業
事前にdocker、growiのインストールは済ませ、起動している状態であること

## コンテナ名の確認
※ここに記載しているコンテナIDなどは架空のものです

```sh
> docker ps

CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                    NAMES
25cd411382xx        growi_app                  "/docker-entrypoint.…"   7 weeks ago         Up 3 hours          0.0.0.0:3000->3000/tcp   growi_app_1
d05394cccayy        elasticsearch:5.3-alpine   "/docker-entrypoint.…"   7 weeks ago         Up 3 hours          9200/tcp, 9300/tcp       growi_elasticsearch_1
ba9fd73299zz        mongo:3.4                  "docker-entrypoint.s…"   2 months ago        Up 3 hours          27017/tcp                growi_mongo_1
```

## コンテナにログイン
`docker exec -it <コンテナ名> /bin/bash`で基本的にログインできる。
もし上記でログインできない場合は
`docker exec -it <コンテナ名> sh`で入れるはず。
（実際、growi_app_1には下の方法でしか入れなかった。なぜ2パターンあるかは不明。誰か教えて下さい・・・）


## コンテナ内のデータコピー先対象フォルダの確認

- **growi：** *docker exec -it <コンテナ名> sh* でログイン
コンテナログインした段階で、`/opt/growi`にいると思うので、`cd..`を2回行いrootまでいく。
そして、`ls`すると`data`ディレクトリがあるため、そこから`data/upload/`まで移動する。
ここがコピー先のディレクトリになる。（最初は何もデータがない）


- **mongoDB：** *docker exec -it <コンテナ名> /bin/bash* でログイン
`data/db`
ここがコピー先のディレクトリになる。（最初からデータがある。上書き更新するイメージ）


## ホスト(ローカル)のデータをコンテナにコピー

- **growi**
    データボリュームのバックアップで取得したtarファイルを解凍して、growiフォルダ直下に配置する。
    （今回はattachmentフォルダ以下を配置 growi - attachmant）
    `docker cp attachment <コピー先のコンテナID>:/data/uploads/`でホスト→コンテナへコピーする。
    `/data/uploads/`は一つ前の手順で確認したコピー先のディレクトリ
    
- **mongoDB**
データボリュームのバックアップで取得したtarファイルを解凍して、growiフォルダ直下に配置する。
（今回はdbフォルダ以下を配置 growi - db）
直接`data/db`にコピーしようとしたら上手くいかなかったため、一度`data/db_new`にコピーした。
    
```sh
> docker cp db <コピー先のコンテナID>:/data/db_new
# （db_newはコピー先のフォルダ名。あとで削除するため任意の名前で良い）
 ```

ここまでで、`/data/db_new/`配下にデータボリュームバックアップで取得したデータ群がコピーされる。
ここから、コンテナにログインし、`/data/db_new/`まで移動した後に`cp -frp * /data/db`コマンドで然るべきフォルダへのコピーが完了する。
(確認として、`/data/db`フォルダに移動し`ls -l`コマンドでデータがコピーされていることを確認する)

`db_new`フォルダを削除して作業完了。


## 再起動
最後に再起動して、データが反映されていれば終了
①`docker-compose stop`
②`docker-compose up -d`
③[ログイン - GROWI](http://127.0.0.1:3000/)


# 感想

データボリュームをバックアップするコマンドがなかなか見つからず、苦労した。
結果的には小手先だけではダメだと思い、dockerの仕組みをもう一度勉強しなおしました。
これが功を奏して?上手くで移行できました。