从 docker-compose 连接到 Postgres 作为 SystemD 服务

Connect to Postgres as SystemD service from docker-compose

我需要从 docker-compose 文件中连接到 运行 作为 SystemD 服务的 Postgres 服务器实例。

docker-compose containers ---> postgres as systemd

这是关于使用 localhost 上的外部 Postgres 数据库设置 Airflow。

我以 docker-compose 为例:

curl -LfO 'https://airflow.apache.org/docs/apache-airflow/2.2.3/docker-compose.yaml'

然而,他们在那里定义了一个 Postgres 容器,Airflow 通过解析 Docker 网络中的 postgres 主机来连接到该容器。

但是我已经通过 SystemD 在机器上安装了 Postgres 运行,我可以通过以下方式检查其状态:

# make sure the service is up and running
systemctl list-units --type=service | grep postgres.*12
# check the process
ps aux | grep postgres.*12.*config_file
# check the service details
systemctl status postgresql@12-main.service

docker-compose YAML 文件中的 AFAIU 我需要使用 host.docker.internal 功能,因此 Docker 服务使 docker 容器从 Docker 网络并使用 SystemD 服务查找 localhost 例如Postgres.

我已经为 docker-compose 设置了 Airflow YAML 文件:

---
version: '3'
x-airflow-common:
  &airflow-common
  image: ${AIRFLOW_IMAGE_NAME:-apache/airflow:2.2.3}
  environment:
    &airflow-common-env
    AIRFLOW__CORE__EXECUTOR: LocalExecutor
    AIRFLOW__CORE__SQL_ALCHEMY_CONN: postgresql+psycopg2://airflow:airflow@host.docker.internal/airflow
    ...
  extra_hosts:
    - "host.docker.internal:host-gateway"

那里发生了很多事情,但重点是 SQLAlchemy 连接字符串使用 host.docker.internal 作为主机。

现在,当我调用命令 docker-compose -f airflow-local.yaml up airflow-init 时,我在输出日志中看到 Airflow 抱怨它找不到 Postgres 服务器:

airflow-init_1       | psycopg2.OperationalError: connection to server at "host.docker.internal" (172.17.0.1), port 5432 failed: Connection refused
airflow-init_1       |  Is the server running on that host and accepting TCP/IP connections?

可能是Docker特殊网络和OS网络之间的DNS解析有问题,不知道如何解决。

我如何制作 Docker 容器来找出服务于 localhost 的 SystemD 服务?

原来我只需要在 Docker 容器定义的 YAML 代码中使用 network_mode: host(容器是 docker-compose 术语中的服务)。

这样 Docker 虚拟网络以某种方式绑定到笔记本电脑网络层(“localhost”或“127.0.0.1”)。 Docker 人不鼓励这种设置,但有时在处理遗留系统时事情会很混乱,因此您必须解决过去所做的事情。

然后您可以使用 localhost 作为 SystemD 服务访问 Postgres DB 运行。

唯一需要注意的是有人在使用 network_mode: host 时不能使用端口映射,否则 docker-compose 会抱怨错误信息:

"host" network_mode is incompatible with port_bindings

因此您必须删除类似于以下内容的 YAML 部分:

ports:
  - 9999:8080

并以不同的方式整理端口(TCP 套接字)。

在我的特定场景(Airflow 的东西)中,我做了以下事情:

对于使 Airflow 网络服务器 (docker container/service) 到达 localhost 上的 Postgres 数据库 (SystemD service/daemon) 的 host/networking:

# see the use of "localhost"
AIRFLOW__CORE__SQL_ALCHEMY_CONN: postgresql+psycopg2://airflow:airflow@localhost/airflow

对于 TCP 端口,在 Airflow 网络服务器的 docker-compose YAML 服务定义中,我指定了端口:

command: webserver -p 9999