統合テストと簡単な拡張のためのPostgres上のデータを含むDockerコンテナー

最近、 Docker



Docker-compose



の使用について多くのことが書かれています。たとえば、まだ慣れていない場合は、Habréに関する最近の記事をお勧めします。 これは本当に便利ですが特にansibleと組み合わせて使用​​します。 そして、私はどこでもそれを使用しています。 CI



開発から自動統合テストまで。 彼らはテストでの使用についても書いた 。 とても快適です。 ただし、ローカル開発の場合、「実稼働時のような」データ処理や「実稼働に近いボリュームでの」パフォーマンステストの場合、「実稼働時のような」データベースを含むイメージを手元に置きたいと思います。







したがって、すべての開発者が1つのチームでプロジェクトを開始できるように、プロジェクトの作業を開始する必要があります。次に例を示します。







 ./gradlew dockerRun
      
      





必要なすべての関連コンテナを使用して、アプリケーションがすぐに起動しますか? そして主なことは、そこに画像やデモデータをエクスポートまたはインポートする時間を無駄にすることなく、すぐに作業を開始できるほとんどの開発およびバグ修正ケース、標準ユーザー、ほとんどの作業サービスのデータがすでに含まれていることです!







素晴らしいボーナスとして、数ギガバイトのデータベースと、数秒以内に元の(または他のコミット)状態にロールバックする機能があるのは素晴らしいことではありませんか?







もちろん、データを含むそのようなイメージのDockerfile



作成と、このプロセスの落とし穴のいくつかについて説明します。







ここが焦点です。 私たちのアプリケーションでは、 Postgres



を積極的に使用しているので、ストーリーと例はコンテナに関するものですが、これは例にのみ適用され、プレゼンテーションの本質は他のリレーショナルまたはファッショナブルなNoSQL



データベースに適用されます。







何が欲しい?



最初に、問題をより詳細に定義しましょう。 アプリケーションで作業するすべての人が使用できるデータを含む画像準備しています:









降りる



Dockerfile



説明しませんが、既にこれを理解していることを望みます。 アイデアを得たい人は、記事 、まあ、または公式ドキュメント参照してください







公式のdocker postgresイメージにはすでにいくつかの拡張ポイントがあります。









ただし、私たちの目的では、これだけでは十分ではありません。









おそらくすぐにファイルのプロトタイプを表示します(一部の重要でない部分のみを切り取って小さくします。たとえば、 Deb



や公式リポジトリにはないため、 RPM



からDebian



pg_hint_plan



れるpg_hint_plan



拡張を含めるには多くのスペースが必要です)。







Dockerfile
 FROM postgres:9.6 MAINTAINER Pavel Alexeev # Do NOT use /var/lib/postgresql/data/ because its declared as volume in base image and can't be undeclared but we want persist data in image ENV PGDATA /var/lib/pgsql/data/ ENV pgsql 'psql -U postgres -nxq -v ON_ERROR_STOP=on --dbname somedb' ENV DB_DUMP_URL 'ftp://user:password@ftp.somehost.com/desired_db_backup/somedb_dump-2017-02-21-16_55_01.sql.gz' COPY docker-entrypoint-initdb.d/* /docker-entrypoint-initdb.d/ COPY init.sql/* /init.sql/ # Later in RUN we hack config to include conf.d parts. COPY postgres.conf.d/* /etc/postgres/conf.d/ # Unfortunately Debian /bin/sh is dash shell instead of bash (https://wiki.ubuntu.com/DashAsBinSh) and some handy options like pipefaile is unavailable # Separate RUN to next will be in bash instead of dash. Change /bin/sh symlink as it is hardcoded https://github.com/docker/docker/issues/8100 RUN ln -sb /bin/bash /bin/sh RUN set -euo pipefail \ && echo '1) Install required packages' `# https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#apt-get` \ && apt-get update \ && apt-get install -y \ curl \ postgresql-plperl-9.6 \ && echo '3) Run postgres DB internally for init cluster:' `# Example how to run instance of service: http://stackoverflow.com/questions/25920029/setting-up-mysql-and-importing-dump-within-dockerfile`\ && bash -c '/docker-entrypoint.sh postgres --autovacuum=off &' \ && sleep 10 \ && echo '4.1) Configure postgres: use conf.d directory:' \ && sed -i "s@#include_dir = 'conf.d'@include_dir = '/etc/postgres/conf.d/'@" "$PGDATA/postgresql.conf" \ && echo '4.2) Configure postgres: Do NOT chown and chmod each time on start PGDATA directory (speedup on start especially on Windows):' \ && sed -i 's@chmod 700 "$PGDATA"@#chmod 700 "$PGDATA"@g;s@chown -R postgres "$PGDATA"@#chown -R postgres "$PGDATA"@g' /docker-entrypoint.sh \ && echo '4.3) RERun postgres DB for work in new configuration:'\ && gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop \ && sleep 10 \ && bash -c '/docker-entrypoint.sh postgres --autovacuum=off --max_wal_size=3GB &' \ && sleep 10 \ && echo '5) Populate DB data: Restore DB backup:' \ && time curl "$DB_DUMP_URL" \ | gzip --decompress \ | grep -Pv '^((DROP|CREATE|ALTER) DATABASE|\\connect)' \ | $pgsql \ && echo '6) Execute build-time sql scripts:' \ && for f in /init.sql/*; do echo "Process [$f]"; $pgsql -f "$f"; rm -f "$f"; done \ && echo '7) Update DB to current migrations state:' \ && time java -jar target/db-updater-*.jar -f flyway.url=jdbc:postgresql://localhost:5432/somedb -f flyway.user=postgres -f flyway.password=postgres \ && echo '8) Vacuum full and analyze (no reindex need then):' \ && time vacuumdb -U postgres --full --all --analyze --freeze \ && echo '9) Stop postgres:' \ && gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop \ && sleep 10 \ && echo '10) Cleanup pg_xlog required to do not include it in image!:' `# Command inspired by http://www.hivelogik.com/blog/?p=513` \ && gosu postgres pg_resetxlog -o $( LANG=C pg_controldata $PGDATA | grep -oP '(?<=NextOID:\s{10})\d+' ) -x $( LANG=C pg_controldata $PGDATA | grep -oP '(?<=NextXID:\s{10}0[/:])\d+' ) -f $PGDATA \ && echo '11(pair to 1)) Apt clean:' \ && apt-get autoremove -y \ curl \ && rm -rf /var/lib/apt/lists/*
      
      





