我正在使用 Java/Postgres/Docker/Gradle 创建一个 Web 应用程序。我的项目是这样设置的:
有一个数据库容器和一个应用程序容器。app 容器只运行一个普通的 jar 文件。jar 文件是使用主机系统中的卷添加的。容器最初运行这个 jar 并监视它的变化。如果它发生变化,它会重新部署 jar,使开发人员可以立即在其本地计算机上查看更改。这就像在 Tomcat 上部署/更新战争文件。当您“按下按钮”时,实时应用程序会更新。无需停止应用程序,重新构建并重新运行:只需重新构建。
使用 Dockerhub 上的Postgres映像,我想做类似的事情:我想在 gradle 中“按下一个按钮”,这将更新数据库容器监控的一些文件并重新部署它。
不幸的是,我碰壁了。我最初的想法是创建一个扩展 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"]
也许这与从外壳运行它有关......
我知道 postgres 应该从 postgres 用户而不是 root 运行。我觉得奇怪的是,如果我将 CMD 设置为:
CMD ["whoami"]
我得到:
db_1 | root
因此,它已经以 root 身份运行 postgres,没有任何问题。
我的第二个想法是做一个 gradle 任务:
1) 更新触发应用容器重新部署的 jar
2) 运行docker exec ...
以手动更新正在运行的数据库容器。
这个想法的唯一问题是,如果没有运行应用程序或数据库容器,作业显然会失败。我将不得不添加检查它们是否存在的逻辑。这似乎并不理想。
有没有人有任何见解?有没有我不知道的已经存在的解决方案?