公式のPostgreSQL Dockerイメージの構成ファイルをカスタマイズする方法は?


100

設定をカスタマイズするために、公式のPostgres Dockerイメージを使用しています。この目的のために、たとえば次のsedように変更するコマンドを使用max_connectionsします。

sed -i -e"s/^max_connections = 100.*$/max_connections = 1000/" /var/lib/postgresql/data/postgresql.conf

この構成を適用するために2つの方法を試しました。1つ目は、コマンドをスクリプトに追加し、それをinitフォルダー「/docker-entrypoint-initdb.d」内にコピーすることです。2番目の方法は、「RUN」コマンドを使用してDockerfile内で直接実行する方法です(この方法は、構成ファイル「/ etc / postgres / ...」へのパスが異なる非公式のPostgresqlイメージで問題なく機能しました)。どちらの場合も、構成ファイルがないため、変更は失敗します(まだ作成されていないと思います)。

構成を変更するにはどうすればよいですか?

編集1:

以下は、イメージの作成に使用されるDockerfileです。

# Database (http://www.cs3c.ma/)

FROM postgres:9.4
MAINTAINER Sabbane <contact@cs3c.ma>

ENV TERM=xterm

RUN apt-get update
RUN apt-get install -y nano

ADD scripts /scripts
# ADD scripts/setup-my-schema.sh /docker-entrypoint-initdb.d/

# Allow connections from anywhere.
RUN sed -i -e"s/^#listen_addresses =.*$/listen_addresses = '*'/" /var/lib/postgresql/data/postgresql.conf
RUN echo "host    all    all    0.0.0.0/0    md5" >> /var/lib/postgresql/data/pg_hba.conf

# Configure logs
RUN sed -i -e"s/^#logging_collector = off.*$/logging_collector = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_directory = 'pg_log'.*$/log_directory = '\/var\/log\/postgresql'/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_filename = 'postgresql-\%Y-\%m-\%d_\%H\%M\%S.log'.*$/log_filename = 'postgresql_\%a.log'/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_file_mode = 0600.*$/log_file_mode = 0644/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_truncate_on_rotation = off.*$/log_truncate_on_rotation = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_rotation_age = 1d.*$/log_rotation_age = 1d/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_min_duration_statement = -1.*$/log_min_duration_statement = 0/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_checkpoints = off.*$/log_checkpoints = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_connections = off.*$/log_connections = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_disconnections = off.*$/log_disconnections = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^log_line_prefix = '\%t \[\%p-\%l\] \%q\%u@\%d '.*$/log_line_prefix = '\%t \[\%p\]: \[\%l-1\] user=\%u,db=\%d'/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_lock_waits = off.*$/log_lock_waits = on/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#log_temp_files = -1.*$/log_temp_files = 0/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#statement_timeout = 0.*$/statement_timeout = 1800000        # in milliseconds, 0 is disabled (current 30min)/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^lc_messages = 'en_US.UTF-8'.*$/lc_messages = 'C'/" /var/lib/postgresql/data/postgresql.conf

# Performance Tuning
RUN sed -i -e"s/^max_connections = 100.*$/max_connections = 1000/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^shared_buffers =.*$/shared_buffers = 16GB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#effective_cache_size = 128MB.*$/effective_cache_size = 48GB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#work_mem = 1MB.*$/work_mem = 16MB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#maintenance_work_mem = 16MB.*$/maintenance_work_mem = 2GB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#checkpoint_segments = .*$/checkpoint_segments = 32/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#checkpoint_completion_target = 0.5.*$/checkpoint_completion_target = 0.7/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#wal_buffers =.*$/wal_buffers = 16MB/" /var/lib/postgresql/data/postgresql.conf
RUN sed -i -e"s/^#default_statistics_target = 100.*$/default_statistics_target = 100/" /var/lib/postgresql/data/postgresql.conf


VOLUME ["/var/lib/postgresql/data", "/var/log/postgresql"]

CMD ["postgres"]

このDockerfileを使用すると、ビルドプロセスでエラーが表示されます。 sed: can't read /var/lib/postgresql/data/postgresql.conf: No such file or directory