ご覧のとおり、ファイルにコメントを直接追加しようとしました。多分それらは完全なものではないかもしれませんが、それでもいくつかの点について詳しく見ていきましょう。







注目に値する



  1. ENV PGDATA /var/lib/pgsql/data/



    をオーバーライドします。 これが重要なポイントです。 なぜなら ビルド中に入力されたデータをイメージ含めたい場合、 ボリュームとして定義された標準の場所に配置しないでください。
  2. DB_DUMP_URL



    変数DB_DUMP_URL



    、後続の編集の便宜上、単に定義されています。 必要に応じて、ビルド中に外部から転送できます。
  3. 次に、ビルドプロセス中にPostgres



    直接起動しますbash -c '/docker-entrypoint.sh postgres --autovacuum=off &'



    いくつかの簡単な設定を実行します。

    • sed



      を使用して、メインの postgres.conf



      include_dir



      sed



      postgres.conf



      include_dir



      。 このような操作を設定で最小限に抑えるためにこれが必要です。そうしないと、メンテナンスが非常に困難になりますが、設定の拡張性に制限はありません。 COPY postgres.conf.d/* /etc/postgres/conf.d/



      ディレクティブCOPY postgres.conf.d/* /etc/postgres/conf.d/



      を使用して、ビルドに固有の構成要素を配置することに注意してください。

      • このメカニズム 、基本的なイメージに含めるための問題としてコミュニティに提案されましたが、リクエストが閉じられている間に、すでに私がやったように質問を提起しましたが(誰かと記事を書く機会に役立つかもしれないことを示唆しています)再発見の希望を失いません。
    • また、メインファイルからchown



      およびchmod



      命令を削除(コメント)します。 データベースが初期化されると、ファイルには既にイメージ内の適切なユーザーと権限がありますが、経験上、WindowsのDockerバージョンでは、何らかの理由でこの操作に数十分かかる非常に長い時間がかかることが判明しました。
    • また、最初にPostgres



      実行する必要があることに注意してください。
      そうしないと、クラスターを初期化するためのディレクトリが空ではないというエラーが開始時に表示されます!
    • 次に、 Postgres



      を再起動して、追加して読み取り用に設定した構成を再読み取りします。 厳密に言えば、この手順はまったく必要ありません。 ただし、デフォルトではshared_buffers = 128MB



      ような非常に控えめなメモリ設定があり、重要なメモリ設定は何時間もドラッグし続けます。
  4. 次のステップでは、すべてが明確になっているはずです-ダンプを復元するだけです。 ただし、その背後にある/init.sql/*



    、イメージの作成中にこのディレクトリからすべてのSQL



    スクリプト/init.sql/*



    適用しSQL



    (標準の拡張スクリプトとは異なります)。 ここで、データの難読化、サンプリング、クリーニング、テストユーザーの追加などを行います。

    • すべてのスクリプトをこのように実行することで、次回ビルド手順に触れることなく、データを使用して何か他のことを行うファイルをこのディレクトリに追加するだけですみます!
  5. イメージを縮小し、さらに効率を上げるために、分析を使用して完全なバキュームを実行します

    • これにより、 auto-vacuumを無効( --autovacuum=off



      )にしてPostgres



      を実行し、インポートを高速化できることに注意してください。
    • また、イメージを縮小する目的で、 pg_resetxlog



      を使用してリセットし、蓄積されたWALを有効にしません。 そして、起動時に--max_wal_size=3GB



      を使用して、ファイルサイズを増やし、再度ローテーションしないようにします。
    • ベストプラクティスのガイドラインに従って、APTキャッシュのクリアが標準です。


完成したイメージは、タグを割り当ててリポジトリにプッシュするだけです。 ほとんどの場合、もちろん、何らかのパブリックデータサンプルで作業していない場合、これはプライベートリポジトリになります。







これにより、誰かがデータを使ったテスト画像の作成を準備するプロセスを少なくとも少し簡単にするのに役立てば非常に嬉しいです。








All Articles