Cómo crear un usuario/base de datos en un script para Docker Postgres
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?
EDITAR - desde el 23 de julio de 2015
La imagen oficial de la ventana acoplable de Postgres ejecutará .sql
los 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_PASSWORD
POSTGRES_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, --single
se 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
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
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: