如何在Docker Postgres的脚本中创建用户/数据库


213

我一直在尝试通过创建自定义用户和数据库来为开发postgres实例设置容器。我正在使用官方的postgres docker镜像。在文档中,它指示您在/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"

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容器以编程方式设置用户/数据库?有没有办法用脚本来做到这一点?

Answers:


378

编辑-自2015年7月23日起

正式的Postgres泊坞窗图像将运行.sql脚本中找到的/docker-entrypoint-initdb.d/文件夹中。

因此,您所需要做的就是创建以下sql脚本:

初始化程序

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

并将其添加到您的Dockerfile中:

Docker文件

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

但自2015年7月8日,如果你需要的是创建一个用户和数据库,它更容易只是让要用到的POSTGRES_USERPOSTGRES_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映像的文档中可以说,

[...]它将启动在该目录[ /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

以前,需要使用--singlemode:

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 2015年

3
注意,任何postgres Dockerfile中不再支持--single。
brianz

1
我按照步骤操作,当我将ssh放入mysql容器并cd进入时,docker-entrypoint-initdb.d我看到了init.sql其中的sql代码。但是,当我打开mysql(使用root用户访问权限)并键入show database时,我只能从该docker-compose.yml文件中看到默认值!为什么对我不起作用?
马哈茂德·扎尔特

1
它不执行db.sql它复制到`即使泊坞窗,入口点,initdb.d`
卡迈勒

16

现在,您可以将.sql文件放入init目录中:

来自文档

如果要在从该镜像派生的映像中进行其他初始化,请在/docker-entrypoint-initdb.d下添加一个或多个* .sql或* .sh脚本(如有必要,创建目录)。入口点调用initdb创建默认的postgres用户和数据库后,它将运行任何* .sql文件并提供在该目录中找到的所有* .sh脚本,以在启动服务之前进行进一步的初始化。

因此,复制.sql文件即可。


用于用户/密码和数据库创建的环境变量仍然有效。(9.5.3)
耶利米亚当斯

1
我有一个在本地工作的项目。但是,当我将其移至AWS EC2时,它表示未找到数据库。我将.sql文件复制到正确的目录中,但它仍返回该错误。知道我在哪里可以看到吗?我是Docker的新手。
MadPhysicist

1
仅当有一个数据库实例绑定到单个卷时,这才是正确的;即,如果卷文件夹中已经有任何实例,它将不会运行任何脚本。这让我头疼,因为我想为每个堆栈服务使用单独的数据库初始化程序。
紫红色

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

创建用户之前,需要先运行数据库。为此,您需要多个过程。您可以在shell脚本的子shell(&)中启动postgres,也可以使用supervisor之类的工具运行postgres,然后运行任何初始化脚本。

主管和Docker指南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:
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.