先週、NISA(一般社団法人長崎県情報産業協会)の『Pythonと Docker ではじめる Web アプリ開発&運用入門』という研修に参加しました。
その中でコンテナ上のデータベースの論理バックアップの話があり、ホストPCにdumpツールを入れて普通にバックアップすればOKという流れだったのですが、自分はこの考え方で面倒な状況に陥ったことがありましたので
「稼働中のデータベースコンテナと同じイメージ上のdumpツールを別コンテナ起動してバックアップした方がバージョンミスマッチを回避できるので良いと思います」
というフィードバックをしました。
講師の方には伝わっていたと思いますが、痛い目の話、実際の例、あとちょっとしたハマりどころについて書いておこうと思います。
今回の研修はMariadbでしたし、出力がSQLスクリプトのdumpをする場合はそもそもあまり問題ないと思います。
自分の場合はPostgreSQLを使うことが多く、pg_dumpのバージョンミスマッチでdumpできなくなるということを複数回経験しています。
今回のようにホストPCにツールを入れる場合ですが、コンテナとホストPCのOSが同じとは限らない(というか違うことが多い)わけで運用していくうちにコンテナで稼働しているデータベースのバージョンとホストPCのツールのバージョンを合わせるのが面倒な状況になることが結構あります。
他の例としては、昔、開発環境として Laradock (https://laradock.io/) を使っていたのですが、Laradock ではデータベースコンテナと作業用のコンテナが別になっています。作業用のコンテナにデータベースのクライアントツールを導入して扱うという形になるのですが、コンテナ間のバージョンを合わせるのが面倒で早々に破綻しました。
そんなわけで、データベースコンテナ(のイメージ)には対応したバージョンのクライアントツールが入っているんだからそれを使うのがいいんじゃない?というわけです。
自分の場合、コンテナまわりの操作は docker compose、データベースはPostgreSQLのことが多いので、その組み合わせでの例とさせていただきます。
データベースコンテナのサービス名が postgres 、データベースがsampledb、データベースユーザーがsampleuser、パスワードがsamplepassとします。
docker compose exec -T postgres bash -c "PGPASSWORD=samplepass pg_dump -Fc --no-acl --no-owner -h postgres -U sampleuser sampledb" > sampledb.dump
PGPASSWORDをコマンドラインで書いちゃってるのはあまり良くないですね。
リストアも同じようにできると思いますが、自分はエラーメッセージなど確認したいので一旦コンテナにdumpファイルをコピーしてコンテナ上で実施しています。
# ホストPC上
$ docker compose cp sampledb.dump postgres:/tmp/
$ docker compose exec postgres bash
# コンテナ上
root@440414c73f7a:/# pg_restore -U sampleuser -d sampledb /tmp/sampledb.dump
root@440414c73f7a:/# rm /tmp/sampledb.dump
前述の exec でオプションに -T (–no-TTYでもOK)を指定しているのに注目してください。これは疑似 TTY 割り当てを無効化するものです。
TTY有効だとpg_dumpからバイナリで出力されたファイルが破損します。
ややこしいのがdocker compose execだとTTY有効がデフォルト、docker execだとTTY無効がデフォルトだということです。
同じ目にあった人がいたので解決は早かったですが、気づかんて。
Why is pg_restore segfaulting in Docker?
https://stackoverflow.com/questions/63934856/why-is-pg-restore-segfaulting-in-docker
リストア時にセグメンテーションフォールトを喰らって気づくという悲劇もありえます。リストアのテスト大事ですね。
タグ: Docker, PostgreSQL