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

fafcakar  于 2023-06-05  发布在  Docker
关注(0)|答案(9)|浏览(426)

我一直试图通过创建一个自定义用户和数据库来为开发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是我的容器名)得到的错误是:
创建用户:无法连接到数据库postgres:无法连接到服务器:没有这样的文件或目录
似乎在postgres启动之前,/docker-entrypoint-initdb.d/文件夹中的命令正在执行。我的问题是,如何使用官方的postgres容器以编程方式设置用户/数据库?有没有办法用脚本来实现这一点?

drkbr07n

drkbr07n1#

编辑-自2015年7月23日

official postgres docker image将运行/docker-entrypoint-initdb.d/文件夹中的.sql脚本。
所以你只需要创建以下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服务启动之前执行,因此出现错误消息 “could not connect to database 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
mfpqipee

mfpqipee2#

使用docker-compose
假设你有以下目录布局:

$MYAPP_ROOT/docker-compose.yml
           /Docker/init.sql
           /Docker/db.Dockerfile

File:docker-compose.yml

version: "3.3"
services:
  db:
    build:
      context: ./Docker
      dockerfile: db.Dockerfile
    volumes:
      - ./var/pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"

File: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;

File: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
368yc8dk

368yc8dk3#

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

wmomyfyw4#

您可以使用以下命令:

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

avkwfej45#

现在可以将.sql文件放在init目录中:
From the docs
如果您想在从该镜像派生的镜像中进行额外的初始化,请在/docker-entrypoint-initdb.d下添加一个或多个 *.sql或 *.sh脚本(如有必要,请创建目录)。在入口点调用initdb来创建默认的postgres用户和数据库之后,它将运行任何 *.sql文件,并获取该目录中找到的任何 *.sh脚本,以便在启动服务之前进行进一步的初始化。
所以复制你的.sql文件就可以了。

3bygqnnd

3bygqnnd6#

使用Postgres最新映像(ID:b262 c8 b2 fb 54)和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

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

bogh5gae

bogh5gae7#

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

.

eblbsuwk

eblbsuwk8#

您需要在创建用户之前运行数据库。为此,您需要多个过程。您可以在shell脚本的子shell(&)中启动postgres,或者使用supervisord之类的工具来运行postgres,然后运行任何初始化脚本。
Supervisord和Docker https://docs.docker.com/articles/using_supervisord/指南

edqdpe6u

edqdpe6u9#

这是我的docker-compose.yml

postgres:
    image: postgres:latest
    ports:
      - 5432:5432
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ${PROJECTDIR}/init.sql:/docker-entrypoint-initdb.d/1-schema.sql
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_DB=postgres
      - POSTGRES_PASSWORD=postgres

这里有两件事你需要考虑:

  1. docker-entrypoint-initdb.d仅在数据字典为空时才起作用。因此,如果您有卷,请确保删除它们docker-compose down --volumes
    1.在init.sql而不是docke-compose.yml中创建用户和数据库。在docker-compose.yml中,您应该指定postgres用户。

相关问题