Docker Postgres için komut dosyasında Kullanıcı / Veritabanı oluşturma


213

Özel bir kullanıcı ve veritabanı oluşturarak geliştirme postgres örneği için bir kap kurmaya çalışıyorum. Ben kullanıyorum resmi postgres liman işçisi görüntüsü . Belgelerde /docker-entrypoint-initdb.d/, veritabanını herhangi bir özel parametre ile kurmak için klasörün içine bir bash betiği eklemenizi söyler .

Benim bash betiğim: 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/

docker logs -f db(Db benim kapsayıcı adıdır) almak hata :

createuser: veritabanına bağlanamadı postgres: sunucuya bağlanamadı: Böyle bir dosya veya dizin yok

/docker-entrypoint-initdb.d/Postgres başlamadan önce klasörün içindeki komutların yürütüldüğü anlaşılıyor . Benim sorum, resmi postgres kapsayıcısını kullanarak programlı olarak bir kullanıcı / veritabanı nasıl kurabilirim? Bunu bir senaryo ile yapmanın bir yolu var mı?

Yanıtlar:


378

EDIT - 23 Tem 2015'den beri

Resmi postgres liman işçisi görüntü çalışacak .sqlkomut dosyalarını bulunan /docker-entrypoint-initdb.d/klasörde.

Tek ihtiyacınız olan aşağıdaki sql betiğini oluşturmak:

init.sql

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

ve Dockerfile'ınıza ekleyin:

Dockerfile

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

Ancak 8 Temmuz 2015'ten bu yana, ihtiyacınız olan tek şey bir kullanıcı ve veritabanı oluşturmaksaPOSTGRES_USER , POSTGRES_PASSWORDve POSTGRES_DBortam değişkenlerini kullanmak daha kolaydır :

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

veya bir Dockerfile ile:

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

23 Tem 2015'ten eski resimler için

Gönderen postgres Docker görüntünün belgelerinde , bu söylenir

[...] /docker-entrypoint-initdb.dhizmeti başlatmadan önce daha fazla başlatma yapmak için bu dizinde [ ] bulunan herhangi bir * .sh betiğini kaynaklayacaktır

Burada önemli olan "hizmete başlamadan önce" . Bu, make_db.sh betiğinizin postgres hizmetinin başlatılmasından önce yürütüleceği ve bu nedenle "veritabanı postgresine bağlanamadı" hata iletisinin gerçekleştirileceği anlamına gelir .

Bundan sonra başka bir yararlı bilgi var:

Başlatma işleminizin bir parçası olarak SQL komutlarını yürütmeniz gerekirse, Postgres tek kullanıcı modunun kullanılması önemle tavsiye edilir.

Bunun ilk bakışta biraz gizemli olabileceğini kabul etti. Söylediği şey, başlatma komut dosyanızın eylemlerini gerçekleştirmeden önce postgres hizmetini tek bir modda başlatmasıdır. Böylece make_db.ksh betiğinizi aşağıdaki gibi değiştirebilirsiniz ve sizi istediğiniz şeye yakınlaştırmalıdır:

NOT , bu son taahhütte son zamanlarda değişmiştir . Bu, en son değişiklikle çalışır:

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

Önceden, --singlemodun kullanılması gerekiyordu:

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

2
gosu postgres postgres --single < /tmp/somefile.sql
Şunları

1
Nasıl koşabilirimpsql -U myDb -d myDb -f myDb.sql
DarVar

3
Not, --single postgres Dockerfiles dosyalarının hiçbirinde artık desteklenmemektedir.
brianz

1
Ben adımları takip ve mysql konteyner içine ssh ve içine içine sql kodu ile docker-entrypoint-initdb.dgörmek benim cd init.sql. AMA mysql (root erişimi kullanarak) ve show show veritabanları açtığınızda sadece varsayılan docker-compose.ymldosyadan görmek! Neden benim için çalışmıyor?
Mahmoud Zalt

1
db.sql`Docker-entrypoint-initdb.d` dosyasına kopyalandıktan sonra bile yürütülmüyor
kamal

16

Şimdi .sql dosyalarını init dizinine koyabilirsiniz:

Dokümanlardan

Bundan türetilen bir görüntüde ek başlatma yapmak isterseniz, /docker-entrypoint-initdb.d altına bir veya daha fazla * .sql veya * .sh komut dosyası ekleyin (gerekirse dizini oluşturma). Giriş noktası, varsayılan postgres kullanıcı ve veritabanını oluşturmak için initdb'yi çağırdıktan sonra, * .sql dosyalarını çalıştırır ve hizmete başlamadan önce daha fazla başlatma yapmak için bu dizinde bulunan * .sh komut dosyalarını kaynaklar.

Bu nedenle, .sql dosyanızı kopyalamak işe yarayacaktır.


kullanıcı / şifre ve db oluşturma için çevresel değişkenler hala çalışır. (9.5.3)
Jeremiah Adams

1
Yerel olarak çalışan bir projem var. Ancak, AWS EC2'ye taşıdığımda DB'nin bulunmadığını söylüyor. .Sql dosyasını uygun dizine kopyalarım, ancak yine de bu hatayı döndürüyor. Nereye bakabileceğime dair bir fikrin var mı? Docker'da yeniyim.
MadPhysicist

1
Bu, yalnızca tek bir birime bağlı tek bir db örneği varsa doğrudur, yani birim klasöründe zaten bir şey varsa herhangi bir komut dosyası çalıştırmaz. Bu bana bir baş ağrısı verir, çünkü yığın hizmetlerimin her biri için ayrı bir db başlatıcısı olmasını istiyorum.
Violet Red

The docs Warning: scripts in /docker-entrypoint-initdb.d are only run if you start the container with a data directory that is empty; any pre-existing database will be left untouched on container startup. One common problem is that if one of your /docker-entrypoint-initdb.d scripts fails (which will cause the entrypoint script to exit) and your orchestrator restarts the container with the already initialized data directory, it will not continue on with your scripts.
sh87

9

Şunları kullanarak docker-compose:

Aşağıdaki dizin düzenine sahip olduğunuzu varsayarsak:

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

Dosya: docker-compose.yml

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

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

Dosya: Docker/db.Dockerfile

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

Oluşturma ve başlatma hizmetleri:

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

8

Hizmetleri başlattıktan sonra CMD'de uyarılmış bir ortama özel komutlar ekliyorum ... Postgres ile yapmadım, ancak Oracle ile:

#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

ve ile başla

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

.


7

Bu komutları kullanabilirsiniz:

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

3
ENCODING 'LATIN1'çok tuhaf ... utf8 kullanmaktan kaçınmak için çok özel ihtiyaçlarınız olmalı
Zyigh

4

Kullanıcıları oluşturmadan önce veritabanının çalışır durumda olması gerekir. Bunun için birden fazla işleme ihtiyacınız var. Kabuk betiğindeki alt kabukta (&) postgres başlatabilir veya postgres çalıştırmak ve ardından başlatma komut dosyalarını çalıştırmak için süpervizör gibi bir araç kullanabilirsiniz.

Süpervizör ve liman işçisi için bir kılavuz https://docs.docker.com/articles/using_supervisord/


2

Docker compose ile basit bir alternatif var (Dockerfile oluşturmaya gerek yok). Sadece bir init-database.sh oluşturun:

#!/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

Ve hacimler bölümünde referans verin:

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:
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.