Podman DNS
解決在 Podman Compose 上 DNS Server 無法使用的問題
本文將解析在使用 Podman Compose 時遇到的 DNS 服務器問題,並提供解決方案。
使用環境
作業系統為 Rocky Linux 8.7
:
工具 podman-compose
版本如下:
podman-compose version: 1.0.7
podman version: 4.4.1
環境描述
由於部門都是在 LINE 上討論公事,常常造成公私不分,因此想架設一個 Rocket Chat 作為辦公的溝通平台,而 Rocket Chat
也有提供 docker-compose.yaml
讓用戶方便部署:
13個你不應該用Line辦公的理由: https://blog.teampel.com/2020/07/13-reasons-not-to-use-line.html
Rocket Chat: https://docs.rocket.chat/deploy/deploy-rocket.chat/deploy-with-docker-and-docker-compose
# src: https://github.com/RocketChat/Docker.Official.Image/blob/master/compose.yml
volumes:
mongodb_data: { driver: local }
services:
rocketchat:
image: registry.rocket.chat/rocketchat/rocket.chat:${RELEASE:-latest}
...
environment:
MONGO_URL: "${MONGO_URL:-\
mongodb://${MONGODB_ADVERTISED_HOSTNAME:-mongodb}:${MONGODB_INITIAL_PRIMARY_PORT_NUMBER:-27017}/\
${MONGODB_DATABASE:-rocketchat}?replicaSet=${MONGODB_REPLICA_SET_NAME:-rs0}}"
...
mongodb:
image: docker.io/bitnami/mongodb:${MONGODB_VERSION:-5.0}
restart: always
volumes:
- mongodb_data:/bitnami/mongodb
environment:
MONGODB_REPLICA_SET_MODE: primary
MONGODB_REPLICA_SET_NAME: ${MONGODB_REPLICA_SET_NAME:-rs0}
...
若使用 docker-compose
部署時沒有問題,但使用 podman-compose
部署時,便會發生 DNS 無法解析的問題,使得 rocketchat
無法連上 mongodb
。
podman-compose: https://github.com/containers/podman-compose
調查結果
- Docker 內建 DNS Server
經過調查,在 Docker
官方文件中可以得知在 docker-compose
中,DNS Server 是由 Docker daemon
所提供,而他的運作原理剛好在 COSCUP 2023 活動中,講者 hwchiu 有提到,有興趣的話可以參考他的演講:
Docker Network: https://docs.docker.com/network/
剖析 KIND(Kubernetes IN Docker) 的實作原理: https://www.slideshare.net/hongweiqiu/learned-from-kind
Containers that attach to a custom network use Docker's embedded DNS server. The embedded DNS server forwards external DNS lookups to the DNS servers configured on the host.
- Podman 需要 DNS Plugin
在 podman 中,因為沒有 Daemon 的關係,需要透過 Plugin 實現 DNS。官方文件中,有這麼一句話: Podman supports two network backends Netavark and CNI. Netavark is the default network backend and was added in Podman version 4.0. CNI is deprecated and will be removed in the next major Podman version 5.0, in preference of Netavark.
我們可以透過以下指令查看當前的 podman network backend:
podman info --format {{.Host.NetworkBackend}}
如果沒有 Plugin,cni
是無法使用 DNS 的功能,我們可以透過 podman network inspect
查看預設的網路設定:
- 安裝 Plugin
一開始我以為直接將 network backend 切換為 netavark
就好,因為從官方描述中,看起來像是內建在 podman 4.0 中,但切換後卻得到以下錯誤,這代表主機並沒有安裝此 Plugin:
可以透過 dnf
直接安裝 netavark
,並重新設定 podman 環境:
過去可以透過
dnf install -y podman-dnsname
安裝dnsname
Plugin,但此專案已經停止維護: https://github.com/containers/dnsname
dnf install -y netavark
- 重設 network backend
以下步驟參考 Oracle Linux 的 Podman User’s Guide,內容詳細介紹如何切換 network backend。根據 GitHub 上關於 Container 的 Common Library 的描述,Container Engine 預設使用 containers.conf
作為設定檔案,因此第一步先建立設定檔:
Podman Common: https://github.com/containers/common/blob/main/docs/containers.conf.5.md
cp /usr/share/containers/containers.conf /etc/containers/
修改 /etc/containers/containers.conf
,將 network_backend
改為 netavark
:
network_backend = "netavark"
初始化 Podman 設置:
podman system reset
- 驗證 network backend
再次執行查看指令,可以看到 network backend 已經改為 netavark
:
podman info --format {{.Host.NetworkBackend}}
也可以透過 ss
指令或 ps
指令查看,可以發現 netavark 使用 aardvark-dns
建立一個 dns server,並且佔用 53
port:
ss -tuanp
ps -ef | grep aardvark-dns
執行結果
修改完 Podman DNS 設定後,Rocket Chat
也成功執行了: