web-dev-qa-db-fra.com

Comment créer un utilisateur / une base de données dans un script pour Docker Postgres

J'ai essayé de configurer un conteneur pour une instance de développement postgres en créant un utilisateur et une base de données personnalisés. J'utilise le image officielle de docker postgres . Dans la documentation, il vous est demandé d'insérer un script bash dans le dossier /docker-entrypoint-initdb.d/ pour configurer la base de données avec tous les paramètres personnalisés.

Mon script bash: make_db.sh

su postgres -c "createuser -w -d -r -s docker"
su postgres -c "createdb -O docker docker"

Dockerfile

FROM library/postgres

RUN ["mkdir", "/docker-entrypoint-initdb.d"]
ADD make_db.sh /docker-entrypoint-initdb.d/

L'erreur que je reçois du docker logs -f db (la base de données est le nom de mon conteneur) est la suivante:

createuser: impossible de se connecter à la base de données postgres: impossible de se connecter au serveur: aucun fichier ou répertoire de ce type

Il semble que les commandes à l'intérieur du dossier /docker-entrypoint-initdb.d/ soient en cours d'exécution avant le démarrage de postgres. Ma question est la suivante: comment configurer par programme un utilisateur/une base de données à l’aide du conteneur officiel Postgres? Est-il possible de faire cela avec un script?

168
pech0rin

EDIT - depuis le 23 juillet 2015

Le image officielle de docker postgres exécutera les scripts .sql situés dans le dossier /docker-entrypoint-initdb.d/.

Donc, tout ce dont vous avez besoin est de créer le script SQL suivant:

init.sql

CREATE USER docker;
CREATE DATABASE docker;
GRANT ALL PRIVILEGES ON DATABASE docker TO docker;

et l'ajouter dans votre Dockerfile:

Dockerfile

FROM library/postgres
COPY init.sql /docker-entrypoint-initdb.d/

Mais depuis le 8 juillet 2015, si tout ce dont vous avez besoin est de créer un utilisateur et une base de données , il est plus facile de simplement utiliser le POSTGRES_USER, POSTGRES_PASSWORD et POSTGRES_DB variables d'environnement:

docker run -e POSTGRES_USER=docker -e POSTGRES_PASSWORD=docker -e POSTGRES_DB=docker library/postgres

ou avec un fichier Docker:

FROM library/postgres
ENV POSTGRES_USER docker
ENV POSTGRES_PASSWORD docker
ENV POSTGRES_DB docker

pour les images plus anciennes que le 23 juil. 2015

De la documentation de l’image postgres Docker , on dit que

[...] il recherchera tout script * .sh trouvé dans ce répertoire [/docker-entrypoint-initdb.d] pour procéder à une autre initialisation avant de démarrer le service

Ce qui est important ici est "avant de démarrer le service" . Cela signifie que votre script make_db.sh sera exécuté avant le démarrage du service postgres. Par conséquent, le message d'erreur "n'a pas pu se connecter à la base de données postgres" .

Après cela, il y a une autre information utile:

Si vous devez exécuter des commandes SQL dans le cadre de votre initialisation, l’utilisation du mode mono-utilisateur de Postgres est vivement recommandée.

D'accord, cela peut être un peu mystérieux au premier regard. Cela dit, votre script d'initialisation doit démarrer le service postgres en mode simple avant de faire ses actions. Vous pouvez donc modifier votre script make_db.ksh comme suit et vous rapprocher de ce que vous voulez:

NOTE, cela a changé récemment dans le commit suivant . Cela fonctionnera avec le dernier changement:

export PGUSER=postgres
psql <<- EOSQL
    CREATE USER docker;
    CREATE DATABASE docker;
    GRANT ALL PRIVILEGES ON DATABASE docker TO docker;
EOSQL

Auparavant, l'utilisation du mode --single était requise:

gosu postgres postgres --single <<- EOSQL
    CREATE USER docker;
    CREATE DATABASE docker;
    GRANT ALL PRIVILEGES ON DATABASE docker TO docker;
EOSQL
312
Thomasleveil

Vous pouvez maintenant placer des fichiers .sql dans le répertoire init:

à partir de la documentation

Si vous souhaitez effectuer une initialisation supplémentaire dans une image dérivée de celle-ci, ajoutez un ou plusieurs scripts * .sql ou * .sh sous /docker-entrypoint-initdb.d (en créant le répertoire si nécessaire). Une fois que le point d'entrée appelle initdb pour créer l'utilisateur et la base de données postgres par défaut, il exécute tous les fichiers * .sql et source tous les scripts * .sh trouvés dans ce répertoire pour procéder à une autre initialisation avant de démarrer le service.

Donc, copier votre fichier .sql fonctionnera.

15
m0meni

J'ajoute des commandes personnalisées à un environnement évoqué dans un CMD après le démarrage de services ... Je ne l'ai pas fait avec postgres, mais avec Oracle:

#set up var with noop command
RUN export POST_START_CMDS=":"
RUN mkdir /scripts
ADD script.sql /scripts
CMD service Oracle-xe start; $POST_START_CMDS; tail -f /var/log/dmesg

et commence avec

docker run -d ... -e POST_START_CMDS="su - Oracle -c 'sqlplus @/scripts/script' " <image>

.

8
Rondo

La base de données doit être en cours d'exécution avant de créer les utilisateurs. Pour cela, vous avez besoin de plusieurs processus. Vous pouvez soit démarrer postgres dans un sous-shell (&) dans le script Shell, soit utiliser un outil tel que supervisord pour exécuter postgres, puis exécuter tout script d'initialisation.

Guide de supervision et de menu fixe https://docs.docker.com/articles/using_supervisord/

3
seanmcl

Vous pouvez utiliser ces commandes:

docker exec -it yournamecontainer psql -U postgres -c "CREATE DATABASE mydatabase ENCODING 'LATIN1' TEMPLATE template0 LC_COLLATE 'C' LC_CTYPE 'C';"

docker exec -it yournamecontainer psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE postgres TO postgres;"
2
Gabriel