Magicode logo
Magicode
0
4 min read

docker-composeでpostgresのDBが永続化できていなかったのを直した

問題

今いるプロジェクトで、docker-composeで名前付きvolumeを使っているのにも関わらず、postgresのDBが永続化できませんでした。 なので、docker-compose downをするとDBが消えてしまい、docker-compose upした後にその都度rake db:createやらrake db:migrateをやりなおさないといけないという感じでした。

まぁ、そんな頻繁にdocker-compose downしなければいいとはいえ、たまにdocker-compose downした時にいちいちDBを作成しなおすのは面倒ですし、必要なデータが存在する場合はDBを削除できないので、誤ってdocker-compose downしないように気をつけないといけません。

余計な部分は省いていますが、当初のdocker-compose.ymlは以下のような感じでした。 ( postgresのDBを永続化するために、名前付きvolumeを作成して、postgresコンテナ内の/var/lib/postgresqlとマウントしています)

version: '3'
services:

  postgres:
    environment:
     - (略)
    image: postgres:10.5-alpine
    volumes:
      - postgres_volume:/var/lib/postgresql # <名前付きvolume名>:マウントしたいコンテナ内のPATH
    ports:
      - "5432:5432"

volumes:
  postgres_volume: # 名前付きvolumeを定義

postgresコンテナの情報をdocker inspectで確認してみると、勝手に匿名ボリューム(anonymous volume)が作成されpostgresコンテナとマウントしているのがわかりました。。うーむ、名前付きvolumeを指定してるんだけどなー:thinking:

docker inspect <コンテナID>

解決方法

結論いうと、volumesプロパティで指定しているコンテナ側のPATHが誤っていました。

【誤】 postgres_volume:/var/lib/postgresql
【正】 postgres_volume:/var/lib/postgresql/data

解説

postgresのDockerfileにあるVOLUME命令

Dockerhubにて、postgresDockerfileを見ると原因がわかります。 postgresDockerfileに以下の記述があります。

VOLUME [/var/lib/postgresql/data]

https://hub.docker.com/layers/postgres/library/postgres/10.5-alpine/images/sha256-294f651dec48ecd86c1ba6cd33e589ed669f0e355ed8c8a2a53f5287b4650f80?context=explore#:~:text=14-,VOLUME,-%5B/var/lib/postgresql

VOLUME命令とは?

Dockerfileで、VOLUME命令を指定すると匿名volumeが自動で作成されるそうです。

https://qiita.com/daemokra/items/322270091cf41a853226#dockerfile%E3%81%AEvolume%E6%96%87%E3%81%A8volumes%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E4%BD%B5%E7%94%A8%E3%81%97%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E6%8C%99%E5%8B%95

なぜ解決した?

再度以下を見てください。

【誤】 postgres_volume:/var/lib/postgresql
【正】 postgres_volume:/var/lib/postgresql/data

上記の記事によれば、DockerfileVOLUME命令で指定されているPATHと同じPATHを、名前付きvolumeのマウント先として指定すると、匿名volumeが作成されず、名前付きvolumeが使用される挙動になるそうです。 実際に試した所そのような挙動となることを確認しました。

なので、DBが永続化できていなかった原因は、docker-compose.ymlにて、名前付きボリュームがマウントするpostgresコンテナのPATHの指定が間違っていたことでした。

補足

匿名ボリュームが作成されてるので、永続化できそうな気もしますが、実際のところ匿名ボリュームはコンテナを削除して作成するたびに作られいて、使い回されないみたいです。 ただ過去の匿名ボリュームは使い回されないだけで、ずっと残りつづけていて、ストレージを逼迫する原因になります。 自分は過去の匿名ボリュームだけでMACのストレージを50GBくらい使ってました:sweat_smile:

以下でvolume一覧が確認可能です。

docker volume ls

不要なvolumeを削除したい場合は以下のコマンドでできます。(現在存在するコンテナと紐付いてないvolumeのみ削除)

docker volume rm $(docker volume ls -qf dangling=true)

https://www.digitalocean.com/community/tutorials/how-to-remove-docker-images-containers-and-volumes-ja

参考

https://hub.docker.com/layers/postgres/library/postgres/10.5-alpine/images/sha256-294f651dec48ecd86c1ba6cd33e589ed669f0e355ed8c8a2a53f5287b4650f80?context=explore

https://qiita.com/daemokra/items/322270091cf41a853226#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB

https://stackoverflow.com/questions/61623124/persist-data-on-postgres-docker-with-a-volume-when-restarting-the-container

https://www.digitalocean.com/community/tutorials/how-to-remove-docker-images-containers-and-volumes-ja

Discussion

コメントにはログインが必要です。