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

时间:2014-10-27 23:47:59

标签: bash postgresql docker dockerhub

我一直在尝试通过创建自定义用户&来为开发postgres实例设置容器。数据库。我正在使用official postgres docker image。在文档中,它指示您在/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容器以编程方式设置用户/数据库?有没有办法用脚本做到这一点?

8 个答案:

答案 0 :(得分:286)

编辑 - 自2015年7月23日起

official postgres docker image将运行.sql文件夹中的/docker-entrypoint-initdb.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_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日之前的图片

来自the documentation of the postgres Docker image,据说

  

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

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

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

  

如果您需要在初始化过程中执行SQL命令,强烈建议使用Postgres单用户模式。

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

注意,最近发生了变化in the following commit。这将适用于最新的变化:

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

答案 1 :(得分:13)

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

From the docs

  

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

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

答案 2 :(得分:8)

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

答案 3 :(得分:7)

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

答案 4 :(得分:3)

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

supervisord and docker https://docs.docker.com/articles/using_supervisord/

指南

答案 5 :(得分:3)

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

答案 6 :(得分:0)

您可以使用以下命令:

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

答案 7 :(得分:0)

使用 Postgres 最新映像(ID:b262c8b2fb54)和 Docker 版本 20.10.6,docker-compose 将如下所示,

private void Window_Activated(object sender, EventArgs e)
{
    //Dispatcher we need for window change the size first
    Dispatcher.BeginInvoke((Action)(() => {
        popUpOver.IsOpen = true;
    }));    
}
private void Window_Deactivated(object sender, EventArgs e)
{
    popUpOver.IsOpen = false;
}
private void Window_StateChanged(object sender, EventArgs e)
{
    popUpOver.IsOpen = this.WindowState != WindowState.Minimized;
}
private void Window_LocationChanged(object sender, EventArgs e)
{
    var offset = popUpOver.HorizontalOffset;
    popUpOver.HorizontalOffset = offset + 1;
    popUpOver.HorizontalOffset = offset;
}

<Popup x:Name="popUpOver" IsOpen="True" StaysOpen="True" Placement="RelativePoint" PlacementRectangle="300,300,500,500">
    <Button Content="OVER" Width="100" Height="30"/>
</Popup>

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