web-dev-qa-db-fra.com

Comment personnaliser le fichier de configuration de l'image officielle de PostgreSQL Docker?

J'utilise le image officielle de Postgres Docker pour personnaliser sa configuration. Pour cela, j'utilise la commande sed pour changer max_connections par exemple:

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

J'ai essayé deux méthodes pour appliquer cette configuration. La première consiste à ajouter les commandes à un script et à le copier dans le dossier init "/docker-entrypoint-initdb.d". La deuxième méthode consiste à les exécuter directement dans mon fichier Dockerfile avec la commande "RUN" (cette méthode a bien fonctionné avec une image non officielle Postgresql avec un chemin différent du fichier de configuration "/ etc/postgres/..."). Dans les deux cas, les modifications échouent car le fichier de configuration est manquant (je pense qu'il n'a pas encore été créé).

Comment devrais-je changer la configuration?

Modifier 1:

Voici le fichier Docker utilisé pour créer l'image:

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

FROM postgres:9.4
MAINTAINER Sabbane <[email protected]>

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

Avec ce fichier Docker, le processus de construction affiche l’erreur suivante: sed: can't read /var/lib/postgresql/data/postgresql.conf: No such file or directory

70
Sakr

Le postgres:9.4 l'image dont vous avez hérité déclare un volume sur /var/lib/postgresql/data. Cela signifie essentiellement que vous ne pouvez copier aucun fichier dans ce chemin dans votre image. les modifications seront ignorées.

Vous avez quelques choix:

  • Vous pouvez simplement ajouter vos propres fichiers de configuration sous forme de volume au moment de l'exécution avec docker run -v postgresql.conf:/var/lib/postgresql/data/postgresql.conf .... Cependant, je ne sais pas exactement comment cela va interagir avec le volume existant.

  • Vous pouvez copier le fichier lorsque le conteneur est démarré. Pour ce faire, copiez votre fichier dans la construction à un emplacement qui ne se trouve pas sous le volume, puis appelez un script à partir du point d'entrée ou de la commande qui lui permettra de copier le fichier dans l'emplacement correct et de démarrer postgres.

  • Clonez le projet derrière l'image officielle de Postgres et modifiez le fichier Docker pour y ajouter votre propre fichier de configuration avant la déclaration du VOLUME (tout élément ajouté avant que l'instruction VOLUME soit automatiquement copiée au moment de l'exécution).

  • Passer tous les changements de configuration dans l'option de commande dans le fichier docker-compose

comme:

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

Avec Docker Compose

Lorsque vous travaillez avec Docker Compose, vous pouvez utiliser command: postgres -c option=value dans votre docker-compose.yml pour configurer Postgres.

Par exemple, cela permet à Postgres de se connecter à un fichier:

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

S'adapter réponse de Vojtech Vitek , vous pouvez utiliser

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

pour changer le fichier de configuration que Postgres utilisera. Vous monteriez votre fichier de configuration personnalisé avec un volume:

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

Voici le docker-compose.yml de mon application, montrant comment configurer 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:

Autorisation d'écrire dans le répertoire du journal

Notez que sous Linux, le répertoire des journaux de l'hôte doit disposer des autorisations appropriées. Sinon, vous obtiendrez l'erreur légèrement trompeuse

FATAL: impossible d'ouvrir le fichier journal "/logs/postgresql-2017-02-04_115222.log": autorisation refusée

Je dis trompeur, car le message d'erreur suggère que le répertoire du conteneur possède une mauvaise autorisation, alors qu'en réalité le répertoire sur l'hôte n'autorise pas l'écriture.

Pour résoudre ce problème, je définis les autorisations appropriées sur l'hôte à l'aide de

chgroup ./logs docker && chmod 770 ./logs
67
Matthias Braun

Injectez le fichier postgresql.conf personnalisé dans le conteneur Docker postgres

Le fichier par défaut postgresql.conf Réside dans le PGDATA dir (/var/lib/postgresql/data), Ce qui complique les choses, en particulier lors de l'exécution du conteneur postgres pour la première fois, car docker-entrypoint.sh Le wrapper appelle l'étape initdb pour l'initialisation de PGDATA dir.

Pour personnaliser de manière cohérente la configuration PostgreSQL dans Docker, je suggère d'utiliser l'option postgres config_file Avec les volumes Docker comme ceci:

