かなり昔にPostgreSQLコンテナをデータごとイメージ化してテストなどで使い回す方法を考えましたが、PostgreSQL公式イメージの Dockerfile を改変して、自分でビルドする必要があり、(最初の1回だけとはいえ)とても手間でした。PostgreSQLのバージョンが古くなるとdocker buildできなくなったり。
よくよく考えてみると、PostgreSQLのデータ保存先である PGDATA
環境変数に VOLUME
指定されたディレクトリ (/var/lib/postgresql/data
) が指定されているからコンテナ外に永続化されてしまうわけで、
...
ENV PGDATA /var/lib/postgresql/data
RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" # this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values)
VOLUME /var/lib/postgresql/data
PGDATA
にコンテナ内の別ディレクトリを指定してやれば一緒にイメージ化されるのでは、ということに気付きました。
解決策(改)
-
PGDATA
をコンテナ内の適当なディレクトリに変更してPostgreSQL公式イメージからDBを起動$ docker run -d --rm -p 5432:5432 --name temp-db \ -e POSTGRES_PASSWORD=postgres \ -e PGDATA=/tmp \ postgres:14.3-alpine
-
DBにデータを投入する
- マイグレーションツールで自動構築するなり、SQLを1つずつ実行して手動構築するなりして、DBを望みの状態にする
-
新しいDockerイメージとしてDBの状態を保存する
$ docker commit temp-db my-awesome-db:1.0 $ docker images my-awesome-db REPOSITORY TAG IMAGE ID CREATED SIZE my-awesome-db 1.0 55f54dadb483 5 seconds ago 257MB
-
イメージ作成用の実行中コンテナを停止する
$ docker stop temp-db
-
作成したDockerイメージから爆速でDBを起動する(必要になるたび)
$ docker run -d --rm -p 5432:5432 --name=awesome-db my-awesome-db:1.0
まとめ
DBのデータ保存先を VOLUME
指定されているディレクトリからあえて変えることで、データごと丸っと Docker イメージ化する方法を紹介しました。
これであの社内プロジェクトの任意の過去バージョンのアプリ&DB起動も爆速のはず!