So erstellen Sie einen Benutzer / eine Datenbank im Skript für Docker Postgres

213

Ich habe versucht, einen Container für eine Postgres-Entwicklungsinstanz einzurichten, indem ich einen benutzerdefinierten Benutzer und eine benutzerdefinierte Datenbank erstellt habe. Ich verwende das offizielle Postgres-Docker-Bild . In der Dokumentation werden Sie angewiesen, ein Bash-Skript in den /docker-entrypoint-initdb.d/Ordner einzufügen , um die Datenbank mit benutzerdefinierten Parametern einzurichten.

Mein Bash-Skript: 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/

Der Fehler, den ich von docker logs -f db(db ist mein Containername) bekomme, ist:

createuser: konnte keine Verbindung zur Datenbank herstellen postgres: konnte keine Verbindung zum Server herstellen: Keine solche Datei oder kein solches Verzeichnis

Es scheint, dass die Befehle im /docker-entrypoint-initdb.d/Ordner ausgeführt werden, bevor postgres gestartet wird. Meine Frage ist, wie ich einen Benutzer / eine Datenbank programmgesteuert mit dem offiziellen Postgres-Container einrichte. Gibt es eine Möglichkeit, dies mit einem Skript zu tun?

pech0rin
quelle

Antworten:

378

BEARBEITEN - seit dem 23. Juli 2015

Das offizielle Postgres-Docker-Image führt .sqlSkripte aus, die sich im /docker-entrypoint-initdb.d/Ordner befinden.

Sie müssen also nur das folgende SQL-Skript erstellen:

init.sql

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

und fügen Sie es in Ihre Docker-Datei ein:

Dockerfile

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

Aber seit dem 8. Juli 2015, wenn alles , was Sie brauchen , ist einen Benutzer und Datenbank zu erstellen , ist es einfacher, nur Gebrauch machen , um das POSTGRES_USER, POSTGRES_PASSWORDund POSTGRES_DBUmgebungsvariablen:

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

oder mit einer Docker-Datei:

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

für Bilder älter als 23. Juli 2015

Aus der Dokumentation des Postgres Docker-Bildes geht hervor, dass

[...] es wird jedes in diesem Verzeichnis [ /docker-entrypoint-initdb.d] gefundene * .sh-Skript als Quelle für die weitere Initialisierung vor dem Start des Dienstes verwenden

Wichtig ist hier "vor dem Start des Dienstes" . Dies bedeutet, dass Ihr Skript make_db.sh ausgeführt wird, bevor der Postgres-Dienst gestartet wird. Daher wird die Fehlermeldung "Verbindung zur Datenbank Postgres konnte nicht hergestellt werden" angezeigt .

Danach gibt es noch eine nützliche Information:

Wenn Sie im Rahmen Ihrer Initialisierung SQL-Befehle ausführen müssen, wird die Verwendung des Postgres-Einzelbenutzermodus dringend empfohlen.

Einverstanden, dass dies auf den ersten Blick etwas mysteriös sein kann. Es heißt, dass Ihr Initialisierungsskript den Postgres-Dienst im Einzelmodus starten sollte, bevor Sie seine Aktionen ausführen. Sie können Ihr make_db.ksh- Skript also wie folgt ändern und es sollte Sie näher an das bringen, was Sie wollen:

HINWEIS : Dies hat sich kürzlich im folgenden Commit geändert . Dies funktioniert mit der neuesten Änderung:

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

Bisher war die Verwendung des --singleModus erforderlich:

gosu postgres postgres --single <<- EOSQL
    CREATE USER docker;
    CREATE DATABASE docker;
    GRANT ALL PRIVILEGES ON DATABASE docker TO docker;
EOSQL
Thomasleveil
quelle
2
Sie können mit:gosu postgres postgres --single < /tmp/somefile.sql
Thomasleveil
1
Wie kann ich laufenpsql -U myDb -d myDb -f myDb.sql
DarVar
3
Beachten Sie, dass --single in keiner der Postgres-Docker-Dateien mehr unterstützt wird.
Brianz
1
Ich folgte den Schritten und wenn ich in den MySQL-Container und in die CD ssh, docker-entrypoint-initdb.dsehe ich meine init.sqlmit dem SQL-Code darin. ABER wenn ich MySQL öffne (mit Root-Zugriff) und show database einfüge, sehe ich nur die Standardeinstellung in der docker-compose.ymlDatei! Warum funktioniert es bei mir nicht?
Mahmoud Zalt
1
Es wird nicht ausgeführt, db.sqlselbst nachdem es in `docker-entrypoint-initdb.d` kopiert wurde
kamal
16

Sie können jetzt SQL-Dateien im Init-Verzeichnis ablegen:

