我一直试图通过创建自定义用户和数据库来为开发postgres实例设置一个容器。我使用的是官方postgres docker映像。在文档中,它指导你在/docker-entrypoint-initdb中插入一个bash脚本。D /文件夹,使用任何自定义参数设置数据库。

我的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日志-f db (db是我的容器名)得到的错误是:

postgres:不能连接到服务器:没有这样的文件或目录

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


当前回答

使用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:

其他回答

编辑-自2015年7月23日

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

所以你所需要的就是创建下面的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

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

从postgres Docker映像的文档中可以看出

[…[/docker-entrypoint-initdb. conf]目录下的*.sh脚本。D .在启动服务之前进行进一步的初始化

这里重要的是“在启动服务之前”。这意味着您的脚本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

使用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

这将创建启动时提到的用户和数据库

我将自定义命令添加到启动服务后在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>

.

使用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:

您可以使用以下命令:

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;"