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 容器
WSL2 和 Docker 桌面上的 Postgres 卷挂载:PGDATA 文件夹上的权限被拒绝