Aus den Dokumenten

Wenn Sie eine zusätzliche Initialisierung in einem von diesem abgeleiteten Bild durchführen möchten, fügen Sie unter /docker-entrypoint-initdb.d ein oder mehrere * .sql- oder * .sh-Skripte hinzu (erstellen Sie gegebenenfalls das Verzeichnis). Nachdem der Einstiegspunkt initdb aufgerufen hat, um den Standardbenutzer und die Standarddatenbank von postgres zu erstellen, werden alle * .sql-Dateien ausgeführt und alle in diesem Verzeichnis gefundenen * .sh-Skripts als Quelle für die weitere Initialisierung bereitgestellt, bevor der Dienst gestartet wird.

Das Kopieren Ihrer .sql-Datei in funktioniert also.

m0meni
quelle
Umgebungsvariablen für die Benutzer- / Kennwort- und Datenbankerstellung funktionieren weiterhin. (9.5.3)
Jeremiah Adams
1
Ich habe ein Projekt, das lokal funktioniert. Wenn ich es jedoch nach AWS EC2 verschiebe, wird angezeigt, dass die Datenbank nicht gefunden wurde. Ich kopiere die SQL-Datei in das richtige Verzeichnis, aber es wird immer noch dieser Fehler zurückgegeben. Irgendeine Idee, wo ich suchen könnte? Ich bin neu bei Docker.
MadPhysicist
1
Dies gilt nur, wenn eine einzelne Datenbankinstanz an ein einzelnes Volume gebunden ist, dh keine Skripts ausgeführt werden, wenn sich bereits etwas im Volume-Ordner befindet. Dies bereitet mir Kopfschmerzen, da ich für jeden meiner Stack-Services separate DB-Initialisierer haben möchte.
Violet Red
9

Mit docker-compose:

Angenommen, Sie haben folgendes Verzeichnislayout:

$MYAPP_ROOT/docker-compose.yml
           /Docker/init.sql
           /Docker/db.Dockerfile

Datei: docker-compose.yml

version: "3.3"
services:
  db:
    build:
      context: ./Docker
      dockerfile: db.Dockerfile
    volumes:
      - ./var/pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"

Datei: Docker/init.sql

CREATE USER myUser;

CREATE DATABASE myApp_dev;
GRANT ALL PRIVILEGES ON DATABASE myApp_dev TO myUser;

CREATE DATABASE myApp_test;
GRANT ALL PRIVILEGES ON DATABASE myApp_test TO myUser;

Datei: Docker/db.Dockerfile

FROM postgres:11.5-alpine
COPY init.sql /docker-entrypoint-initdb.d/

Dienste komponieren und starten:

docker-compose -f docker-compose.yml up --no-start
docker-compose -f docker-compose.yml start
Vlad
quelle
8

Ich füge einer Umgebung, die nach dem Starten von Diensten in einer CMD aufgerufen wird, benutzerdefinierte Befehle hinzu. Ich habe dies nicht mit postgres, sondern mit Oracle getan:

#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

und beginnen mit

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

.

Rondo
quelle
7

Sie können diese Befehle verwenden:

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;"
Gabriel
quelle
3
ENCODING 'LATIN1'ist sehr seltsam ... Sie müssen ganz besondere Bedürfnisse haben, um die Verwendung von utf8 zu vermeiden
Zyigh
4

Sie müssen die Datenbank ausführen, bevor Sie die Benutzer erstellen. Dafür benötigen Sie mehrere Prozesse. Sie können Postgres entweder in einer Subshell (&) im Shell-Skript starten oder ein Tool wie Supervisord verwenden, um Postgres auszuführen und anschließend Initialisierungsskripte auszuführen.

Eine Anleitung zu Supervisord und Docker https://docs.docker.com/articles/using_supervisord/

seanmcl
quelle
2

Mit Docker Compose gibt es eine einfache Alternative (es ist nicht erforderlich, eine Docker-Datei zu erstellen). Erstellen Sie einfach eine init-database.sh:

#!/bin/bash
set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    CREATE USER docker;
    CREATE DATABASE my_project_development;
    GRANT ALL PRIVILEGES ON DATABASE my_project_development TO docker;
    CREATE DATABASE my_project_test;
    GRANT ALL PRIVILEGES ON DATABASE my_project_test TO docker;
EOSQL

Und verweisen Sie darauf im Abschnitt Bände:

version: '3.4'

services:
  postgres:
    image: postgres
    restart: unless-stopped
    volumes:
      - postgres:/var/lib/postgresql/data
      - ./init-database.sh:/docker-entrypoint-initdb.d/init-database.sh
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    ports:
      - 5432:5432

volumes:
  postgres:
danigb
quelle