Podman 作為新一代容器引擎,以其無守護行程的架構和安全性優勢,逐漸受到開發者的青睞。然而,許多開發者已習慣使用 Docker Compose 管理多容器應用程式。因此,如何在 Podman 環境中有效利用 Docker Compose 成為一個關鍵議題。本文將詳細介紹如何在 Podman 中使用 Docker Compose,包含組態解析、命令操作、以及 systemd 和 Kubernetes 的整合,協助開發者無縫遷移並提升容器化應用程式的管理效率。
使用 Podman 與 Docker Compose 的整合
在容器化的世界中,Podman 逐漸成為 Docker 的一個有力替代方案,尤其是在無守護程式(daemonless)的架構下提供了更高的安全性和靈活性。然而,對於許多已經習慣使用 Docker Compose 的開發者來說,如何在 Podman 中使用 Docker Compose 成為一個重要的議題。本篇文章將探討 Podman 與 Docker Compose 的整合使用方法,並提供實用的範例與技巧。
Podman 中缺少的 Docker 命令
在轉移到 Podman 的過程中,瞭解兩者之間的命令差異是非常重要的。以下是一些 Docker 中存在但 Podman 中尚未支援的命令:
儘管 Podman 缺少了一些 Docker 命令,但它也引入了一些 Docker 中沒有的新命令,例如 podman generate、podman healthcheck 和 podman machine 等。這些新命令為容器管理和排程提供了更多的靈活性。
Docker Compose 簡介
Docker Compose 是一個強大的工具,用於定義和執行多容器的 Docker 應用程式。它使用 YAML 檔案來組態應用程式的服務,從而簡化了複雜應用程式的佈署和管理。
Docker Compose 快速入門
一個典型的 docker-compose.yaml 檔案定義了多個服務及其相關的卷和網路。以下是一個簡單的範例,展示瞭如何使用 Docker Compose 執行一個 Docker Registry:
services:
registry:
ports:
- "5000:5000"
volumes:
- registry_volume:/var/lib/registry
image: docker.io/library/registry
volumes:
registry_volume: {}
內容解密:
- services: 定義了組成應用程式的服務。在這個範例中,只有一個名為
registry的服務。 - ports: 將主機的 5000 埠對映到容器內的 5000 埠,使得外部可以存取 Registry 服務。
- volumes: 定義了一個名為
registry_volume的卷,用於持久化儲存 Registry 的資料。 - image: 指定了要使用的 Docker 映象。在這個例子中,使用的是官方的 Registry 映象。
另一個更複雜的例子是 WordPress 與 MySQL 的組合:
services:
db:
image: docker.io/library/mysql:latest
command: '--default-authentication-plugin=mysql_native_password'
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: wordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: docker.io/library/wordpress:latest
ports:
- "80:80"
restart: always
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
volumes:
db_data: {}
內容解密:
- db 服務: 使用 MySQL 映象,並設定了必要的環境變數來初始化資料函式庫。
- wordpress 服務: 依賴於
db服務,使用 WordPress 映象,並將主機的 80 埠對映到容器的 80 埠。 - depends_on: 表示
wordpress服務依賴於db服務,確保資料函式庫服務在 WordPress 啟動前已經準備就緒。
在 Podman 中使用 Docker Compose
隨著 Podman v3.0 的發布,Podman 開始原生支援 Docker Compose。這意味著使用者可以直接使用 podman-compose 命令來執行和管理原本為 Docker Compose 組態的應用程式。
使用 podman-compose 的好處包括:
- 無需守護程式: 繼承了 Podman 的無守護程式架構,提高了安全性和降低了資源消耗。
- 相容性: 可以直接使用現有的
docker-compose.yaml檔案,無需進行修改。
使用 Docker Compose 與 Podman 的技術
Docker Compose 基本概念與組態解析
Docker Compose 是一種用於定義和執行多容器 Docker 應用程式的工具。透過一個 YAML 檔案來組態應用程式的服務、網路和磁碟區,從而簡化了多容器應用的佈署和管理。
示例解析:WordPress 與 MySQL 服務組態
以下是一個典型的 docker-compose.yaml 檔案,用於啟動 WordPress 和 MySQL 服務:
version: '3'
services:
db:
image: docker.io/library/mysql:latest
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=wordpressroot
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=wordpress
expose:
- 3306
- 33060
wordpress:
image: docker.io/library/wordpress:latest
ports:
- 8080:80
restart: always
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress
- WORDPRESS_DB_NAME=wordpress
volumes:
db_data:
組態項解析
在上述組態中,主要包含兩個服務:db 和 wordpress。
image:指定服務使用的 Docker 映象。volumes:定義掛載到容器中的磁碟區。restart:設定容器的重啟策略。environment:設定傳遞給容器的環境變數。expose和ports:分別用於暴露容器埠和對映容器埠到主機埠。
內容解密:
image屬性:指定了服務所使用的 Docker 映象,例如 MySQL 和 WordPress。在此例中,使用了 Docker Hub 上的官方最新版本映象。volumes組態:將主機上的db_data磁碟區掛載到 MySQL 容器的/var/lib/mysql目錄,用於持久化資料儲存。environment環境變數:為容器設定了必要的環境變數,例如 MySQL 的 root 密碼、資料函式庫名稱、使用者名稱和密碼,以及 WordPress 連線資料函式庫所需的引數。expose和ports:expose用於暴露容器的埠,而ports將容器內的埠對映到主機的埠,使得外部可以存取這些服務。
建置與執行 Docker Compose 應用程式
要啟動由 Docker Compose 管理的應用程式,可以使用以下命令:
$ docker-compose up
此命令會建立所有定義在 docker-compose.yaml 中的服務和相關磁碟區,並將輸出列印到標準輸出。
常見操作命令
後台執行:使用
-d選項讓應用程式在後台執行。
$ docker-compose up -d
* **建置並啟動**:使用 `--build` 選項重新建置映像並啟動服務。
```bash
$ docker-compose up --build
停止服務:使用
down命令停止並移除容器、網路和相關資源。
$ docker-compose down
### 組態 Podman 以支援 Docker Compose
Podman 需要透過本地 UNIX socket 公開其 REST API 服務,以支援 Docker Compose。以下是組態步驟:
1. **安裝必要套件**:在 Fedora 系統上安裝 `docker-compose` 和 `podman-docker`。
```bash
$ sudo dnf install docker-compose podman-docker
啟動 Podman socket 服務:啟用並啟動
podman.socketsystemd 單元。
$ sudo systemctl enable –now podman.socket
#### 安全注意事項
* Podman 的 UNIX socket 預設僅允許具有 root 許可權的程式存取。可以透過調整檔案許可權或設定自訂 ACLs 以放寬限制。
## 使用 Podman 與 docker-compose 執行 Compose 工作負載
為了幫助讀者學習如何操作 `docker-compose` 並在主機上建立協調的多容器佈署,我們將重用先前範例中的 Go REST API 與 Redis 記憶體儲存。
### 檢查 Dockerfile
首先,讓我們檢查用於建置應用程式的 Dockerfile:
```dockerfile
FROM docker.io/library/golang AS builder
# 複製檔案進行建置
RUN mkdir -p /go/src/golang-redis
COPY go.mod main.go /go/src/golang-redis
# 設定工作目錄
WORKDIR /go/src/golang-redis
# 下載依賴項
RUN go get -d -v ./...
# 安裝套件
RUN go build -v
# 執行階段映像
FROM registry.access.redhat.com/ubi8/ubi-minimal:latest as bin
COPY --from=builder /go/src/golang-redis/golang-redis /usr/local/bin
COPY entrypoint.sh /
EXPOSE 8080
ENTRYPOINT ["/entrypoint.sh"]
內容解密:
- 多階段建置:Dockerfile 使用多階段建置,先在
golang映像中編譯 Go 應用程式,然後將編譯好的二進位制檔案複製到ubi-minimal映像中,以減小最終映像的大小。 - 依賴項下載:使用
go get命令下載依賴項,確保應用程式所需的套件都已安裝。 - 暴露埠:使用
EXPOSE指令暴露 8080 埠,供外部存取。 - 入口點:使用
ENTRYPOINT指令設定容器啟動時執行的命令,這裡是執行entrypoint.sh指令碼。
建置與執行應用程式
要建置和執行應用程式,需要切換到專案目錄並執行 docker-compose up 命令:
# cd Chapter13/golang-redis
# docker-compose up --build -d
輸出結果顯示 docker-compose 建立了兩個容器,分別是 golang-redis_redis_1 和 golang-redis_web_1。
檢查執行中的容器
使用 podman ps 命令檢查執行中的容器:
# podman ps
結果顯示兩個容器正在執行,且 golang-redis_web_1 容器的 8080 埠已對映到主機的 8080 埠。
網路設定
當建立 Compose 堆積疊時,Podman 會建立一個新的網路,名稱遵循 <project_name>_default 的模式。這個網路使用 dnsname 外掛程式來例項化一個 dnsmasq 程式,並將容器的 IP 解析為服務名稱。
# podman network ls | grep golang-redis
結果顯示網路名稱為 golang-redis_default。
DNS 解析
dnsmasq 服務可以將服務名稱解析為容器的 IP 地址。在 /run/containers/cni/dnsname/golang-redis_default/addnhosts 檔案中,可以找到服務名稱與容器 IP 地址的對映關係:
# cat /run/containers/cni/dnsname/golang-redis_default/addnhosts
結果顯示 golang-redis_redis_1 的 IP 地址為 10.89.3.240,而 golang-redis_web_1 的 IP 地址為 10.89.3.241。
環境變數
在 docker-compose.yaml 檔案中,web 服務的環境變數部分定義了 REDIS_HOST=redis。這個變數被注入到執行中的容器中,用於建立與 Redis 的連線字串。
# docker-compose exec web env
結果顯示 REDIS_HOST 環境變數已正確注入到容器中。
從 Docker 遷移到 Podman:與 systemd 和 Kubernetes 互動
在前面的章節中,我們學習瞭如何初始化和管理容器,從簡單的概念到進階的操作。容器技術在最新的 Linux 作業系統版本中代表著應用程式開發的關鍵技術。因此,對於進階開發者和系統管理員來說,容器只是起點。一旦企業或技術專案廣泛採用這項技術,下一步就是將其與基礎作業系統和系統協調平台整合。
在本章中,我們將涵蓋以下主要主題:
- 設定主機作業系統的先決條件
- 建立 systemd 單元檔案
- 管理根據容器的 systemd 服務
- 生成 Kubernetes YAML 資源
- 在 Podman 中執行 Kubernetes 資源檔案
- 在 Kubernetes 中測試結果
使用 Docker Compose 與 Podman
使用 podman-compose
podman-compose 專案在 Podman 3.0 版本之前就已經開始,為需要使用 Compose 檔案來協調容器的使用者提供相容性層。在本小節中,我們將在 Fedora 上使用 podman-compose 的範例進行探討。
podman-compose 工具的 CLI 是用 Python 編寫的。該套件可以透過 dnf 安裝,或者從 GitHub 儲存函式庫取得最新版本:
$ sudo dnf install -y podman-compose
或者,可以使用 Python 的套件管理器 pip3 進行安裝,支援更廣泛的作業系統和發行版:
$ pip3 install podman-compose
現在,我們可以使用 podman-compose 執行與之前範例相同的 Compose 堆積疊,並且享有 Podman 提供的無根(rootless)方法。
以下是所有與 docker-compose 相容的可用命令,以及它們的描述和一些由 podman-compose help 命令輸出的次要變更:
help:顯示工具的幫助資訊version:顯示命令的版本pull:提取堆積疊映像push:推播堆積疊映像build:建立堆積疊映像up:建立並啟動整個堆積疊或部分服務down:拆除整個堆積疊ps:顯示執行中的容器狀態run:建立一個類別似服務的容器來執行一次性命令exec:在執行中的容器中執行特定命令start:啟動特定服務stop:停止特定服務restart:重新啟動特定服務logs:顯示服務的日誌
內容解密:
podman-compose up命令的作用:該命令會根據docker-compose.yaml檔案建立並啟動整個堆積疊或指定的服務。它會讀取設定檔中的服務定義,並根據這些定義建立和啟動容器。podman-compose down命令的作用:該命令會停止並刪除由podman-compose up命令建立的容器和相關資源,但不會刪除資料卷(volumes)。如果需要刪除資料卷,需要額外指定-v選項。podman-compose的優勢:提供了一個與docker-compose相容的工具,使得使用者可以無縫地從 Docker 切換到 Podman,並且支援無根容器。
進一步閱讀
要了解更多關於本章涵蓋的主題,請參考以下資源:
- Docker Awesome Compose:https://github.com/docker/awesome-compose
- GitHub 上的 Podman-compose 專案:https://github.com/containers/podman-compose
- Red Hat 部落格介紹 Podman 中的 Docker Compose 支援:https://www.redhat.com/sysadmin/podman-docker-compose
- Twelve-Factor App:https://12factor.net/
- Podman 手冊頁面:https://github.com/containers/podman/blob/main/docs/source/markdown/podman.1.md
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Podman 整合 Docker Compose 技術
package "Kubernetes Cluster" {
package "Control Plane" {
component [API Server] as api
component [Controller Manager] as cm
component [Scheduler] as sched
database [etcd] as etcd
}
package "Worker Nodes" {
component [Kubelet] as kubelet
component [Kube-proxy] as proxy
package "Pods" {
component [Container 1] as c1
component [Container 2] as c2
}
}
}
api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2
note right of api
核心 API 入口
所有操作經由此處
end note
@enduml此圖示說明瞭使用 podman-compose 建立和刪除堆積疊的基本流程。
- 流程起始:流程從
podman-compose up命令開始,該命令負責根據設定檔建立並啟動整個堆積疊或指定的服務。 - 建立並啟動堆積疊:一旦執行
podman-compose up,系統會根據docker-compose.yaml檔案中的定義建立並啟動容器。 - 停止並刪除堆積疊:當需要停止並刪除堆積疊時,使用者可以執行
podman-compose down命令,該命令會停止並刪除先前建立的容器及其相關資源。
這個流程展示瞭如何使用 podman-compose 管理容器的生命週期,從建立到刪除,確保了操作的便捷性和一致性。