Cómo crear un usuario/base de datos en un script para Docker Postgres

Resuelto pech0rin asked hace 10 años • 10 respuestas

He estado intentando configurar un contenedor para una instancia de desarrollo de Postgres creando un usuario y una base de datos personalizados. Estoy usando la imagen oficial de la ventana acoplable de Postgres . En la documentación, le indica que inserte un script bash dentro de la /docker-entrypoint-initdb.d/carpeta para configurar la base de datos con cualquier parámetro personalizado.

Mi script bash: make_db.sh

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

archivo acoplable

FROM library/postgres

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

El error que recibo de docker logs -f db(db es el nombre de mi contenedor) es:

createuser: no se pudo conectar a la base de datos postgres: no se pudo conectar al servidor: no existe tal archivo o directorio

Parece que los comandos dentro de la /docker-entrypoint-initdb.d/carpeta se ejecutan antes de que se inicie postgres. Mi pregunta es, ¿cómo configuro un usuario/base de datos mediante programación utilizando el contenedor oficial de Postgres? ¿Hay alguna manera de hacer esto con un script?

pech0rin avatar Oct 28 '14 06:10 pech0rin
Aceptado

EDITAR - desde el 23 de julio de 2015

La imagen oficial de la ventana acoplable de Postgres ejecutará .sqllos scripts que se encuentran en la /docker-entrypoint-initdb.d/carpeta.

Entonces todo lo que necesitas es crear el siguiente script SQL:

inicio.sql

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

y agrégalo en tu Dockerfile:

archivo acoplable

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

Pero desde el 8 de julio de 2015, si todo lo que necesita es crear un usuario y una base de datos , es más fácil utilizar las variables de entorno y POSTGRES_USER:POSTGRES_PASSWORDPOSTGRES_DB

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

o con un Dockerfile:

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

para imágenes anteriores al 23 de julio de 2015

De la documentación de la imagen Docker de postgres , se dice que

[...] obtendrá cualquier script *.sh que se encuentre en ese directorio [ /docker-entrypoint-initdb.d] para realizar una inicialización adicional antes de iniciar el servicio

Lo importante aquí es "antes de iniciar el servicio" . Esto significa que su script make_db.sh se ejecutará antes de que se inicie el servicio postgres, de ahí el mensaje de error "no se pudo conectar a la base de datos postgres" .

Después de eso hay otra información útil:

Si necesita ejecutar comandos SQL como parte de su inicialización, se recomienda encarecidamente el uso del modo de usuario único de Postgres.

De acuerdo, esto puede resultar un poco misterioso a primera vista. Lo que dice es que su script de inicialización debe iniciar el servicio postgres en modo único antes de realizar sus acciones. Por lo tanto, podría cambiar su script make_db.ksh de la siguiente manera y debería acercarlo a lo que desea:

NOTA , esto ha cambiado recientemente en la siguiente confirmación . Esto funcionará con el último cambio:

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

Anteriormente, --singlese requería el uso del modo:

gosu postgres postgres --single <<- EOSQL
    CREATE USER docker;
    CREATE DATABASE docker;
    GRANT ALL PRIVILEGES ON DATABASE docker TO docker;
EOSQL
Thomasleveil avatar Oct 28 '2014 00:10 Thomasleveil

Mediante el uso docker-compose:

Suponiendo que tiene el siguiente diseño de directorio:

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

Archivo:docker-compose.yml

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

Archivo: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;

Archivo:Docker/db.Dockerfile

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

Servicios de composición y puesta en marcha:

docker-compose -f docker-compose.yml up --no-start
docker-compose -f docker-compose.yml start
Vlad avatar Oct 11 '2019 17:10 Vlad

Con Docker Compose existe una alternativa sencilla (no es necesario crear un Dockerfile). Simplemente cree un 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

Y haga referencia a él en la sección de volúmenes:

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 avatar May 11 '2020 11:05 danigb