IT TIP

공식 PostgreSQL Docker 이미지의 구성 파일을 사용자 지정하는 방법은 무엇입니까?

itqueen 2020. 10. 13. 20:01
반응형

공식 PostgreSQL Docker 이미지의 구성 파일을 사용자 지정하는 방법은 무엇입니까?


구성을 사용자 지정하려는 공식 Postgres Docker 이미지를 사용 하고 있습니다. 이를 위해 다음과 같은 명령 sed사용하여 변경 max_connections합니다.

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

이 구성을 적용하기 위해 두 가지 방법을 시도했습니다. 첫 번째는 스크립트에 명령을 추가하고 init 폴더 "/docker-entrypoint-initdb.d"내에 복사하는 것입니다. 두 번째 방법은 "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


postgres:9.4당신이로부터 상속 한 이미지에 볼륨을 선언합니다 /var/lib/postgresql/data. 이것은 본질적으로 이미지의 해당 경로에 파일을 복사 할 수 없음을 의미합니다. 변경 사항이 삭제됩니다.

몇 가지 선택이 있습니다.

  • .NET을 사용하여 런타임에 자체 구성 파일을 볼륨으로 추가 할 수 있습니다 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"
      ...

Docker Compose 사용

도커 작성 작업을 할 때 사용할 수있는 command: postgres -c option=value당신의 docker-compose.yml포스트 그레스를 구성 할 수 있습니다.

예를 들어 다음은 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.ymlPostgres를 구성하는 방법을 보여주는 내 응용 프로그램은 다음과 같습니다 .

# 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

사용자 지정 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 디렉토리는 이후 삭제됨 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에서 (분리 옵션)을 제거하십시오 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;
    

When you run the official entrypoint (A.K.A. when you launch the container), it runs initdb in $PGDATA (/var/lib/postgresql/data by default), and then it stores in that directory these 2 files:

  • postgresql.conf with default manual settings.
  • postgresql.auto.conf with settings overriden automatically with ALTER SYSTEM commands.

The entrypoint also executes any /docker-entrypoint-initdb.d/*.{sh,sql} files.

All this means you can supply a shell/SQL script in that folder that configures the server for the next boot (which will be immediately after the DB initialization, or the next times you boot the container).

Example:

conf.sql file:

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

Dockerfile file:

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

And then you will have to execute conf.sql manually in already-existing databases. Since configuration is stored in the volume, it will survive rebuilds.


Another alternative is to pass -c flag as many times as you wish:

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

This way you don't need to build a new image, and you don't need to care about already-existing or not databases; all will be affected.


You can put your custom postgresql.conf in a temporary file inside the container, and overwrite the default configuration at runtime.

To do that :

  • Copy your custom postgresql.conf inside your container
  • Copy the updateConfig.sh file in /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

At runtime, the container will execute the script inside /docker-entrypoint-initdb.d/ and overwrite the default configuration with yout custom one.


I looked through all answers and there is another option left. You can change your CMD value in docker file (it is not the best one, but still possible way to achieve your goal).

Basically we need to

  • Copy config file in docker container
  • Override postgres start options

Docker file example:

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"]

Though I think using command: postgres -c config_file=/etc/postgresql/postgresql.confin your docker-compose.yml file proposed by Matthias Braun is the best option.


A fairly low-tech solution to this problem seems to be to declare the service (I'm using swarm on AWS and a yaml file) with your database files mounted to a persisted volume (here AWS EFS as denoted by the cloudstor:aws driver specification).

  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. The db comes up as initialized with the image default settings.
  2. You edit the conf settings inside the container, e.g if you want to increase the maximum number of concurrent connections that requires a restart
  3. stop the running container (or scale the service down to zero and then back to one)
  4. the swarm spawns a new container, which this time around picks up your persisted configuration settings and merrily applies them.

A pleasant side-effect of persisting your configuration is that it also persists your databases (or was it the other way around) ;-)


My solution is for colleagues who needs to make changes in config before launching docker-entrypoint-initdb.d

I was needed to change 'shared_preload_libraries' setting so during it's work postgres already has new library preloaded and code in docker-entrypoint-initdb.d can use it.

So I just patched postgresql.conf.sample file in Dockerfile:

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

And with this patch it become possible to add extension in .sql file in docker-entrypoint-initdb.d/:

CREATE EXTENSION pg_cron;

참고URL : https://stackoverflow.com/questions/30848670/how-to-customize-the-configuration-file-of-the-official-postgresql-docker-image

반응형