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
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"
...
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:
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
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:
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
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
(Option de détachement) de docker run
Pour afficher directement les journaux du serveur.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;
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é.
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 :
postgresql.conf
à l'intérieur de votre conteneurupdateConfig.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.
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
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.conf
dans votre docker-compose.yml
fichier proposé par Matthias Braun est la meilleure option.
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"
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) ;-)
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;