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

我一直在试图通过创build一个自定义用户和数据库来设置一个开发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" 

Dockerfile

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

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

createuser:无法连接到数据库postgres:无法连接到服务器:没有这样的文件或目录

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

编辑 – 自2015年7月23日起

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

所以你只需要创build下面的sql脚本:

init.sql

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

并添加到你的Dockerfile:

Dockerfile

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

但是从2015年7月8日起, 如果您只需要创build一个用户和数据库 ,那么使用POSTGRES_USERPOSTGRES_PASSWORDPOSTGRES_DB环境variables会更容易:

 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镜像的文档来看 ,据说

它将获取在该目录中find的任何* .sh脚本[ /docker-entrypoint-initdb.d ],以在启动服务之前进行进一步的初始化

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

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

如果您需要在初始化过程中执行SQL命令,强烈build议使用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 

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

从文档

如果您想在从此映像派生的映像中进行额外的初始化,请在/docker-entrypoint-initdb.d下添加一个或多个* .sql或* .sh脚本(必要时创build该目录)。 在入口点调用initdb创build默认的postgres用户和数据库之后,它将运行任何* .sql文件,并在该目录中find任何* .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> 

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

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