【问题标题】:Unable to run queries from a file using psql command line with docker exec无法使用带有 docker exec 的 psql 命令行从文件运行查询
【发布时间】:2020-04-25 11:48:31
【问题描述】:

我有一个 bash 文件,应该让 postgres docker 容器联机,然后运行 ​​.sql 文件来创建数据库。但它抛出了错误。

psql: error: provision-db.sql: No such file or directory

我已经检查了路径,并且文件存在于这个 bash 脚本的同一级别。以下是我的 bash 文件的内容。

#!/usr/bin/env bash

docker-compose up -d db

# Ensure the Postgres server is online and usable
until docker exec -i boohoo.postgres pg_isready --host="${POSTGRES_HOST}" --username="${POSTGRES_USER}"
do
    echo "."
    sleep 1
done

docker exec -i boohoo.postgres psql -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -a -q -f provision-db.sql

这是provision-db.sql 文件。

DROP DATABASE "boo-hoo";
CREATE DATABASE "boo-hoo";
GRANT ALL PRIVILEGES ON DATABASE "boo-hoo" TO postgres;

这是docker-compose.yml的部分

version: '3.3'

services:
  db:
    container_name: boohoo.postgres
    hostname: postgres.boohoo
    image: postgres
    ports:
      - "15432:5432"
    environment:
      POSTGRES_USER: "postgres"
      POSTGRES_PASSWORD: "postgres"

【问题讨论】:

  • 文件如何进入容器?你可以在不需要docker exec的情况下从主机运行psql吗?
  • cat provision-db.sql | docker exec -i boohoo.postgres psql -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -a -q -f - 应该可以解决问题,因为 provision-db.sql 在您的主机上而不是在您的容器中。
  • @ckaserer 当我尝试这个时它不允许我在提示时输入数据库密码并给我FATAL: password authentication failed for user
  • @DavidMaze 如果我直接从 bash 脚本运行 psql 它将如何连接到容器数据库?
  • 使用-h 127.0.0.1 指向当前主机,并通过docker-compose.yml 文件中ports: 行中的第一个端口号。

标签: bash postgresql docker


【解决方案1】:

短版

这行得通

cat provision-db.sql | docker exec -i boohoo.postgres bash -c 'psql -U ${POSTGRES_USER} -w -a -q -f -'

长版

这里有很多东西

1) 为什么下面的命令找不到provision-db.sql

docker exec -i boohoo.postgres psql -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -a -q -f provision-db.sql

因为 provision-db.sql 在您的主机上,而不是在您的容器中。因此,当您在容器内执行 psql 命令时,找不到该文件

2) 为什么我的第一个解决方案不起作用?

cat provision-db.sql | docker exec -i boohoo.postgres psql -h "${POSTGRES_HOST}" -U "${POSTGRES_USER}" -a -q -f - 应该可以使用 provision-db.sql

这是因为变量${POSTGRES_USER}${POSTGRES_PASSWORD} 在您的主机上得到评估,我猜他们没有设置在那里。另外我忘记指定-w标志以避免密码提示

3) 为什么会这样?

cat provision-db.sql | docker exec -i boohoo.postgres bash -c 'psql -U ${POSTGRES_USER} -w -a -q -f -'

好吧,让我们一步一步来。

首先,我们将驻留在主机上的provision-db.sql 的内容打印到stdout,并通过| 将其传送到下一个命令。

docker-exec 在指定的容器 (boohoo.postgres) 中执行命令。通过指定 -i 标志,我们允许来自您主机的标准输入转到容器中的标准输入

在容器中,我们执行bash -c,它只是一个包装器,以避免评估主机上的 bash 变量。我们想要容器中的变量,通过将它放在单引号中我们可以做到这一点。

docker-exec boohoo.postgres bash -c "echo $POSTGRES_USER"

评估名为 POSTGRES_USER 的主机环境变量。

docker-exec boohoo.postgres bash -c "echo $POSTGRES_USER"

评估名为 POSTGRES_USER 的容器环境变量。

接下来我们只需要按顺序获取我们的 postgres 命令。

psql -U ${POSTGRES_USER} -w -a -q -f -

-U 指定用户
-w 不要求输入密码
-q 安静地执行此操作
-f - 处理您从标准输入获得的任何内容

【讨论】:

    【解决方案2】:

    -fpsql 的一个选项,而不是docker exec 的一个选项,并且psql 在容器内运行,因此它只能访问容器内的文件。

    【讨论】:

    • 嗯,谢谢你解释问题,但这个答案并不能解决问题。
    • 好的。但是一旦你理解了问题,解决方案就很简单了。
    猜你喜欢
    • 2017-11-12
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多