Postgres 和 Docker 在文件更改时重新部署

Posted

技术标签:

【中文标题】Postgres 和 Docker 在文件更改时重新部署【英文标题】:Postgres and Docker redeploy on file change 【发布时间】:2019-02-08 00:47:23 【问题描述】:

我正在使用 Java/Postgres/Docker/Gradle 创建一个 Web 应用程序。 我的项目是这样设置的:

有一个数据库容器和一个应用程序容器。 app 容器只运行一个普通的 jar 文件。 jar 文件是使用主机系统中的卷添加的。容器最初运行这个 jar 并监视它的变化。如果它发生变化,它会重新部署 jar,使开发人员可以立即在其本地计算机上查看更改。这就像在 Tomcat 上部署/更新战争文件。当您“按下按钮”时,实时应用程序会更新。无需停止应用程序,重新构建并重新运行:只需重新构建即可。

使用 Dockerhub 上的 Postgres 图像,我想做类似的事情:我想在 gradle 中“按下一个按钮”,这将更新一些由 DB 容器监控的文件并重新部署。

不幸的是,我碰壁了。我最初的想法是创建一个扩展 Postgres 的 Dockerfile。它所要做的就是像往常一样运行 Postgres 服务并运行一个脚本来查找某些文件中的更改并重新部署。

不幸的是,以下 Dockerfile 失败了:

FROM postgres:9.4

WORKDIR /db
COPY monitor.py .
COPY run-pg-and-monitor.sh .

CMD ["run-pg-and-monitor.sh"]

shell 脚本有以下命令:

# Run monitor in the background
python3 monitor.py &

# Run postgres normally
postgres

不幸的是,这不适用于 Postgres。我得到错误:

db_1       | "root" execution of the PostgreSQL server is not permitted.
db_1       | The server must be started under an unprivileged user ID to prevent
db_1       | possible system security compromise.  See the documentation for
db_1       | more information on how to properly start the server.

如果我将命令设置为:

CMD ["postgres"]

这是 Postgres 容器最初所做的,错误消失了。显然,这不会运行我需要的 monitor.py。

奇怪的是,运行不带方括号的 CMD 也会导致此问题。

CMD postgres

从 shell 环境中运行它也会失败:

CMD ["sh", "-c", "postgres"]

也许这与从 shell 运行它有关...

我知道 postgres 应该从 postgres 用户而不是 root 运行。我觉得奇怪的是,如果我将 CMD 设置为:

CMD ["whoami"]

我明白了:

db_1       | root

所以,它已经以 root 身份运行 postgres,没有任何问题。

我的第二个想法是做一个 gradle 任务:

1) 更新触发应用容器重新部署的 jar

2) 运行docker exec ... 手动更新正在运行的数据库容器。

这个想法的唯一问题是,如果没有运行应用程序或数据库容器,作业显然会失败。我将不得不添加检查它们是否存在的逻辑。这似乎不太理想。

有人有什么见解吗?有没有我不知道的已经存在的解决方案?

【问题讨论】:

linux.die.net/man/1/su 不知道 postgres,但您可能需要在一个帐户下运行这些...使用中的 postgres 守护进程,然后使用 su 执行相同操作。 我试过用 su 运行。当我这样做时,它抱怨找不到'postgres'命令...... su 使用了哪个用户?您可能需要使用postgres 的完整路径。或者可以使用-p 来保留环境/路径。 在尝试作为 postgres 运行后,它抱怨找不到文件。这也真的很奇怪。看来 Postgres Dockerfile 无论如何都以 root 身份运行。 github.com/docker-library/postgres/blob/… 【参考方案1】:

这些奇怪的原因是 postgres Dockerfile 将它自己的 docker-entrypoint.sh 脚本设置为图像的 ENTRYPOINT。所以在容器启动时,docker-entrypoint.sh 被执行,任何设置为 CMD 的东西都作为参数传递给脚本。

入口脚本将执行 postgres 所需的初始化步骤,例如删除权限,前提是第一个传递的参数等于 postgres(参见 here 和 here),然后最终简单地执行通过 @987654329 传递的任何内容@。

覆盖ENTRYPOINT 而不是CMD,本质上是用您自己的脚本包装docker-entrypoint.sh,应该会给您所需的行为:

# Run monitor in the background
python3 monitor.py &

# Run postgres normally
docker-entrypoint.sh "$@"

【讨论】:

开枪,我显然需要研究 Docker 的精妙之处。是的,我知道我错过了什么。感谢您的信息! 我最终只是从主机发出了正在运行的 db 容器的信号,但是有了这些信息,我也许可以从一开始就做我想做的事。谢谢! 好的,好的。我想我明白了。因此,在 shell/bash 中,"$@" 只是来自 CMD(或其他名称)的位置参数。在这种情况下,它只是 ["postgres"]。这被 ENTRYPOINT 使用,它也执行 Postgres-ey 咒语以正确启动。直到现在才知道 ENTRYPOINT 做了什么。

以上是关于Postgres 和 Docker 在文件更改时重新部署的主要内容,如果未能解决你的问题,请参考以下文章

无法从 docker-compose 启动 postgres docker 容器

[重命名应用程序中的树节点时重命名文件夹名称

如何更改 Postgresql docker 镜像密码

WSL2 和 Docker 桌面上的 Postgres 卷挂载:PGDATA 文件夹上的权限被拒绝

如何将节点 docker 容器与 postgres docker 容器连接起来

Laravel 在区域设置更改时重定向到路由