1
1つの方法は、との接続内部、それを起動し、公式画像を使用することでdocker exec -it container_id bash、その後、その後、あなたの変更を行うdocker commit container_id myuser/myimage_myPostegresql:myversionドキュメントの参照docs.docker.com/reference/commandline/cli/#commit
user2915097

2
dockerパラダイムの利点の1つは、ビルドプロセス全体を自動化することです。別のイメージで説明しpaintedfox/postgresqlたように、Dockerfile内で直接構成を変更することができます。公式画像でも可能だと思います。
Sakr

sedメソッドが機能するはずですが、Dcokerfileまたは完全な再生プログラムを投稿できますか?
user2915097 2015年

回答:


53

postgres:9.4あなたがから継承されてきた画像は、ボリュームを宣言します/var/lib/postgresql/data。これは基本的に、イメージ内のそのパスにファイルをコピーできないことを意味します。変更は破棄されます。

いくつかの選択肢があります。

  • を使用して、実行時に独自の構成ファイルをボリュームとして追加できますdocker run -v postgresql.conf:/var/lib/postgresql/data/postgresql.conf ...。ただし、それが既存のボリュームとどのように相互作用するかは正確にはわかりません。

  • コンテナの起動時にファイルをコピーできます。これを行うには、ボリュームの下ではない場所でビルドにファイルをコピーし、エントリポイントまたはcmdからスクリプトを呼び出して、ファイルを正しい場所にコピーし、postgresを開始します。

  • Postgres公式イメージの背後にあるプロジェクトのクローンを作成し、Dockerfileを編集して、VOLUMEが宣言される前に独自の構成ファイルを追加します(VOLUME命令が実行時に自動的にコピーされる前に追加されたもの)。

  • docker-composeファイルのコマンドオプションですべての構成変更を渡す

お気に入り:

services:
  postgres:
    ...  
    command:
      - "postgres"
      - "-c"
      - "max_connections=1000"
      - "-c"
      - "shared_buffers=3GB"
      - "-c"
      ...

3
変更はDockerfile内にあるべきではありません。私はそれらをスクリプトに移動し、エントリポイントから呼び出しましたが、現在は正常に機能しています。答えてくれてありがとう。
Sakr

5
スクリプトをinitフォルダー「/docker-entrypoint-initdb.d/」内にコピーしたところ、今回も問題なく動作しました。それは奇妙ですが、私はDockerfileでの画像の設定に非常に集中していたため、ほとんどの画像で慣れているように、initスクリプトを初めて使用するときに何かを見落としました。
Sakr

「これは基本的に、イメージ内のそのパスにファイルをコピーできないことを意味します。変更は破棄されます。」なぜそうなのか説明していただけますか?
isco

@iscoは公式ドキュメントでボリュームを調べます。基本的にボリュームはイメージではなくホストに保存されるため、データはイメージではなくホストに保存されます。データを保持するには、同じボリュームが接続された状態でコンテナーを起動する必要があります。
エイドリアンMouat

/var/lib/postgres/data/pg_hba.confを変更して、accept only接続はhost all all 192.168.0.0/0 md5であり、comment host all all all md5(デフォルト)です。しかし、効果を変更しないでください
ルーカスは

83

Docker Composeを使用

Docker Composeを使用する場合command: postgres -c option=value、でを使用してdocker-compose.ymlPostgresを構成できます。

たとえば、これはPostgresのログをファイルに作成します。

command: postgres -c logging_collector=on -c log_destination=stderr -c log_directory=/logs

Vojtech Vitekの答えを適応させて、あなたは使うことができます

command: postgres -c config_file=/etc/postgresql.conf

Postgresが使用する設定ファイルを変更します。カスタム構成ファイルをボリュームにマウントします。

volumes:
   - ./customPostgresql.conf:/etc/postgresql.conf

これdocker-compose.ymlが私のアプリケーションので、Postgresの構成方法を示しています。

