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


102

구성을 사용자 지정하려는 공식 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


1
한 가지 방법은 공식 이미지를 사용하여 시작하고 내부에 연결 docker exec -it container_id bash한 다음 수정을 수행 한 다음 docker commit container_id myuser/myimage_myPostegresql:myversion문서 docs.docker.com/reference/commandline/cli/#commit
user2915097

2
도커 패러다임의 장점 중 하나는 전체 빌드 프로세스를 자동화하는 것입니다. 다른 이미지에서 언급했듯이 paintedfox/postgresqlDockerfile 내에서 직접 구성을 변경할 수 있습니다. 공식 이미지로도 가능해야한다고 생각합니다.
Sakr

sed 방법이 작동해야합니다. Dcokerfile 또는 완전한 재생기를 게시 할 수 있습니까?
user2915097

답변:


54

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

3
즉, 변경 사항이 Dockerfile 내에 있어서는 안됩니다. 나는 그것들을 스크립트로 옮겼고 진입 점에서 호출했고 지금은 잘 작동했습니다. 답변 감사합니다.
Sakr

5
방금 스크립트를 init 폴더 "/docker-entrypoint-initdb.d/"에 복사했으며 이번에도 제대로 작동했습니다. 이상 하긴하지만 대부분의 이미지에 익숙한 Dockerfile로 이미지를 설정하는 데 너무 집중해서 init 스크립트를 사용한 첫 시도에서 뭔가 놓친 것 같습니다.
Sakr

"이것은 본질적으로 이미지의 해당 경로에 파일을 복사 할 수 없음을 의미합니다. 변경 사항이 삭제됩니다." 그 이유를 설명해 주시겠습니까?
isco

@isco는 공식 문서에서 볼륨을 찾습니다. 기본적으로 볼륨은 이미지가 아니라 호스트에 저장되므로 데이터는 이미지가 아닌 호스트에 저장됩니다. 데이터를 유지하려면 동일한 볼륨이 연결된 상태에서 컨테이너를 시작해야합니다.
Adrian Mouat

연결 만 허용하기 위해 /var/lib/postgres/data/pg_hba.conf에서 변경하면 호스트는 모두 192.168.0.0/0 md5이고 호스트는 모두 모두 md5 (기본값)입니다. 하지만 효과를 바꾸지
마십시오

83

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

stdout 대신 파일에 postgres 로그를 작성하고이를 처리하기 위해 docker logs 명령을 사용하는 것이 좋습니다. github 문제 에서 교차 연결에 대한 찬사 !
jpic

1
파일에 로깅하거나 Docker 로그를 사용하는 것이 바람직한 지 여부는 결정되지 않았습니다.
Matthias Braun

여기에서 마스킹하고 싶은 암호를 추가했습니다
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 디렉토리는 이후 삭제됨 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;

30

공식 진입 점 (컨테이너를 시작할 때 일명)을 실행하면 ( 기본적으로) initdb에서 실행 되고 다음 2 개의 파일이 해당 디렉터리에 저장됩니다.$PGDATA/var/lib/postgresql/data

  • postgresql.conf 기본 수동 설정으로.
  • postgresql.auto.confALTER SYSTEM명령 으로 자동으로 재정의되는 설정 .

진입 점은 또한 모든 /docker-entrypoint-initdb.d/*.{sh,sql}파일을 실행 합니다.

이 모든 것은 다음 부팅 (DB 초기화 직후 또는 다음에 컨테이너를 부팅 할 때)을 위해 서버를 구성하는 해당 폴더에 셸 / SQL 스크립트를 제공 할 수 있음을 의미합니다.

예:

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이미 존재하는 데이터베이스에서 수동으로 실행 해야합니다. 구성은 볼륨에 저장되므로 재 구축 후에도 유지됩니다.


또 다른 대안은 -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/하고 기본 구성을 사용자 지정 구성으로 덮어 씁니다.


두 번째 복사 명령에 "_"가있는 이유는 무엇입니까? 해서는 안됩니다 : /docker-entrypoint-initdb.d/updateConfig.sh?
Fernando Castilla Ospina

3
docker-entrypoint-initdb.d / 폴더가 알파벳순으로 스크립트를 실행하기 때문입니다. 이 스크립트를 다른 스크립트보다 먼저 적용하고 싶습니다.
alphayax

TNX는 내가 복사가 밑줄 사용할 파일 이름을 바꿀 것을 잊었다
페르난도 카 스틸라 Ospina

9

나는 모든 답변을 살펴 보았고 다른 옵션이 남아 있습니다. 도커 파일에서 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. db는 이미지 기본 설정으로 초기화 된 상태로 나타납니다.
  2. 예를 들어 재시작이 필요한 최대 동시 연결 수를 늘리려는 경우 컨테이너 내부의 구성 설정을 편집합니다.
  3. 실행중인 컨테이너 중지 (또는 서비스를 0으로 축소 한 다음 다시 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 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.