2015-01-30 13 views
8

Sto cercando di creare un Dockerfile dall'immagine postgres. Il repository dice che l'inizializzazione dovrebbe essere gestita inserendo uno script di shell in /docker-entrypoint-initdb.d/. Ho messo il seguente script sulla base di un esempio che ho trovato on-line:Creazione di una tabella in modalità utente singolo in postgres

#!/bin/bash 
echo "******CREATING DOCKER DATABASE******" 
gosu postgres postgres --single <<- EOSQL 
    CREATE DATABASE orpheus; 
    CREATE USER docker WITH ENCRYPTED PASSWORD 'pwd_docker'; 
    GRANT ALL PRIVILEGES ON DATABASE orpheus to docker; 
    CREATE TABLE profiles (\ 
    profile_id SERIAL UNIQUE PRIMARY KEY, \ 
    user_id integer NOT NULL UNIQUE, \ 
    profile_photo_id integer NOT NULL UNIQUE, \ 
    age integer \ 
    ); 
    CREATE TABLE hidden_user (\ 
    owner_id integer NOT NULL PRIMARY KEY, \ 
    target_id integer NOT NULL \ 
    ); 
EOSQL 
echo "" 
echo "******DOCKER DATABASE CREATED******" 

I backslash sembrano necessari perché altrimenti ottengo un errore di analisi. Lo script viene eseguito senza errori e tutti i comandi tranne i comandi CREATE TABLE sembrano avere avuto un effetto.

È che la creazione di tabelle non è supportata in modalità utente singolo? Se è così, c'è un modo migliore per avere un file docker di creare un'immagine con tabelle create in postgres?

+2

modalità utente singolo non è destinato ad altro che il ripristino di emergenza: http://postgresql.nabble.com/BUG-12670-Can-t-create-postgis-extension-in- single-user-mode-tp5835585p5835592.html La domanda è: perché si avvia Postgres in modalità utente singolo? –

+1

Si consiglia nel repository ufficiale docker per postgres. "Se è necessario eseguire comandi SQL come parte dell'inizializzazione, si consiglia vivamente l'uso della modalità utente singolo Postgres." - https://registry.hub.docker.com/_/postgres/ – sdab

+2

Questo è chiaramente un cattivo consiglio –

risposta

10

@a_horse_with_no_name mi ha fatto sulla strada giusta con il suo commento. Ho deciso di abbandonare la modalità utente singolo anche se era "consigliata". Invece avvio postgres con pg_ctl, carico alcuni file sql contenenti le mie creazioni di tabelle e interrompo il server con pg_ctl.

mio script di shell assomiglia a questo:

#!/bin/bash 
echo "******CREATING DOCKER DATABASE******" 

echo "starting postgres" 
gosu postgres pg_ctl -w start 

echo "bootstrapping the postgres db" 
gosu postgres psql -h localhost -p 5432 -U postgres -a -f /db/bootstrap.sql 

echo "initializing tables" 
gosu postgres psql -h localhost -p 5432 -U postgres -d orpheus -a -f /db/setup.sql 

echo "stopping postgres" 
gosu postgres pg_ctl stop 

echo "stopped postgres" 


echo "" 
echo "******DOCKER DATABASE CREATED******" 
+1

Questo ha funzionato alla grande per me. Grazie per il consiglio; Stavo iniziando a girare le ruote. – Jondlm

+0

Hai salvato parecchie ore della mia vita ... Grazie mille. –

+0

Quasi perfetto: ho spostato l'utente sulle "tabelle di inizializzazione" su uno creato nel bootstrap però :) – GlynD

5

Se si desidera impedire PostgreSQL di essere accessibile agli utenti prima di tutto quello di installazione è necessario eseguire è fatto, avviare con accesso solo loopback oppure solo una presa unix , esegui l'inizializzazione, quindi riavvialo per l'accesso generale.

non parlo Docker, ma se si stesse facendo questo in un ambiente normale si farebbe qualcosa di simile:

mkdir -p /db/temp_socket 
chown -r postgres:postgres /db 

PGHOST=/db/temp_socket pg_ctl -D /path/to/datadir -o "-c listen_addresses='' -c unix_socket_directories='/db/temp_socket'" -l "/db/dbsetup.log" -w start 

# Do your work 
PGHOST=/db/temp_socket psql -f some_script 

PGHOST=/db/temp_socket pg_ctl -D /path/to/datadir -m fast -w stop 

pg_ctl -D /path/to/datadir -w start ...normalstartupoptionsblah... 

cioè iniziare PostgreSQL non ascoltare su tutti i socket TCP/IP, e con un non predefinito unix_socket_directories. Fai il tuo setup. Quindi riavvialo con il valore predefinito (o configurato) unix_socket_directories e listen_addresses una volta pronto per l'accesso generale.

Invece di questo si potrebbe:

  • Modifica pg_hba.conf solo consentire l'accesso dal vostro utente Setup/solo l'indirizzo di loopback/etc
  • Inizio Pg
  • Fate la vostra configurazione
  • Sostituire pg_hba.conf con quello di produzione
  • pg_ctl reload o SELECT pg_reload_conf() per caricare le nuove impostazioni e consentire l'accesso generale

... tuttavia ciò permetterà applicazioni per collegare poi respingere l'autenticazione durante la fase di installazione; potrebbe non essere quello che vuoi, e non tutte le applicazioni affrontano questo correttamente.

+1

Mi piace questa risposta. I nostri contenitori di app utilizzano un piccolo script per attendere che il contenitore di Postgre accetti le connessioni TCP prima di tentare di connettersi ad esso. Avere in breve tempo per importare lo schema è un problema, che è ben risolto utilizzando un socket locale. –

0

Ho testato il tuo script e sta funzionando quasi bene. Utilizzando PostgreSQL 9.4 sono riuscito a fare la seguente al lavoro:

gosu postgres postgres --single -jE <<- EOSQL 
    CREATE DATABASE orpheus; 
EOSQL 
echo  
gosu postgres postgres --single -jE orpheus <<- EOSQL 
    CREATE USER docker WITH ENCRYPTED PASSWORD 'pwd_docker'; 
    GRANT ALL PRIVILEGES ON DATABASE orpheus to docker; 
    CREATE TABLE profiles (
    profile_id SERIAL UNIQUE PRIMARY KEY, 
    user_id integer NOT NULL UNIQUE, 
    profile_photo_id integer NOT NULL UNIQUE, 
    age integer 
    ); 
    CREATE TABLE hidden_user (
    owner_id integer NOT NULL PRIMARY KEY, 
    target_id integer NOT NULL 
    ); 
EOSQL 
echo 

Fondamentalmente ho dovuto dividere lo script in due come il PostgreSQL si lamentava che il create database non potrebbe essere utilizzato negli script multilinea. E l'altro era solo per aggiungere il nome del database, orpheus, al secondo comando.

e voilà

Problemi correlati