# Start the app using docker-compose pull && docker-compose up to make sure you have the latest image
version: '2.1'
services:
  myApp:
    image: registry.gitlab.com/bullbytes/myApp:latest
    networks:
      - myApp-network
  db:
     image: postgres:9.6.1
     # Make Postgres log to a file.
     # More on logging with Postgres: https://www.postgresql.org/docs/current/static/runtime-config-logging.html
     command: postgres -c logging_collector=on -c log_destination=stderr -c log_directory=/logs
     environment:
       # Provide the password via an environment variable. If the variable is unset or empty, use a default password
       - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-4WXUms893U6j4GE&Hvk3S*hqcqebFgo!vZi}
     # If on a non-Linux OS, make sure you share the drive used here. Go to Docker's settings -> Shared Drives
     volumes:
       # Persist the data between container invocations
       - postgresVolume:/var/lib/postgresql/data
       - ./logs:/logs
     networks:
       myApp-network:
         # Our application can communicate with the database using this hostname
         aliases:
           - postgresForMyApp
networks:
  myApp-network:
    driver: bridge
# Creates a named volume to persist our data. When on a non-Linux OS, the volume's data will be in the Docker VM
# (e.g., MobyLinuxVM) in /var/lib/docker/volumes/
volumes:
  postgresVolume:

ログディレクトリへの書き込み権限

Linuxでは、ホストのログディレクトリに適切な権限が必要であることに注意してください。そうしないと、少し誤解を招くエラーが発生します

致命的:ログファイル "/logs/postgresql-2017-02-04_115222.log"を開けませんでした:権限が拒否されました

エラーメッセージは、実際にはホスト上のディレクトリ書き込みを許可していないのに、コンテナー内のディレクトリ誤ったアクセス許可を持っていることを示唆しているため、誤解を招きます。

これを修正するには、次を使用してホストに正しい権限を設定します

chgroup ./logs docker && chmod 770 ./logs

stdoutではなくpostgresログをファイルに作成し、docker logsコマンドを使用してそれを処理することをお勧めしますか?GitHubの問題におけるクロスリンクの称賛!
jpic

1
ファイルにログを記録するのか、Dockerログを使用するのが望ましいのか、私はまだ決めていません、jpic。
Matthias Braun 2017年

あなたはおそらくここで隠したいと思うパスワードを追加しました
vidstige

3
@vidstige:このランダムな文字列はパスワードとして使用しません。これはデモ用です。
Matthias Braun

1
@Gherman:これをDockerfileに追加しましたか?すべきではないからです。私の答えはを使用していdocker-compose.ymlます。
Matthias Braun

39

カスタムpostgresql.confをpostgres Dockerコンテナに挿入する

デフォルトのpostgresql.confファイルはPGDATAdir(/var/lib/postgresql/data)内にあります。これは、docker-entrypoint.shラッパーがdir初期化のinitdbステップを呼び出すため、初めてpostgresコンテナーを実行するときに特に複雑になりPGDATAます。

DockerのPostgreSQL構成を一貫してカスタマイズするには、次のconfig_fileようにDockerボリュームと共にpostgresオプションを使用することをお勧めします。

本番データベース(永続ボリュームとしてのPGDATAディレクトリ)

docker run -d \
-v $CUSTOM_CONFIG:/etc/postgresql.conf \
-v $CUSTOM_DATADIR:/var/lib/postgresql/data \
-e POSTGRES_USER=postgres \
-p 5432:5432 \
--name postgres \
postgres:9.6 postgres -c config_file=/etc/postgresql.conf

データベースのテスト(PGDATA dirは後に破棄されますdocker rm

docker run -d \
-v $CUSTOM_CONFIG:/etc/postgresql.conf \
-e POSTGRES_USER=postgres \
--name postgres \
postgres:9.6 postgres -c config_file=/etc/postgresql.conf

デバッグ中

  1. コマンド-dから(detachオプション)を削除してdocker run、サーバーログを直接確認します。
  2. psqlクライアントでpostgresサーバーに接続し、構成をクエリします。

    docker run -it --rm --link postgres:postgres postgres:9.6 sh -c 'exec psql -h $POSTGRES_PORT_5432_TCP_ADDR -p $POSTGRES_PORT_5432_TCP_PORT -U postgres'
    
    psql (9.6.0)
    Type "help" for help.
    
    postgres=# SHOW all;
    

30

公式のエントリポイント(コンテナーを起動したときの別名)を実行するとinitdb$PGDATA/var/lib/postgresql/dataデフォルトで)実行され、そのディレクトリに次の2つのファイルが格納されます。

  • postgresql.conf デフォルトの手動設定。
  • postgresql.auto.confALTER SYSTEMコマンドで設定が自動的に上書きされます。

