dockerでDBを使っているとデータを永続化させるためにローカルの特定のディレクトリなどをマウントさせる事が多い。運用しているdocker-composeを次のような感じで書いていた。
image: mongo:3.6 restart: unless-stopped volumes: - mongo_configdb:/data/configdb - mongo_db:/data/db restart: always volumes: mongo_db:
まぁこれで全然問題なかったのだけど、volumesで特にパスを指定していなかった。
そのため /var/lib/docker/volumes
以下に動かしているコンテナ名でディレクトリが作成されていて、そのディレクトリがmountされている感じで動いていた。
/var/lib/docker
以下に保存していると、なにかdocker pruneとかしてしまうとファイルが消えてしまう可能性があるらしい。それは避けたいのでローカルディレクトリ上に保存しようとした。
ファイルの移動
どうも調べていると一度volumeとimageを消さないと移動はできないらしい。
mvで移動しても良かったが、最初にbackupがてらcpでディレクトリごとコピーした。 今思い返せばcpじゃなくてrsync使ってたほうが良かったのかもしれない。
$cp -r /var/lib/docker/volumes /home/anatofuz/backup
この時点で/var/lib/docker/volumes
を ls -l
したら全てroot:root
になっていたので油断していた。
ホームディレクトリに移したのでanatofuz:docker
くらいにchownしていた。
docker-composeへの追記
docker-composeにカレントディレクトリ以下にデータを保存させたかったので次の様な感じで追記をした。
volumes: growi_data: driver_opts: type: none device: /home/anatofuz/growi/data/growi_growi_data o: bind mongo_configdb: driver_opts: type: none device: /home/anatofuz/growi/data/growi_mongo_configdb o: bind mongo_db: driver_opts: type: none device: /home/anatofuz/growi/data/growi_mongo_db o: bind es_data: driver_opts: type: none device: /home/anatofuz/growi/data/growi_es_data o: bind
docer-compose stop
してdocker-compose rm
したあとにdocer-compose build
しようとしたら所、 volumeを消せと言われたのでポチポチvolumeを消していった。
ビルド時のpermission
ビルドするとこんな感じになる
Successfully built e3a815260e49 Successfully tagged growi_elasticsearch:latest Building app Traceback (most recent call last): File "bin/docker-compose", line 6, in <module> File "compose/cli/main.py", line 72, in main File "compose/cli/main.py", line 128, in perform_command File "compose/cli/main.py", line 304, in build File "compose/project.py", line 397, in build File "compose/project.py", line 380, in build_service File "compose/service.py", line 1104, in build File "site-packages/docker/api/build.py", line 160, in build File "site-packages/docker/utils/build.py", line 30, in tar File "site-packages/docker/utils/build.py", line 49, in exclude_paths File "site-packages/docker/utils/build.py", line 214, in rec_walk File "site-packages/docker/utils/build.py", line 214, in rec_walk File "site-packages/docker/utils/build.py", line 214, in rec_walk File "site-packages/docker/utils/build.py", line 184, in rec_walk PermissionError: [Errno 13] Permission denied: '/home/anatofuz/growi/data/growi_mariadb_data/mysql' [395570] Failed to execute script docker-compose
そもそもappは次の様にdocker-compose.ymlを書いている。
app: build: context: . dockerfile: ./Dockerfile ports: - 3000:3000 links: - mongo:mongo - elasticsearch:elasticsearch depends_on: - mongo - elasticsearch environment: - MONGO_URI=mongodb://mongo:27017/growi - ELASTICSEARCH_URI=http://elasticsearch:9200/growi # - FILE_UPLOAD=mongodb # activate this line if you use MongoDB GridFS rather than AWS - FILE_UPLOAD=local # activate this line if you use local storage of server rather than AWS - MATHJAX=1 # activate this line if you want to use MathJax command: "dockerize -wait tcp://mongo:27017 -wait tcp://elasticsearch:9200 -timeout 60s npm run server:prod" restart: unless-stopped volumes: - growi_data:/data restart: always
mariadbのdataにアクセスする必要は無いと思うのだけれど、なぜかこのパーミッションで怒られている。dataディレクトリの中でコンテナごとにディレクトリを切っていたけれど、この運用が駄目だったのかもしれない。
root:root
なのが怪しいのかと思いchownで変更した。
sudo chown -R anatofuz:docker data/
こうするとbuildは通った。
起動するとDBの中身を読んでくれない問題
build通ったので喜びながらdocker-compose upしたがアプリケーションの初期設定画面が表示されてしまっていた。DBがデータを読んでなさそうな気配はあったが、docker-composeのlogを見る限りPermission関連で怒られている気配はない。
色々見た結果、もともと/var/lib/docker/volumes
の中にあったgrowi_growi_data
の様なコンテナ名のディレクトリをプロジェクトのdata
ディレクトリにコピっていた。このコピー先の/home/anatofuz/growi/data/growi_growi_data
をdocker-composeでvolumeとして指定していたのだけど、これが駄目だった。
実際には/home/anatofuz/growi/data/growi_growi_data
の中に_data
ディレクトリがあり、このディレクトリの中に実際のデータが存在している。つまりこの_data
まで指定しなければならない。
今回はdocker-composeを操作せずに、各コンテナ名ディレクトリの_data
をmv ..
して解決した。正直この解決方法が正しいかは微妙である。
とはいえ
もう一度docer-compose build
すると、相変わらず
PermissionError: [Errno 13] Permission denied: '/home/anatofuz/growi/data/growi_mariadb_data/mysql' [395570] Failed to execute script docker-compose
と怒られてしまう。
$ ls -l data/ total 56 drwxr-xr-x 3 anatofuz docker 4096 Jun 4 23:18 growi_es_data drwxr-xr-x 3 anatofuz docker 4096 Jun 4 23:18 growi_growi_data drwxr-xr-x 4 anatofuz docker 4096 Jun 4 23:18 growi_https-portal_data drwxr-xr-x 5 999 docker 4096 Jun 4 23:23 growi_mariadb_data drwxr-xr-x 2 999 docker 4096 Apr 30 02:20 growi_mongo_configdb drwxr-xr-x 4 999 docker 4096 Jun 5 08:53 growi_mongo_db -rw------- 1 anatofuz docker 65536 Jun 4 23:18 metadata.db
どうもdocker-compose run
した瞬間にmariadbなどのDB系のユーザーが999で実行されてしまい、anatofuzで起動しているgrowi(app)からは参照できないらしい。
実際にps aux
するとmariadbが999ユーザーで実行されていた。/var/lib/docker/volumes
で実行していたときは999ではなくrootで動いていた気がするので、なぜこうなったかはよく解っていない。
所感
/var/lib/docker/volumes
に結局データが保存されるのであれば、別にわざわざ違うディレクトリをマウントしようと頑張る必要はなかったのかもしれない。少なくともdocker-compose build
がスムーズに行かなくなってしまった。
dockerのvolumeを適当なディレクトリに保存して永続化させるよりは、mongodbやmysqlなどのコンテナにattachするなりしてバックアップを取っていくほうが無難であるかなという気がした。今の環境を元に戻すかは怪しいところ。戻せたら良いんだけど…
全体的にdockerよく解っていないことが露呈しているので、なぜこうなったか検討がつく方がいれば教えていただけると嬉しいです
追記 (2020/06/08)
'/home/anatofuz/growi/data/
以下においていた999ユーザーで実行されてしまうDB系のファイル群を
'/home/anatofuz/db/data
の様なトップディレクトリが異なるディレクトリ内に移動させてvolumeを作り直したところ、docker-compose build
時のパーミッション問題は出なくなった。
おそらくappのビルド時にカレントディレクトリをマウントしていて、カレントディレクトリ以下のファイルのパーミッションは全て確認する挙動のような気がする。