[英]How to create User/Database in script for Docker Postgres
我一直在嘗試通過創建自定義用戶和數據庫來為開發 postgres 實例設置容器。 我正在使用官方的 postgres docker 圖像。 在文檔中,它指示您在/docker-entrypoint-initdb.d/
文件夾中插入 bash 腳本,以使用任何自定義參數設置數據庫。
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 容器以編程方式設置用戶/數據庫? 有沒有辦法用腳本做到這一點?
官方postgres /docker-entrypoint-initdb.d/
鏡像將運行/docker-entrypoint-initdb.d/
文件夾中的.sql
腳本。
所以你需要的是創建以下sql腳本:
init.sql
CREATE USER docker;
CREATE DATABASE docker;
GRANT ALL PRIVILEGES ON DATABASE docker TO docker;
並將其添加到Dockerfile中:
Dockerfile
FROM library/postgres
COPY init.sql /docker-entrypoint-initdb.d/
但是從2015年7月8日開始, 如果你只需要創建一個用戶和數據庫 ,就可以更容易地使用POSTGRES_USER
, POSTGRES_PASSWORD
和POSTGRES_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
[...]它將在該目錄[
/docker-entrypoint-initdb.d
]中找到任何* .sh腳本,以便在啟動服務之前進行進一步的初始化
這里重要的是“在開始服務之前” 。 這意味着您的腳本make_db.sh將在postgres服務啟動之前執行,因此錯誤消息“無法連接到數據庫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
通過使用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
使用 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:
您現在可以將.sql文件放在init目錄中:
如果您想在從這個映像派生的映像中進行其他初始化,請在/docker-entrypoint-initdb.d下添加一個或多個* .sql或* .sh腳本(必要時創建目錄)。 在入口點調用initdb創建默認的postgres用戶和數據庫之后,它將運行任何* .sql文件,並在該目錄中找到任何* .sh腳本,以便在啟動服務之前進行進一步的初始化。
因此,復制.sql文件將起作用。
我在啟動服務之后將自定義命令添加到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>
。
使用 Postgres 最新圖像(ID:b262c8b2fb54)和 Docker 版本 20.10.6,docker-compose 看起來像,
version: '2'
services:
app:
# the detail of app
db:
image: 'postgres'
container_name: book-shop-db-postgres
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=bookshop-db
這將創建啟動時提到的用戶和數據庫
在創建用戶之前,您需要運行數據庫。 為此,您需要多個流程。 您可以在shell腳本的子shell(&)中啟動postgres,也可以使用supervisord之類的工具來運行postgres,然后運行任何初始化腳本。
supervisord和docker的指南https://docs.docker.com/articles/using_supervisord/
您可以使用以下命令:
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;"
這是我的docke-compose.yml
postgres:
image: postgres:latest
ports:
- 5432:5432
volumes:
- postgres_data:/var/lib/postgresql/data
- ${PROJECTDIR}/init.sql:/docker-entrypoint-initdb.d/1-schema.sql
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
- POSTGRES_PASSWORD=postgres
以下是您需要考慮的兩件事:
docker-entrypoint-initdb.d
僅在您的數據字典為空時有效。 因此,如果您有卷,請務必刪除它們docker-compose down --volumes
。
在init.sql
而不是docke-compose.yml
中創建您的用戶和數據庫。 在docker-compose.yml
中,您應該指定postgres
用戶。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.