在终端和bash脚本中运行docker exec有什么区别

时间:2019-01-27 14:33:42

标签: bash docker

假设我在脚本中运行以下命令:

#!/usr/bin/env bash

docker run --name mydb --rm -e POSTGRES_PASSWORD=kgalli -e POSTGRES_USER=kgalli -p "9999:5432" -v $PWD/db:/opt -d postgres

然后我运行以下命令来创建数据库时,它运行正常。

docker exec -e PGPASSWORD=kgalli mydb psql -U kgalli -d template1 -c "CREATE DATABASE kgalli_test WITH OWNER kgalli ENCODING 'UTF8' LC_COLLATE = 'en_US.utf8' LC_CTYPE = 'en_US.utf8';"

但是,当我将此行添加到上面的脚本中时,该脚本不仅启动了postgres服务器,还创建了失败的数据库。

我不太明白为什么会出现以下错误:

psql: could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

我知道我可以指示docker postgres映像在启动时创建数据库。但这实际上不是我想要实现的。我只是以此为例来理解问题。

3 个答案:

答案 0 :(得分:1)

使用docker run,您将启动一个新容器,使用docker exec,您将在已经运行的容器中执行命令

答案 1 :(得分:1)

在脚本中运行它时,很可能发生得太快。 docker run …命令立即返回,然后docker exec …在数据库服务器仍在启动时尝试使用PostgreSQL。创建额外的数据库之前,您需要等待它准备就绪。

也就是说,postgres image在其入口点脚本中具有运行自定义初始化脚本的功能。您可以将CREATE DATABASE …语句放入.sql文件或配置中,并将其装入容器中的/docker-entrypoint-initdb.d中。数据库服务器就绪后,postgres容器将自动运行它。

有关此文档的文档似乎已经消失了,但是you can see the implementation in docker-entrypoint.sh

答案 2 :(得分:0)

docker run命令首先在指定的图像上creates一个可写的容器层,然后使用指定的命令starts将其复制。

docker exec命令在正在运行的容器中运行新命令。 如果容器已暂停,则docker exec命令将失败并显示错误

$ docker pause test

test

$ docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                   PORTS               NAMES
1ae3b36715d2        ubuntu:latest       "bash"              17 seconds ago      Up 16 seconds (Paused)                       test

$ docker exec test ls

FATA[0000] Error response from daemon: Container test is paused, unpause the container before exec

$ echo $?
1

ref.1) (ref.2