docker compose 网络在构建时是否可用于 dockerfile?

Are docker compose networks available to dockerfiles at build time?

提问人:cegredev 提问时间:11/10/2023 更新时间:11/10/2023 访问量:27

问:

我正在设置的 Web 服务器包含一个由节点和 postgres 服务组成的服务器。一旦容器运行,我就能够使用 postgres 容器的名称作为主机从节点容器与数据库进行通信。docker-compose.yml

但是,我想将数据库迁移逻辑集成到我的节点服务的 dockerfile 中,但连接失败并出现错误:

无法解析主机:db

这是我的配置的简化版本,用于展示错误:

FROM node:18-alpine AS builder

## ...Setup...

## Connect to database in order to migrate which essentially does this
RUN apk add curl
RUN curl http://db:5432
# And fails with the above error

## More stuff

# Stage Container
FROM node:18-alpine

# Stuff

## Run application
CMD ["node", "build/index.js"]

通过正在运行的容器访问数据库时,没有任何问题 - 但是当我尝试从 dockerfile 访问时,我收到错误。难道在构建时我只想做什么是不可能的吗?db:5432

节点.js postgresql docker docker-compose

评论

0赞 AymDev 11/10/2023
也许使用 RUN --network,但我真的不确定。但我可以确认这是一种不好的做法:这是一个构建,而不是部署。

答:

2赞 David Maze 11/10/2023 #1

docker compose 网络在构建时是否可用于 dockerfile?

不。

我想将数据库迁移逻辑集成到dockerfile中。难道在构建时我只想做什么是不可能的吗?

这是不可能的。


考虑您在 Compose 文件中运行的映像。您不会下载其 Dockerfile 并从源代码重新构建它;相反,您可以下载预编译的映像。每个 Docker 镜像都旨在以这种方式工作:原则上,您可以将构建的应用程序拉到某个 Docker 注册表中,然后将其拉取并在其他地方运行,而无需重新构建它。postgresdocker-compose build && docker-compose push

但现在,应用程序数据不是映像的一部分。它存储在 PostgreSQL 数据库中,通常存储在仅存在于计算机上的命名卷中。生成 Node 应用程序映像不会将另一个容器的不透明数据推送到该映像中。

在这种运营模式下,存在一些技术挑战。映像生成器不在 Compose 提供的网络上运行,而是在不包含某些标准 Docker 功能的“默认桥接网络”上运行。一个映像构建与另一个运行映像之间也没有排序限制;在启动数据库之前,这对您的应用程序来说是正常的。docker-compose builddocker-compose up


此处的典型方法是在入口点包装器脚本中运行迁移。编写一个 shell 脚本,该脚本运行迁移,然后运行传递给它的任何 Docker 命令

#!/bin/sh
npm run migrate
exec "$@"

COPY此文件放入映像中,使其成为 ,并保持不变。ENTRYPOINTCMD

COPY entrypoint.sh ./  # could be part of COPY ./ ./
ENTRYPOINT ["./entrypoint.sh"]
CMD ["node", "build/index.js"]

这将在每次启动时运行迁移,这通常是您想要的。

评论

0赞 cegredev 11/10/2023
谢谢!当我写这个问题时,我开始意识到这一点,这很有意义。我使用的 ORM 还能够在 Node 应用程序本身中运行迁移。你认为使用这样的入口点仍然是不好的做法,我不应该这样做,因为我可以选择不这样做?
0赞 David Maze 11/10/2023
有一种观点认为,应在部署到生产序列中手动运行迁移。我认为大多数迁移系统都可以处理多个并发迁移尝试。最大的风险是做一些像 Kubernetes 滚动更新这样的事情,你将同时运行软件的“旧”和“新”版本,你需要知道使用哪个数据库模式。我不认为在入口点这样做是一种不好的做法,但这也不是解决这个问题的唯一方法。
0赞 cegredev 11/14/2023
非常感谢,很抱歉回复晚了!我最终在我的 Web 应用程序中通过服务器端启动钩子执行此操作,考虑到项目的规模,这应该不是什么大问题,并且让事情变得容易得多。