Як налаштувати файл конфігурації офіційного зображення Docker PostgreSQL?


102

Я використовую офіційний образ Dock Postgres, намагаючись налаштувати його конфігурацію. Для цього я використовую команду sedдля зміни, max_connectionsнаприклад:

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

Я спробував два способи застосувати цю конфігурацію. Перший - додавання команд до сценарію та копіювання його в папку init "/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 або повний відтворювач?
користувач2915097

Відповіді:


54

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
Я щойно скопіював сценарій у папку init "/docker-entrypoint-initdb.d/", і він також добре працював цього разу. Це дивно, але здається, що я був настільки зосереджений на встановленні зображення за допомогою Dockerfile, як я звик робити з більшою кількістю зображень, що я щось пропустив під час своїх перших спроб за допомогою сценарію init.
Сакр

"Це по суті означає, що ви не можете копіювати жодні файли на цей шлях у вашому зображенні; зміни будуть відкинуті." Чи можете ви поясніть, чому це так?
isco

@isco шукати обсяги в офіційних документах. В основному томи зберігаються не на зображенні, а на хості, тому дані зберігатимуться на хості, а не на зображенні. Вам потрібно буде запустити контейнер із тим самим обсягом, який додається, щоб зберегти дані.
Адріан Муат

я змінюю /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.

Наприклад, це робить 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 до файлу, а не stdout та використовувати команди докерів-журналів для боротьби з ним? кудо для зшивання у випуску github !
jpic

1
Я не вирішував, чи краще входити в файл або використовувати журнали Docker, jpic.
Маттіас Браун

Ви додали пароль, який ви, мабуть, захочете замаскувати тут
vidstige

3
@vidstige: Я не використовую цей випадковий рядок як пароль, це лише для демонстрації.
Маттіас Браун

1
@Gherman: Ви додали це до свого Dockerfile? Тому що ти не повинен. Моя відповідь використовує docker-compose.yml.
Маттіас Браун

39

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

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

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

Виробнича база даних (PGDATA dir як постійний обсяг)

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

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


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 / папка виконує скрипти в алфавітному порядку. І я хочу застосувати цей скрипт перед іншими.
альфаякс

tnx я забув, що копія перейменувала файл, щоб використати підкреслення
Fernando Castilla Ospina

9

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

В основному нам це потрібно

  • Скопіюйте конфігураційний файл у контейнер докера
  • Визначити параметри запуску постгресів

Приклад файлу 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

Досить низькотехнологічним рішенням цієї проблеми, здається, є оголошення служби (я використовую рій на AWS та файл yaml) з файлами бази даних, встановленими на збережений об'єм (тут AWS EFS як позначається хмарним штором: aws driver специфікація).

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

Приємним побічним ефектом збереження вашої конфігурації є те, що вона також зберігає ваші бази даних (чи це було навпаки) ;-)


2

Моє рішення - для колег, яким потрібно внести зміни в config перед запуском 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;

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

Використовуючи докер-композицію, ви можете змонтувати гучність за допомогою 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саму локацію.
Башдл

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"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.