381 Stimmen

Wie erstellt man Benutzer/Datenbank im Skript für Docker Postgres

Ich habe versucht, einen Container für eine Entwicklungs-Postgres-Instanz einzurichten, indem ich einen benutzerdefinierten Benutzer & Datenbank erstelle. Ich verwende das offizielle Postgres Docker-Image. In der Dokumentation wird darauf hingewiesen, dass ein Bash-Skript in den /docker-entrypoint-initdb.d/-Ordner eingefügt werden muss, 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 den docker logs -f db (db ist mein Containername) erhalte, ist:

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

Es scheint, dass die Befehle innerhalb des /docker-entrypoint-initdb.d/-Ordners ausgeführt werden, bevor Postgres gestartet wird. Meine Frage ist, wie richte ich einen Benutzer/Datenbank programmatisch mit dem offiziellen Postgres-Container ein? Gibt es einen Weg, dies mit einem Skript zu tun?

634voto

Thomasleveil Punkte 91312

BEARBEITEN - seit dem 23. Jul 2015

Das offizielle Postgres Docker-Image wird .sql Skripte ausführen, die im Ordner /docker-entrypoint-initdb.d/ gefunden werden.

Alles, was Sie brauchen, ist das folgende SQL-Skript zu erstellen:

init.sql

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

und fügen Sie es in Ihre Dockerfile hinzu:

Dockerfile

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

Aber seit dem 8. Juli 2015 ist es einfacher, wenn Sie nur einen Benutzer und eine Datenbank erstellen müssen, die Umgebungsvariablen POSTGRES_USER, POSTGRES_PASSWORD und POSTGRES_DB zu verwenden:

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

oder mit einem Dockerfile:

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

für Bilder älter als 23. Jul 2015

Von der Dokumentation des Postgres Docker-Images ist zu lesen, dass

[...] es jedes *.sh Skript in diesem Verzeichnis [/docker-entrypoint-initdb.d] aufrufen wird, um weitere Initialisierungen vor dem Start des Dienstes durchzuführen.

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 die Fehlermeldung "konnte keine Verbindung zur Datenbank postgres herstellen".

Danach gibt es noch eine weitere nützliche Information:

Wenn Sie SQL-Befehle als Teil Ihrer Initialisierung ausführen müssen, wird die Verwendung des Postgres-Einzelnutzermodus dringend empfohlen.

Zugegebenermaßen kann dies auf den ersten Blick etwas mysteriös sein. Was damit gemeint ist, ist, dass Ihr Initialisierungsskript den Postgres-Dienst im Einzelmodus starten sollte, bevor es seine Aktionen ausführt. Sie könnten also Ihr make_db.ksh Skript wie folgt ändern und es sollte Sie näher an das bringen, was Sie wollen:

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

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

Zuvor war die Verwendung des --single Modus erforderlich:

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

58voto

Vlad Punkte 5563

Bei Verwendung von docker-compose:

Vorausgesetzt, 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/

Komponieren und Starten von Diensten:

docker-compose -f docker-compose.yml up --no-start
docker-compose -f docker-compose.yml start

41voto

danigb Punkte 601

Mit Docker Compose gibt es eine einfache Alternative (kein Dockerfile erforderlich). Erstellen Sie einfach ein 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 der Volumes:

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:

26voto

Gabriel Punkte 453

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

17voto

m0meni Punkte 15072

Jetzt können Sie .sql-Dateien im init-Verzeichnis ablegen:

Aus der Dokumentation

Wenn Sie zusätzliche Initialisierungen in einem von diesem abgeleiteten Bild durchführen möchten, fügen Sie ein oder mehrere *.sql- oder *.sh-Skripte unter /docker-entrypoint-initdb.d hinzu (ggf. das Verzeichnis erstellen). Nachdem der Eintrittspunkt initdb aufgerufen hat, um den Standard-Postgres-Benutzer und die -Datenbank zu erstellen, werden alle *.sql-Dateien ausgeführt und alle *.sh-Skripte in diesem Verzeichnis ausgeführt, um weitere Initialisierungen vor dem Start des Dienstes durchzuführen.

Das Kopieren Ihrer .sql-Datei funktioniert also.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X