Docker Postgres 용 스크립트에서 사용자 / 데이터베이스를 만드는 방법


213

사용자 정의 사용자 및 데이터베이스를 만들어 개발 postgres 인스턴스에 대한 컨테이너를 설정하려고했습니다. 공식 postgres 도커 이미지를 사용하고 있습니다. 문서에서 /docker-entrypoint-initdb.d/사용자 정의 매개 변수를 사용하여 데이터베이스를 설정하기 위해 폴더 안에 bash 스크립트를 삽입하도록 지시합니다 .

내 bash 스크립트 : make_db.sh

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

도커 파일

FROM library/postgres

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

docker logs -f db(db는 내 컨테이너 이름입니다) 에서 얻는 오류 는 다음과 같습니다.

createuser : 데이터베이스에 연결할 수 없습니다 postgres : 서버에 연결할 수 없습니다 : 해당 파일 또는 디렉토리가 없습니다

/docker-entrypoint-initdb.d/postgres가 시작되기 전에 폴더 내부의 명령 이 실행되고 있는 것 같습니다 . 내 질문은 공식 postgres 컨테이너를 사용하여 프로그래밍 방식으로 사용자 / 데이터베이스를 어떻게 설정합니까? 스크립트로 이것을 할 수있는 방법이 있습니까?

답변:


378

편집-2015 년 7 월 23 일부터

공식 포스트 그레스 고정 표시기 이미지 실행 .sql스크립트는에있는 /docker-entrypoint-initdb.d/폴더.

따라서 필요한 것은 다음 SQL 스크립트를 작성하는 것입니다.

init.sql

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

Dockerfile에 추가하십시오.

도커 파일

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

그러나 2015 년 7 월 8 일 이후 로 사용자와 데이터베이스를 작성 하기 만하면 POSTGRES_USER, POSTGRES_PASSWORDPOSTGRES_DB환경 변수 를보다 쉽게 ​​사용할 수 있습니다 .

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

또는 Dockerfile로 :

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

2015 년 7 월 23 일보다 오래된 이미지

에서 postgres의 도커 이미지의 문서 , 그것은 있다고한다

[...] /docker-entrypoint-initdb.d서비스를 시작하기 전에 추가 초기화를 수행하기 위해 해당 디렉토리 [ ] 에서 찾은 * .sh 스크립트를 소싱합니다.

여기서 중요한 것은 "서비스를 시작하기 전에" 입니다. 이는 postgres 서비스가 시작되기 전에 make_db.sh 스크립트 가 실행되므로 "postgres 데이터베이스에 연결할 수 없습니다" 라는 오류 메시지가 표시 됩니다.

그 후 또 다른 유용한 정보가 있습니다.

초기화의 일부로 SQL 명령을 실행해야하는 경우 Postgres 단일 사용자 모드를 사용하는 것이 좋습니다.

첫눈에 조금 신비 할 수 있다는 데 동의했다. 말하는 것은 초기화 스크립트가 동작을 수행하기 전에 postgres 서비스를 단일 모드로 시작해야한다는 것입니다. 따라서 make_db.ksh 스크립트를 다음과 같이 변경할 수 있으며 원하는 것에 더 가까이 갈 수 있습니다.

참고 , 이것은 최근 다음 커밋에서 변경되었습니다 . 이것은 최신 변경 사항과 함께 작동합니다.

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

이전에는 --single모드를 사용해야했습니다.

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
Thomasleveil

1
달리는 방법psql -U myDb -d myDb -f myDb.sql
DarVar

3
postgres Dockerfile에서 --single은 더 이상 지원되지 않습니다.
brianz

1
나는 단계를 밟았고 mysql 컨테이너에 ssh하고 cd를 넣으면 SQL 코드가 들어있는 docker-entrypoint-initdb.d것을 볼 init.sql수 있습니다. 그러나 mysql (루트 액세스 사용)을 열고 show database를 입력하면 docker-compose.yml파일 에서 기본값 만 표시 됩니다! 왜 나를 위해 작동하지 않습니까?
Mahmoud Zalt

1
db.sql`docker-entrypoint-initdb.d`에 복사 한 후에도 실행되지 않습니다
kamal

16

이제 .sql 파일을 init 디렉토리에 넣을 수 있습니다.

문서에서

이 이미지에서 파생 된 이미지에서 추가 초기화를 수행하려면 /docker-entrypoint-initdb.d 아래에 하나 이상의 * .sql 또는 * .sh 스크립트를 추가하십시오 (필요한 경우 디렉토리 작성). 진입 점이 기본 postgres 사용자 및 데이터베이스를 작성하기 위해 initdb를 호출 한 후 서비스를 시작하기 전에 추가 초기화를 수행하기 위해 * .sql 파일을 실행하고 해당 디렉토리에있는 * .sh 스크립트를 소싱합니다.

따라서 .sql 파일을 복사하면 작동합니다.


사용자 / 암호 및 DB 생성을위한 환경 변수는 여전히 작동합니다. (9.5.3)
예레미야 아담스

1
로컬로 작동하는 프로젝트가 있습니다. 그러나 AWS EC2로 옮기면 DB를 찾을 수 없다는 메시지가 나타납니다. 적절한 디렉토리에 .sql 파일을 복사하지만 여전히 해당 오류를 반환합니다. 내가 어디에서 볼 수 있는지 아십니까? 저는 Docker를 처음 사용합니다.
MadPhysicist

1
단일 볼륨에 바인딩 된 단일 db 인스턴스가있는 경우에만 해당됩니다. 즉, 볼륨 폴더에 이미 스크립트가 있으면 스크립트가 실행되지 않습니다. 각 스택 서비스마다 별도의 db 이니셜 라이저를 원하기 때문에 두통이 발생합니다.
Violet Red

로부터 문서 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

사용하여 docker-compose:

다음 디렉토리 레이아웃이 있다고 가정합니다.

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

파일: docker-compose.yml

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

파일: 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;

파일: Docker/db.Dockerfile

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

서비스 작성 및 시작 :

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

8

서비스를 시작한 후 CMD에서 발생하는 환경에 사용자 정의 명령을 추가합니다 ... postgres로 수행하지 않았지만 Oracle에서 수행했습니다.

#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

그리고 시작

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

.


7

이 명령을 사용할 수 있습니다 :

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'매우 이상합니다 ... utf8 사용을 피해야하는 매우 특별한 요구가 있어야합니다
Zyigh

4

사용자를 작성하기 전에 데이터베이스를 실행해야합니다. 이를 위해 여러 프로세스가 필요합니다. 쉘 스크립트의 서브 쉘 (&)에서 postgres를 시작하거나 supervisord와 같은 도구를 사용하여 postgres를 실행 한 다음 초기화 스크립트를 실행할 수 있습니다.

감독자 및 도커 가이드 https://docs.docker.com/articles/using_supervisord/


2

docker compose에는 간단한 대안이 있습니다 (Dockerfile을 만들 필요가 없습니다). 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

볼륨 섹션에서 참조하십시오.

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:
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.