エントリポイントは、すべての/docker-entrypoint-initdb.d/*.{sh,sql}ファイルも実行します。

つまり、次の起動用にサーバーを構成するシェル/ SQLスクリプトをそのフォルダーに提供できます(DBの初期化直後、または次回コンテナーを起動するとき)。

例:

conf.sql ファイル:

ALTER SYSTEM SET max_connections = 6;
ALTER SYSTEM RESET shared_buffers;

Dockerfile ファイル:

FROM posgres:9.6-alpine
COPY *.sql /docker-entrypoint-initdb.d/
RUN chmod a+r /docker-entrypoint-initdb.d/*

そして、conf.sql既存のデータベースで手動で実行する必要があります。構成はボリュームに保存されるため、再構築後も存続します。


もう1つの方法は、-cフラグを必要な回数だけ渡すことです。

docker container run -d postgres -c max_connections=6 -c log_lock_waits=on

この方法では、新しいイメージを構築する必要はなく、既存のデータベースやデータベースではないことを気にする必要もありません。すべてが影響を受けます。


2
最後の-cを渡すのが私のお気に入りです。これは非常にクリーンでシンプルなので、さまざまな環境で生成できます。
epic_fil

10

カスタムpostgresql.confをコンテナ内の一時ファイルに入れて、実行時にデフォルト設定を上書きできます。

それを行うには:

  • postgresql.confコンテナ内にカスタムをコピーする
  • updateConfig.shファイルをコピーします/docker-entrypoint-initdb.d/

Dockerfile

FROM postgres:9.6

COPY postgresql.conf      /tmp/postgresql.conf
COPY updateConfig.sh      /docker-entrypoint-initdb.d/_updateConfig.sh

updateConfig.sh

#!/usr/bin/env bash

cat /tmp/postgresql.conf > /var/lib/postgresql/data/postgresql.conf

実行時に、コンテナは内部/docker-entrypoint-initdb.d/でスクリプトを実行し、デフォルトの構成をカスタム構成で上書きします。


2番目のコピーコマンドで「_」を使用する理由 すべきではない:/docker-entrypoint-initdb.d/updateConfig.sh
フェルナンドカスティーリャオスピナ2017

3
これは、docker-entrypoint-initdb.d /フォルダーがスクリプトをアルファベット順に実行するためです。そして、このスクリプトを他のスクリプトより先に適用したいと思います。
alphayax 2017

tnxコピーがアンダースコアを使用するようにファイルの名前を変更したことを忘れていました
Fernando Castilla Ospina '21

9

すべての回答を確認しましたが、別のオプションが残っています。dockerファイルでCMD値を変更できます(これは最良のものではありませんが、目標を達成するための可能な方法です)。

基本的には

  • Dockerコンテナーに構成ファイルをコピーする
  • postgres起動オプションを上書きする

Dockerファイルの例:

FROM postgres:9.6
USER postgres

# Copy postgres config file into container
COPY postgresql.conf /etc/postgresql

# Override default postgres config file
CMD ["postgres", "-c", "config_file=/etc/postgresql/postgresql.conf"]

Matthias Braunによって提案されたファイルでの使用command: postgres -c config_file=/etc/postgresql/postgresql.confが最良のオプションだと思いますが。docker-compose.yml


2

この問題に対するかなりローテクな解決策は、永続化されたボリューム(ここでは、cloudstor:awsドライバーで示されるAWS EFS)にマウントされたデータベースファイルでサービスを宣言することです(私はAWSでswarmとyamlファイルを使用しています)。仕様)。

  version: '3.3'
  services:
    database:
      image: postgres:latest
      volumes:
        - postgresql:/var/lib/postgresql
        - postgresql_data:/var/lib/postgresql/data
    volumes:
       postgresql:
         driver: "cloudstor:aws" 
       postgresql_data:
         driver: "cloudstor:aws"
  1. データベースは、イメージのデフォルト設定で初期化された状態で起動します。
  2. コンテナー内のconf設定を編集します(再起動が必要な同時接続の最大数を増やしたい場合など)。
  3. 実行中のコンテナを停止します(またはサービスをゼロにスケールダウンしてから1に戻します)。
  4. スウォームは新しいコンテナを生成します。このコンテナは、今度は永続化された構成設定を取得し、それらを楽しく適用します。

構成を永続化することの快適な副作用は、データベースも永続化することです(またはその逆です);-)


2

私の解決策は、docker-entrypoint-initdb.dを起動する前に構成を変更する必要がある同僚向けです。

'shared_preload_libraries'設定を変更する必要があったので、作業中にpostgresには新しいライブラリがプリロードされており、docker-entrypoint-initdb.dのコードでそれを使用できます。

Dockerfileのpostgresql.conf.sampleファイルにパッチを適用しました。

RUN echo "shared_preload_libraries='citus,pg_cron'" >> /usr/share/postgresql/postgresql.conf.sample
RUN echo "cron.database_name='newbie'" >> /usr/share/postgresql/postgresql.conf.sample

そして、このパッチにより、docker-entrypoint-initdb.d /の.sqlファイルに拡張子を追加することが可能になります。

CREATE EXTENSION pg_cron;

1

これは私にとってはうまくいきます:

FROM postgres:9.6
USER postgres

# Copy postgres config file into container
COPY postgresql.conf /etc/postgresql

# Override default postgres config file
CMD ["postgres", "-c", "config_file=/etc/postgresql/postgresql.conf"]

なぜこれは賛成票を受け取っていないのですか?それはここで非常に正直な命題です...ありがとう。
Paflow

0

docker composeを使用すると、ボリュームをマウントできますpostgresql.auto.conf。例:

version: '2'

services:
  db:
    image: postgres:10.9-alpine
    volumes:
      - postgres:/var/lib/postgresql/data:z
      - ./docker/postgres/postgresql.auto.conf:/var/lib/postgresql/data/postgresql.auto.conf
    ports:
      - 5432:5432

postgresql.auto.confは上書きされるため、編集しないでください。postgresql.conf同じ場所で使用してください。
Baschdl

0

また、公式イメージ(FROM postgres)を使用しており、次のコマンドを実行して構成を変更できました。

最初に、PostgreSQL設定ファイルを探します。これは、実行中のデータベースでこのコマンドを実行することで実行できます。

SHOW config_file;

私の場合それは戻ります/data/postgres/postgresql.conf

次のステップは、実行中のPostgreSQL Dockerコンテナーのハッシュを見つけることです。

docker ps -a

これにより、実行中のすべてのコンテナのリストが返されます。私の場合はこんな感じです。

...
0ba35e5427d9    postgres    "docker-entrypoint.s…" ....
...

次のコマンドを実行して、コンテナー内のbashに切り替える必要があります。

docker exec -it 0ba35e5427d9 /bin/bash

コンテナー内で、構成が正しいパスにあるかどうかを確認して表示します。

cat /data/postgres/postgresql.conf

最大接続数を100から1000に、共有バッファを128MBから3GBに変更したいと思いました。sedコマンドを使用して、検索を実行し、構成内の対応する変数に置き換えることができます。

sed -i -e"s/^max_connections = 100.*$/max_connections = 1000/" /data/postgres/postgresql.conf
sed -i -e"s/^shared_buffers = 128MB.*$/shared_buffers = 3GB/" /data/postgres/postgresql.conf

最後に、コンテナ内でデータベースを再起動する必要があります。使用しているPostGresのバージョンを確認します。

cd /usr/lib/postgresql/
ls 

私の場合、その12 ため、正しいバージョンを使用して次のコマンドを実行することで、データベースを再起動できます。

su - postgres -c "PGDATA=$PGDATA /usr/lib/postgresql/12/bin/pg_ctl -w restart"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.