目錄

用 Distribution 建立 TLS 容器倉庫

遇過非常多人使用 Distribution 和 RHEL 來建立人生第一個容器映像檔倉庫 (Container Registry) 時,都會遇到 SSL/TLS 相關的問題,大多都是用 insecure-registries 來避掉,今天要來分享自簽憑證的作法

系統規格

  • Hostname: registry.lab.test
  • IP: 10.0.100.7/24
  • Necessary Software
    • Distribution 3.1.2,使用官方容器映像
    • RHEL 9 / 10
    • Podman、OpenSSL 3、Skopeo,使用對應 RHEL 套件庫提供的版本

安裝過程

準備 OS

  • Firewalld 開啟、SELinux 保持 Enforcing
  • 以 RHEL 9/10 為核心,已配置有效的 BaseOS、AppStream 套件庫
  • 以下指令以 root 執行,使用 rootful Podman;RHEL 9/10 可使用相同指令,但套件版本與預設設定可能不同
  • 伺服器與客戶端均需透過 DNS 或 /etc/hosts 將 registry.lab.test 解析到 10.0.100.7

Docker Distribution

安裝 Distribution

1
2
3
dnf install -y podman openssl firewalld ca-certificates
install -d -m 0750 /etc/distribution/certs /var/lib/registry
podman pull docker.io/library/registry:3.1.2

RHEL 9/10 使用 Podman 執行官方映像,設定與憑證統一放在 /etc/distribution。

設定 Distribution

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
cat << 'EOF' > /etc/distribution/config.yml
---
version: 0.1
log:
  fields:
    service: registry
storage:
    cache:
        blobdescriptor: inmemory
    filesystem:
        rootdirectory: /var/lib/registry
http:
    addr: 0.0.0.0:5000
    host: https://registry.lab.test:5000
    tls:
      certificate: /etc/distribution/certs/registry.crt
      key: /etc/distribution/certs/registry.key
EOF

依據上述的設定檔,/var/lib/registry 是指定主要放置 Container Images 檔案的位置,後面會掛載主機的同一路徑;:5000 開的 Port 預設是 5000,但可以依據需求修改;certificate、key 則是放置 SSL/TLS 的憑證和金鑰,後面會講怎麼快速自簽;若想要瞭解更多的設定檔,可以參考 Distribution - Configuring a registry

自簽 OpenSSL

1
2
3
4
5
6
7
umask 077
openssl req -x509 -noenc -sha256 -days 365 -newkey rsa:2048 \
  -keyout /etc/distribution/certs/registry.key \
  -out /etc/distribution/certs/registry.crt \
  -subj "/CN=registry.lab.test" \
  -addext "subjectAltName=DNS:registry.lab.test,IP:10.0.100.7"
chmod 0600 /etc/distribution/certs/registry.key

注意 subjectAltName 務必要填自己的 hostname;若要透過 IP 存取,也要填入對應的 IP。現代客戶端不能只靠 Common Name 驗證 hostname。RHEL 9/10 的 OpenSSL 3 可使用 -noenc 和 -addext,不需要互動式填寫憑證欄位。

在 RHEL 匯入自簽憑證:

1
2
3
4
5
openssl x509 \
  -in /etc/distribution/certs/registry.crt \
  -out /etc/pki/ca-trust/source/anchors/workstation.pem \
  -outform PEM
update-ca-trust

建議把 /etc/distribution/certs/registry.crt 透過可信管道提供給其他機器,未來只要有需要用到該 Container Registry 的 RHEL 客戶端,都要執行上面的動作匯入憑證,並將 -in 改成該機器實際存放憑證的位置;不要提供 .key 私鑰檔案。

啟動 Distribution

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
podman run -d --name registry --restart=always \
  --publish 10.0.100.7:5000:5000 \
  --volume /etc/distribution:/etc/distribution:ro,Z \
  --volume /var/lib/registry:/var/lib/registry:Z \
  --env OTEL_TRACES_EXPORTER=none \
  docker.io/library/registry:3.1.2 \
  serve /etc/distribution/config.yml

systemctl enable podman-restart.service
podman logs registry

:Z 會設定容器需要的 SELinux 標籤,:ro 將設定和憑證目錄設為唯讀。podman-restart.service 用來在主機開機後恢復這個 rootful 容器;修改設定或憑證後,執行 podman restart registry。

此範例只設定 TLS,不含登入驗證,僅供受控網路測試。

啟用 Firewall

先用 firewall-cmd --get-active-zones 確認網卡所屬區域;以下以 public 為例,請依環境調整:

1
2
3
4
5
6
systemctl enable --now firewalld
firewall-cmd --get-active-zones
firewall-cmd --zone=public --add-port=5000/tcp --permanent
firewall-cmd --reload
podman network reload registry
firewall-cmd --zone=public --list-all

驗證 Container Registry

1
2
3
4
5
6
7
dnf install -y skopeo

skopeo copy --all \
  docker://docker.io/library/alpine:3.24.3 \
  docker://registry.lab.test:5000/library/alpine:3.24.3

skopeo inspect docker://registry.lab.test:5000/library/alpine:3.24.3

--all 會一併複製多平台映像;測試映像改用 Alpine,避免沿用已停止維護的 CentOS 7。

結語

整個過程其實蠻簡單的,大概不用半小時就可以建立完,但他能提供的功能,就是非常基本中的基本 - 放映像檔,若要尋求多功能的 Container Registry,可以考慮使用紅帽宣布 Red Hat Introduces open source Project Quay container registry 的 Project Quay,比較符合現實生活。

References