docker-composeでマウント先を間違えると大変なことになる。

とあるシステムをDocker-Composeで構築し、運用していました。
サンプルとして、gitbucketをpostgresqlで運用したものを上げます。
中身はこんな感じです。

```yaml
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
以下略
```

ファイルはあります。しかし妙です。容量があからさまに少ないです。
ではコンテナがどうなっているか見てみます。

```js
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で述したディレクトリは、外部とのマウントポイントとなります。
それ以外のディレクトリはマウントできないわけではないのですが、```特にエラーもなくこのように無視されることもあります```
[ドキュメント](http://docs.docker.jp/engine/reference/builder.html#volume)によると、

>VOLUME 命令は指定した名前でマウントポイントを作成し、他のホストやコンテナから外部マウント可能なボリュームにします。
>docker run コマンドは、ベース・イメージから指定した場所に、データを保存する場所として新規作成したボリュームを初期化します。

つまり、明示的にマウントしないものは、docker runした時点で自動的にボリュームが作成され、初期化されるようです。
ただし、このボリュームは明示的に指示していないのでランダムな文字列で作成され、コンテナ再作成時に別名で作られます。以前のは明示的に消さない限りは残るようですが、当時のコンテナを消してしまっていると、docker inspectで調べることもできず、特定作業は困難となります・・

# 最後に
ちゃんと作成したデータボリュームにデータが格納されているか確認しよう。
面倒でも、バックアップを取りましょう。
自分はコンテナはどうせ作り替えだし、データボリュームは消えないからと、**どうせなら全部きれいにしてしまえ**とバックアップ取らず```docker image prune```したりしたので、頭の中もまっさらになりました（涙

# 追記
Dockerを長く運用していると不要なイメージがたまって容量を食うので、ググると最近は

```
docker system prune 
```

でOK！みたいなのが結構引っかかるのですが、
これは```停止中のコンテナ、関連リソースすべて吹っ飛ばします```

停止中＝不要とはかならずしもならないと思いますので、盲目的にググってコピペして実行しないようにしましょう。