Base de données de production (répertoire PGDATA en tant que volume persistant)

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

Base de données de test (le répertoire PGDATA sera supprimé après 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

Débogage

  1. Supprimez la commande -d (Option de détachement) de docker run Pour afficher directement les journaux du serveur.
  2. Connectez-vous au serveur postgres avec le client psql et interrogez la configuration:

    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;
    
36
Vojtech Vitek

Lorsque vous exécutez le point d'entrée officiel (A.K.A. lorsque vous lancez le conteneur), il exécute initdb dans $PGDATA (/var/lib/postgresql/data par défaut), puis il stocke dans ce répertoire ces 2 fichiers:

  • postgresql.conf avec les réglages manuels par défaut.
  • postgresql.auto.conf avec des paramètres remplacés automatiquement par ALTER SYSTEM commandes.

Le point d’entrée exécute également toute /docker-entrypoint-initdb.d/*.{sh,sql} des dossiers.

Tout cela signifie que vous pouvez fournir un script Shell/SQL dans ce dossier qui configure le serveur pour le prochain démarrage (qui aura lieu immédiatement après l'initialisation de la base de données ou lors de la prochaine initialisation du conteneur).

Exemple:

conf.sql fichier:

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

fichier Dockerfile:

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

Et alors vous devrez exécuter conf.sql manuellement dans les bases de données déjà existantes. La configuration étant stockée dans le volume, elle survivra aux reconstructions.


Une autre alternative est de passer -c drapeauz autant de fois que vous le souhaitez:

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

De cette manière, vous n'avez pas besoin de créer une nouvelle image ni de vous soucier des bases de données existantes ou non existantes; tout sera affecté.

25
Yajo

Vous pouvez mettre votre coutume postgresql.conf dans un fichier temporaire à l'intérieur du conteneur et écrasez la configuration par défaut au moment de l'exécution.

Pour faire ça :

  • Copiez votre personnalisé postgresql.conf à l'intérieur de votre conteneur
  • Copiez le updateConfig.sh fichier dans /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

Au moment de l'exécution, le conteneur exécutera le script dans /docker-entrypoint-initdb.d/ et écrasez la configuration par défaut avec votre configuration personnalisée.

7
alphayax

J'ai parcouru toutes les réponses et il reste une autre option. Vous pouvez modifier votre valeur CMD dans le fichier Docker (ce n'est pas le meilleur, mais reste le moyen possible d'atteindre votre objectif).

Fondamentalement, nous devons

  • Copier le fichier de configuration dans le conteneur de menu fixe
  • Ignorer les options de démarrage de postgres

Exemple de fichier 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"]

Bien que je pense en utilisant command: postgres -c config_file=/etc/postgresql/postgresql.confdans votre docker-compose.yml fichier proposé par Matthias Braun est la meilleure option.

5
Dr. Botwing

Une solution relativement peu technique à ce problème semble être de déclarer le service (j'utilise swarm sur AWS et un fichier yaml) avec vos fichiers de base de données montés sur un volume persistant (ici AWS EFS comme indiqué par le pilote cloudstor: aws spécification).

  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. La base de données apparaît comme initialisée avec les paramètres par défaut de l'image.
  2. Vous modifiez les paramètres de configuration dans le conteneur, par exemple si vous souhaitez augmenter le nombre maximal de connexions simultanées nécessitant un redémarrage.
  3. arrêter le conteneur en cours d'exécution (ou réduire le service à zéro puis à un autre)
  4. l'essaim engendre un nouveau conteneur qui, cette fois, récupère vos paramètres de configuration persistants et les applique joyeusement.

Un effet secondaire agréable de la persistance de votre configuration est que vos bases de données sont également conservées (ou était-ce l'inverse) ;-)

2
Eoan

Ma solution s'adresse aux collègues qui doivent apporter des modifications à la configuration avant de lancer docker-entrypoint-initdb.d

J'avais besoin de changer le paramètre 'shared_preload_libraries' pour que, pendant son travail, Postgres ait déjà une nouvelle bibliothèque préchargée et que le code de docker-entrypoint-initdb.d puisse l'utiliser.

Je viens donc de corriger le fichier postgresql.conf.sample dans 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

Et avec ce correctif, il devient possible d'ajouter une extension dans un fichier .sql dans docker-entrypoint-initdb.d /:

CREATE EXTENSION pg_cron;
0
40min