Как настроить файл конфигурации официального образа Docker PostgreSQL?

103

Я использую официальный образ Docker Postgres, пытаясь настроить его конфигурацию. Для этого я использую команду sedдля изменения, max_connectionsнапример:

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

Я попробовал два метода применить эту конфигурацию. Первый - добавить команды в сценарий и скопировать его в папку инициализации «/docker-entrypoint-initdb.d». Второй метод - запускать их прямо в моем Dockerfile с помощью команды «RUN» (этот метод отлично работал с неофициальным образом Postgresql с другим путем к файлу конфигурации «/ etc / postgres / ...»). В обоих случаях изменения не удаются, потому что файл конфигурации отсутствует (я думаю, что он еще не создан).

Как мне изменить конфигурацию?

Изменить 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просмотреть doc docs.docker.com/reference/commandline/cli/#commit
user2915097
2
Я считаю, что одним из преимуществ докер-парадигмы является автоматизация всего процесса сборки. Как упоминалось в другом образе paintedfox/postgresql, можно изменить конфигурацию непосредственно в файле Dockerfile. Я думаю, что это должно быть возможно и с официальным изображением.
Сакр
метод sed должен работать, вы можете опубликовать свой Dcokerfile или полный репродуктор?
user2915097

Ответы:

55

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. Я переместил их в сценарий и вызвал его из точки входа, и теперь он работает нормально. Спасибо за ответ.
Сакр,
5
Я только что скопировал скрипт в папку инициализации "/docker-entrypoint-initdb.d/", и на этот раз он также работал нормально. Это странно, но мне кажется, что я был настолько сосредоточен на установке образа с помощью Dockerfile, как я привык делать с большинством образов, что я что-то пропустил при первых попытках использования сценария инициализации.
Сакр,
«По сути, это означает, что вы не можете копировать файлы по этому пути в вашем изображении; изменения будут отменены». Не могли бы вы объяснить, почему это так?
isco,
@isco поищите тома в официальных документах. Обычно тома хранятся не в образе, а на хосте, поэтому данные будут сохраняться на хосте, а не в образе. Вам нужно будет запустить контейнер с тем же прикрепленным томом для хранения данных.
Адриан Муат,
Я меняю /var/lib/postgres/data/pg_hba.conf, чтобы принять только соединение, это хост все 192.168.0.0/0 md5 и комментировать хост все все все md5 (по умолчанию). Но не меняйте эффект
Лукас Ресенде
83

С Docker Compose

При работе с Докер Compose, вы можете использовать command: postgres -c option=valueв вашем docker-compose.ymlнастроить Postgres.

Например, это делает журнал Postgres в файл:

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

Адаптировав ответ Войтех Витек , вы можете использовать

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 каталог журнала на хосте должен иметь необходимые разрешения. В противном случае вы получите слегка вводящую в заблуждение ошибку

FATAL: не удалось открыть файл журнала "/logs/postgresql-2017-02-04_115222.log": в доступе отказано

Я говорю, что вводит в заблуждение, поскольку сообщение об ошибке предполагает, что каталог в контейнере имеет неправильное разрешение, тогда как в действительности каталог на хосте не разрешает запись.

Чтобы исправить это, я установил правильные разрешения на хосте, используя

chgroup ./logs docker && chmod 770 ./logs
Маттиас Браун
источник
Вы бы порекомендовали записывать журнал postgres в файл, а не стандартный вывод, и использовать для этого команды docker logs? Престижность за сшивание в выпуске на github !
jpic 05
1
Я не решил, предпочтительнее ли ведение журнала в файл или использование журналов Docker, jpic.
Маттиас Браун
вы добавили пароль, который вы, вероятно, захотите здесь замаскировать
vidstige
3
@vidstige: я не использую эту случайную строку в качестве пароля, это только для демонстрации.
Маттиас Браун
1
@Gherman: Вы добавили это в свой Dockerfile? Потому что не стоит. Мой ответ использует docker-compose.yml.
Маттиас Браун
40

Внедрить пользовательский postgresql.conf в контейнер Postgres Docker

postgresql.confФайл по умолчанию находится в PGDATAdir ( /var/lib/postgresql/data), что усложняет задачу, особенно при первом запуске контейнера postgres, поскольку docker-entrypoint.shоболочка вызывает initdbэтап PGDATAинициализации dir.

Чтобы последовательно настраивать конфигурацию PostgreSQL в Docker, я предлагаю использовать config_fileопцию postgres вместе с такими томами Docker:

Производственная база данных (каталог 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. Подключитесь к серверу postgres с клиентом psql и запросите конфигурацию:

    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

При запуске официального EntryPoint (AKA при запуске контейнера), она работает initdbв $PGDATA( /var/lib/postgresql/dataпо умолчанию), а затем он сохраняет в этой директории эти 2 файла:

  • postgresql.conf с ручными настройками по умолчанию.
  • postgresql.auto.confс настройками, автоматически заменяемыми ALTER SYSTEMкомандами.

Точка входа также выполняет любые /docker-entrypoint-initdb.d/*.{sh,sql}файлы.

Все это означает, что вы можете предоставить сценарий оболочки / 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

Таким образом, вам не нужно создавать новый образ, и вам не нужно заботиться об уже существующих или несуществующих базах данных; все будет затронуто.

Yajo
источник
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/и перезапишет конфигурацию по умолчанию вашей собственной.

Alphayax
источник
почему "_" во второй команде копирования? это не должно быть: /docker-entrypoint-initdb.d/updateConfig.sh?
Фернандо Кастилья Оспина
3
Это потому, что папка docker-entrypoint-initdb.d / выполняет сценарии в алфавитном порядке. И я хочу применить этот сценарий раньше других.
alphayax
tnx я забыл, что копия переименовала файл, чтобы использовать подчеркивание
Фернандо Кастилья Оспина
9

Я просмотрел все ответы, остался еще один вариант. Вы можете изменить значение CMD в файле докеров (это не лучший, но все же возможный способ достижения вашей цели).

В основном нам нужно

  • Скопируйте файл конфигурации в контейнер докеров
  • Переопределить параметры запуска 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"]

Хотя я думаю, что использование command: postgres -c config_file=/etc/postgresql/postgresql.confв вашем docker-compose.ymlфайле, предложенное Матиасом Брауном, - лучший вариант.

Доктор Ботвинг
источник
2

Довольно низкотехнологичное решение этой проблемы, по-видимому, состоит в объявлении службы (я использую swarm на AWS и файл yaml) с файлами вашей базы данных, подключенными к постоянному тому (здесь AWS EFS, как обозначено драйвером cloudstor: aws Технические характеристики).

  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. остановить работающий контейнер (или масштабировать службу до нуля, а затем обратно до единицы)
  4. рой порождает новый контейнер, который на этот раз забирает ваши постоянные настройки конфигурации и весело применяет их.

Приятным побочным эффектом сохранения вашей конфигурации является то, что она также сохраняет ваши базы данных (или было наоборот) ;-)

Эоан
источник
2

Мое решение для коллег, которым необходимо внести изменения в конфигурацию перед запуском docker-entrypoint-initdb.d

Мне нужно было изменить настройку shared_preload_libraries, чтобы во время работы у postgres уже была предварительно загружена новая библиотека, и код в docker-entrypoint-initdb.d мог ее использовать.

Итак, я просто пропатчил файл postgresql.conf.sample в 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

И с этим патчем стало возможно добавить расширение в файл .sql в docker-entrypoint-initdb.d /:

CREATE EXTENSION pg_cron;
40 мин
источник
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, а общий буфер со 128 МБ до 3 ГБ. С помощью команды 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"
Себастьян
источник