如何通过docker run运行一个包含插入语句的sql文件?

64

给定一个包含SQL插入语句的文件:

INSERT INTO countries (id, country_code, name)
VALUES
    (1, 'AF', 'Afghanistan'),
    (2, 'AL', 'Albania');

我想在正在运行Postgres的容器上,使用docker run命令运行该文件。

我已经尝试过这个:

docker run -e domain="192.168.99.100" pg /bin/bash -c "psql -d whiteboard_api -a -f inserts_into_countries_table.sql"
psql: could not connect to server: Connection refused
    Is the server running locally and accepting
    connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

你可以看到我的图像是pg格式:

capistrano:whiteboard_v2 jzollars$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
6b500bec9210        bbb                 "/usr/bin/supervisord"   4 weeks ago         Up 4 weeks          0.0.0.0:80->80/tcp       distracted_raman
c1e88f2695f5        wh                  "/usr/bin/supervisord"   4 weeks ago         Up 4 weeks          0.0.0.0:3000->3000/tcp   high_einstein
7e383e99bdc3        pg                  "/usr/lib/postgresql/"   4 weeks ago         Up 4 weeks          0.0.0.0:5432->5432/tcp   pg_test

我该如何使用docker run命令在Docker容器中加载并运行此文件?


你能分享一下你的 pg 镜像 Dockerfile 吗? - Thomasleveil
5个回答

98

要针对正在运行的容器执行命令,请使用docker exec

要将文件(例如dump.sql)复制到容器中,请使用docker cp

因此,你的方法可能看起来像这样:

docker cp ./dump.sql pg_test:/docker-entrypoint-initdb.d/dump.sql
docker exec -u postgres pg_test psql postgres postgres -f docker-entrypoint-initdb.d/dump.sql

这是通用形式:

docker cp ./localfile.sql containername:/container/path/file.sql
docker exec -u postgresuser containername psql dbname postgresuser -f /container/path/file.sql

请注意,如果您需要每次运行数据库时都要填充数据,则使用 官方postgres映像 时,文件夹/docker-entrypoint-initdb.d/具有特殊含义


1
谢谢,这是一个很好的答案,特别喜欢“通用形式”。 - JZ.
有没有办法在不将文件复制到容器中的情况下完成这个操作? - Max Carroll
我进行了一些搜索,但是我找不到任何方法可以在不将文件复制到Docker容器中的情况下完成它,如果有人找到了方法,请发布答案。 - Max Carroll
4
你可以使用 volume 标志将文件挂载到容器中,而不是显式地复制文件。命令为:docker run -v ./dump.sql:/docker-entrypoint-initdb.d/dump.sql pg_test - code_monk

89

你可以通过以下一行命令来针对正在运行的Postgres容器运行SQL命令文件

cat ./query.sql | docker exec -i <container-name> psql -U <user> -d <database>

无需将文件从主机复制到容器中即可完成操作。


3
这对我很有效。我不想使用其他答案,因为它们都使用多行或将文件存储在Docker实例上。我认为这是我使用情况的最佳答案,因为它只执行脚本,没有其他任何操作。 - pizzae
1
根据这个答案,我也期望它能够工作,并且它确实做到了。谢谢。echo SELECT * FROM table; | docker exec -i postgresdb psql -U user -d db - bearcat
似乎只有在Docker容器中运行psql时才能正常工作,无法在“远程”数据库上运行。提到这一点是因为我只想使用Docker容器的psql命令在另一个数据库上运行SQL。 - ka3ak
2
好的。已经想出如何做到了:echo "select count(*) from ..." | docker exec -i postgres-12.3 sh -c "export PGPASSWORD=<pwd> && psql -U <user> -h <ip> -p 5432 -d <db>"感谢您的回答。它很有帮助。 - ka3ak

7

使用官方的Docker镜像来安装PostgreSQL,code_monk的回答对我不起作用。我找到了这个解决方案:

docker exec -it <container-name> psql -U <DB_USER> -d <DB_NAME> -f /file.sql

文件/file.sql是在容器内还是在主机上?我尝试了一下,但它显示文件未找到,我想知道它是否正在容器中寻找文件而不是在主机上。 - Max Carroll
5
文件必须在容器内,你可以使用 docker cp 命令来复制它。 - GuanacoBE

1
#!/bin/bash
set -e

FUN_SQL2="
CREATE OR REPLACE FUNCTION insert_event(text)
  RETURNS integer AS
\\\\$BODY\\\\$
DECLARE ret INTEGER;
begin
select $1 into ret;
RETURN ret;

end;
\\\\$BODY\\\\$
  LANGUAGE 'plpgsql' VOLATILE
  COST 100;
"

# add function to DB
docker exec -it db_container sh -c "psql -U postgres -d db_name -c \"$FUN_SQL2\" ";

1
\$BODY\$ 必须包含 3 个 \\。 - Mariusz Szot

1

如果您也想使用ssh,这里有一个带有脚本/ sql的一行命令

#!/bin/bash

ssh -tt -i .ssh/local.pem username@remotehost docker exec -ti docker-container /usr/bin/psql postgresql://user:password@dbhost:port/dbname -f sqlscript_on_docker

ssh -tt -i .ssh/local.pem username@remotehost docker exec -ti docker-container /usr/bin/psql postgresql://user:password@dbhost:port/dbname -c \"select \* from table\”

请注意,此命令涉及IT技术。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接