【问题标题】:Creating a table in single user mode in postgres在 postgres 中以单用户模式创建表
【发布时间】:2015-05-06 02:49:29
【问题描述】:

我正在尝试从 postgres 映像创建 Dockerfile。 repo 说初始化应该通过在 /docker-entrypoint-initdb.d/ 中放置一个 shell 脚本来处理。我根据我在网上找到的一个示例放置了以下脚本:

#!/bin/bash
echo "******CREATING DOCKER DATABASE******"
gosu postgres postgres --single <<- EOSQL
   CREATE DATABASE orpheus;
   CREATE USER docker WITH ENCRYPTED PASSWORD 'pwd_docker';
   GRANT ALL PRIVILEGES ON DATABASE orpheus to docker;
   CREATE TABLE profiles ( \
     profile_id    SERIAL UNIQUE PRIMARY KEY, \
     user_id integer NOT NULL UNIQUE, \
     profile_photo_id integer NOT NULL UNIQUE, \
     age integer \
   );
   CREATE TABLE hidden_user ( \
     owner_id    integer NOT NULL PRIMARY KEY, \
     target_id integer NOT NULL \
   );
EOSQL
echo ""
echo "******DOCKER DATABASE CREATED******"

反斜杠似乎是必需的,否则我会收到解析错误。脚本运行没有错误,除了 CREATE TABLE 命令之外的所有命令似乎都产生了效果。

是不是单用户模式不支持建表?如果是这样,有没有更好的方法让 dockerfile 设置一个带有在 postgres 中创建的表的图像?

【问题讨论】:

  • 单用户模式仅用于灾难恢复:postgresql.nabble.com/… 问题是:你为什么要在单用户模式下启动 Postgres?
  • 在官方 docker repo 中推荐用于 postgres。 “如果您需要在初始化过程中执行 SQL 命令,强烈建议使用 Postgres 单用户模式。” - registry.hub.docker.com/_/postgres
  • 这显然是个坏建议
  • @a_horse_with_no_name 我认为他们试图避免数据库在所需的初始化完成之前出现并可用于一般连接。以listen_addresses = '' 启动它并使用unix 套接字或postgreslisten_addresses = '127.0.0.1, ::1' (via the -c` 参数并使用环回psql 会话会更加明智,做你需要做的事情,然后重新启动Pg 用于一般访问,但大多数时候 Docker 人员似乎更喜欢快速破解而不是强大的解决方案......

标签: postgresql docker dockerfile


【解决方案1】:

@a_horse_with_no_name 的评论让我走上了正轨。我决定放弃单用户模式,即使它是“推荐的”。相反,我使用 pg_ctl 启动 postgres,加载一些包含我的表创建的 sql 文件,并使用 pg_ctl 停止服务器。

我的 shell 脚本如下所示:

#!/bin/bash
echo "******CREATING DOCKER DATABASE******"

echo "starting postgres"
gosu postgres pg_ctl -w start

echo "bootstrapping the postgres db"
gosu postgres psql -h localhost -p 5432 -U postgres -a -f /db/bootstrap.sql

echo "initializing tables"
gosu postgres psql -h localhost -p 5432 -U postgres -d orpheus -a -f /db/setup.sql

echo "stopping postgres"
gosu postgres pg_ctl stop

echo "stopped postgres"


echo ""
echo "******DOCKER DATABASE CREATED******"

【讨论】:

  • 这对我很有用。谢谢你的提示;我开始转动我的轮子。
  • 你救了我几个小时的生命...非常感谢。
  • 几乎完美 - 我将“初始化表”上的用户切换为在引导程序中创建的用户:)
【解决方案2】:

如果您想在您需要执行的任何设置完成之前阻止用户访问 PostgreSQL,请仅使用环回访问或仅使用 unix 套接字启动它,进行初始化,然后重新启动它以进行一般访问。

我不会说 Docker,但如果您在常规环境中执行此操作,您会执行以下操作:

mkdir -p /db/temp_socket
chown -r postgres:postgres /db

PGHOST=/db/temp_socket pg_ctl -D /path/to/datadir -o "-c listen_addresses='' -c unix_socket_directories='/db/temp_socket'" -l "/db/dbsetup.log" -w start

# Do your work
PGHOST=/db/temp_socket psql -f some_script

PGHOST=/db/temp_socket pg_ctl -D /path/to/datadir -m fast -w stop

pg_ctl -D /path/to/datadir -w start ...normalstartupoptionsblah...

即启动 PostgreSQL 不监听任何 TCP/IP 套接字,并且使用非默认 unix_socket_directories。做你的设置。然后使用默认(或配置)unix_socket_directorieslisten_addresses 重新启动它,一旦它准备好进行一般访问。

您可以这样做:

  • 修改 pg_hba.conf 以仅允许您的设置用户/仅在环回地址/等上进行访问
  • 开始页面
  • 进行设置
  • pg_hba.conf 替换为生产版本
  • pg_ctl reloadSELECT pg_reload_conf() 加载新设置并允许一般访问

...但是这将允许应用程序连接,然后在设置阶段拒绝其身份验证;这可能不是您想要的,而且并非所有应用程序都能正确处理。

【讨论】:

  • 我喜欢这个答案。我们的应用程序容器正在使用一个小脚本来等待 postgres 容器接受 TCP 连接,然后再尝试连接它。为了导入架构而简单地启动它是一个问题,使用本地套接字很好地解决了这个问题。
【解决方案3】:

我测试了您的脚本,它几乎可以正常工作。使用 Postgresql 9.4 我设法使以下工作:

gosu postgres postgres --single -jE <<- EOSQL
   CREATE DATABASE orpheus;
EOSQL
echo    
gosu postgres postgres --single -jE orpheus <<- EOSQL
   CREATE USER docker WITH ENCRYPTED PASSWORD 'pwd_docker';
   GRANT ALL PRIVILEGES ON DATABASE orpheus to docker;
   CREATE TABLE profiles (
     profile_id    SERIAL UNIQUE PRIMARY KEY,
     user_id integer NOT NULL UNIQUE,
     profile_photo_id integer NOT NULL UNIQUE,
     age integer
   );
   CREATE TABLE hidden_user (
     owner_id    integer NOT NULL PRIMARY KEY,
     target_id integer NOT NULL
   );
EOSQL
echo

基本上我不得不将脚本一分为二,因为 postgresql 抱怨 create database 不能在多行脚本中使用。另一个只是在第二个命令中添加数据库名称orpheus

然后瞧

【讨论】:

    猜你喜欢
    • 2015-03-24
    • 1970-01-01
    • 2023-02-14
    • 2014-05-11
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    相关资源
    最近更新 更多