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

How to create User/Database in script for Docker Postgres

我一直在尝试通过创建自定义用户&来为开发postgres实例设置容器。 数据库。 我正在使用官方的postgres docker图像。 在文档中,它指示您在/docker-entrypoint-initdb.d/文件夹中插入bash脚本,以使用任何自定义参数设置数据库。

我的bash脚本:make_db.sh

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

Dockerfile

1
2
3
4
FROM library/postgres

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

我从docker logs -f db(db是我的容器名称)得到的错误是:

createuser: could not connect to database postgres: could not connect to server: No such file or directory

似乎在启动postgres之前正在执行/docker-entrypoint-initdb.d/文件夹内的命令。 我的问题是,如何使用官方postgres容器以编程方式设置用户/数据库? 有没有办法用脚本执行此操作?


编辑 - 自2015年7月23日起

官方postgres docker镜像将运行/docker-entrypoint-initdb.d/文件夹中的.sql脚本。

所以你需要的是创建以下sql脚本:

init.sql

1
2
3
CREATE USER docker;
CREATE DATABASE docker;
GRANT ALL PRIVILEGES ON DATABASE docker TO docker;

并将其添加到Dockerfile中:

Dockerfile

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

但是从2015年7月8日开始,如果你只需要创建一个用户和数据库,就可以更容易地使用POSTGRES_USERPOSTGRES_PASSWORDPOSTGRES_DB环境变量:

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

或者使用Dockerfile:

1
2
3
4
FROM library/postgres
ENV POSTGRES_USER docker
ENV POSTGRES_PASSWORD docker
ENV POSTGRES_DB docker

适用于2015年7月23日之前的图片

从postgres Docker图像的文档来看,据说

[...] it will source any *.sh script found in that directory [/docker-entrypoint-initdb.d] to do further initialization before starting the service

这里重要的是"在开始服务之前"。这意味着您的脚本make_db.sh将在postgres服务启动之前执行,因此错误消息"无法连接到数据库postgres"。

之后还有另一个有用的信息:

If you need to execute SQL commands as part of your initialization, the use of Postgres single user mode is highly recommended.

同意这在初看时可能有点神秘。它说的是你的初始化脚本应该在执行其操作之前以单一模式启动postgres服务。因此,您可以按照以下方式更改make_db.ksh脚本,它可以让您更接近您想要的内容:

注意,这在最近的提交中已经改变了。这将适用于最新的变化:

1
2
3
4
5
6
export PGUSER=postgres
psql <<- EOSQL
    CREATE USER docker;
    CREATE DATABASE docker;
    GRANT ALL PRIVILEGES ON DATABASE docker TO docker;
EOSQL

以前,需要使用--single模式:

1
2
3
4
5
gosu postgres postgres --single <<- EOSQL
    CREATE USER docker;
    CREATE DATABASE docker;
    GRANT ALL PRIVILEGES ON DATABASE docker TO docker;
EOSQL


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

来自文档

If you would like to do additional initialization in an image derived from this one, add one or more *.sql or *.sh scripts under /docker-entrypoint-initdb.d (creating the directory if necessary). After the entrypoint calls initdb to create the default postgres user and database, it will run any *.sql files and source any *.sh scripts found in that directory to do further initialization before starting the service.

因此,复制.sql文件将起作用。


我在启动服务之后将自定义命令添加到CMD中引发的环境中...我没有使用postgres,而是使用Oracle:

1
2
3
4
5
#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

并开始

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


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

supervisord和docker的指南https://docs.docker.com/articles/using_supervisord/


您可以使用以下命令:

1
2
3
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;"