容器镜像不像酒,越陈越香;而是更像奶酪,越陈越臭.

Podman是Pod Manager的缩写。Podman解决了Docker一直存在的某些问题,其中最重要的两点是:

  1. Podman提供了增强的安全性
  2. 非root权限执行命令的能力

Pod是Kubernetes项目中普遍存在的一个概念,一个pod可以有一个或者多个容器,这些容器共享相同的命名空间和控制组。Podman项目组将Podman描述为“用于在Linux系统上开发、管理和运行OCI容器的无守护进程的容器引擎。容器既可以以特权模式运行,可以以非特权模式运行”。Podman的目标是可以在Linux上自然的运行容器,从而充分利用Linux平台的所有功能。

2025.02 山西·晋中·榆次

术语

容器

容器是在Linux系统上运行的一组进程.容器确保一个进程组不会干扰系统上的其他进程,恶意进程不能支配系统资源.容器通过以下方式进行隔离:

  1. 资源限制(cgroups)
    1. 一组进程可以使用的内存量
    2. 进程可使用的CPU核数
    3. 进程可使用的网络资源数量
  2. 安全限制
    1. 放弃Linux能力来限制root用户的权限
    2. 通过SELinux控制对文件系统的访问
    3. 只读访问内核文件系统
    4. 通过seccomp限制内核中可用的系统调用
    5. 通过用户命名空间将主机上的一组UID映射到另一组UID,从而允许访问有限特权环境
  3. 命名空间
    1. 网络命名空间
    2. 挂载命名空间
    3. PID命名空间

镜像

容器镜像通过将所有软件捆绑到一个单元中的方式,解决了依赖管理问题,可以将所有软件库\可执行文件和配置文件一并交付.

  1. 容器镜像格式

    1. 包含应用程序所需的所有软件的目录树
    2. 描述rootfs内容的JSON文件
    3. 被称为manifest列表的JSON文件,用于将多个镜像连接在一起以支持不同的硬件架构
  2. 容器运行方式

    1. 镜像使用Linux tar工具将rootfs和JSON文件打包在一起,然后上传到容器镜像注册服务器
    2. 容器引擎会将JSON文件\引擎内置默认值和用户输入合并来创建新的容器OCI运行时贵方的JSON文件
    3. 容器运行时读取容器的JSON文件\内核cgroups\安全约束和命名空间,并最终启动容器的主进程
  3. 容器标准

    1. OCI标准委员会
    2. OCI镜像格式
    3. OCI运行时规范

Podman

  1. 支持fork/exec模型,容器时命令的子进程
  2. 无守护进程,软件升级时不停止容器
  3. 支持kubernetes类pod和基于kubernetetes yaml启动容器
  4. 支持非特权容器
  5. 支持REST API
  6. 与systemd集成
  7. 自定义容器镜像注册服务器
  8. 支持多种传输方式
  9. 完全可定制

特权容器

1
2
3
4
5
6
7
8
9
10
11
12
# 关闭docker的安全限制,并挂载本地根目录
(base) [root@docker ~]# docker run -it --name hacker --privileged -v /:/host redhat/ubi8 chroot /host
Unable to find image 'redhat/ubi8:latest' locally
latest: Pulling from redhat/ubi8
c9235833a899: Pull complete
Digest: sha256:2e863fb65e595839633113300a0c6709e9af81523a30001290068265c121a927
Status: Downloaded newer image for redhat/ubi8:latest
sh-4.2# ls /
bin boot data dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
sh-4.2# cd /root
sh-4.2# ls
Anaconda3-2023.09-0-Linux-x86_64.sh

如果普通用户拥有docker的权限,就可以获得”为所欲为”的权限,删除容器就可以抹除所有操作记录.

基础命令

参见:Podman使用入门

Pod

Podman pod和Kubernetes pod一样,包含一个infra容器,或者被称为pause容器。该容器负责维持内核的命名空间和cgroups的状态,允许容器在pod内的创建与销毁。infra容器由一个名为conmon的容器监控进程来监控,而且pod中的每个容器都有属于自己的conmon。

  1. conmon负责执行OCI运行时,将OCI规范文件的路径和容器层挂载点
  2. conmon负责监控容器的生命周期
  3. conmon负责处理用户到容器的连接
  4. conmon负责生成pod的日志文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 创建一个空的pod,也就是一个网络命名空间,并将容器内部端口8080绑定到主机上的8080端口
$ mkdir html
$ podman pod create -p 8080:8080 --name mypod --volume ./html:/var/www/html:z
a086f23c67ae68ba79399d8dcb09217440e43f9079608607059bf8f929b97845
# 列出当前的pod
$ podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
a086f23c67ae mypod Created About a minute ago be5b8119c711 1
# 可见实际只有pause容器,并无业务容器,端口也已经映射
$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
be5b8119c711 localhost/podman-pause:5.3.1-1732147200 reated 0.0.0.0:8080->8080/tcp a086f23c67ae-infra
# 添加pod, Web程序的实际应用
$ podman create --pod mypod --name myapp ubi8/httpd-24
# 创建应用脚本
$ cat > ./html/time.sh <<EOF
#!/bin/bash
data() {
echo "<html><head></head><h1>"; date; echo "Hello World</h1></body></html>"
sleep 1
}
while true ; do
data > index.html
done
EOF
$ chmod +x ./html/time.sh
# 添加边车容器,将/var/www/html目录作为默认目录并运行打印时间戳脚本
$ podman create --pod mypod --name time --workdir /var/www/html ubi8 ./time.sh
# 启动pod
$ podman pod start mypod
# 列出pod
$ podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
c8a185241126 mypod Running 4 minutes ago b2e753fc5766 3
# 查看pod属性
$ podman pod inspect mypod
[
{
"Id": "c8a185241126ef5370ca62f32a2b87286dbc6fe29a6a1de6203f2cb790ffbb16",
"Name": "mypod",
"Created": "2025-02-05T21:18:04.411942531+08:00",
"CreateCommand": [
"podman",
"pod",
"create",
"-p",
"8080:8080",
"--name",
"mypod",
"--volume",
"/root/html:/var/www/html:z"
],
"ExitPolicy": "continue",
"State": "Running",
"Hostname": "",
"CreateCgroup": true,
……
# 检查
$ curl 192.168.24.10:8080
<html><head></head><h1>
Wed Feb 5 13:31:26 UTC 2025
Hello World</h1></body></html>
# 停止pod
$ podman pod stop mypod
# 删除pod
$ podman pod rm mypod

设计

自定义和配置文件

存储位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 配置文件位置
# root权限下系统podman配置存储文件位置
root@docker:~# podman info --format '{{ .Store.ConfigFile }}'
/usr/share/containers/storage.conf
# 普通用户配置存储文件位置
$ podman info --format '{{ .Store.ConfigFile }}'
/home/sujx/.config/containers/storage.conf

# 默认配置位置
root@docker:~# vim /usr/share/containers/storage.conf
[storage]
driver = "overlay"
runroot = "/run/containers/storage"
graphroot = "/var/lib/containers/storage"

通过修改graproot参数可以修改镜像和容器存储位置。Podman使用container/storage支持多种不同类型的分层文件,被称为写时复制(CoW)文件系统,Podman默认使用overlay驱动程序。

容器镜像注册服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 配置文件位置
root@docker:~# cat /etc/containers/registries.conf
# 镜像注册服务器数组,按顺序依次拉取镜像
unqualified-search-registries = ["registry.fedoraproject.org", "registry.access.redhat.com", "docker.io", "quay.io"]
# 配置docker hub代理,每个镜像注册服务器独立配置
[[registry]]
prefix="docker.io"
location="hub.1panel.dev"
# 允许未加密http连接
insecure=true
# 禁止镜像下载
blocked=true
# 允许使用短命称
short-name-mode = "enforcing"

引擎配置

1
2
# 引擎配置文件位置
root@podman:~# vim /usr/share/containers/containers.conf

container.conf支持以下配置项:

  1. [containers] 运行单个容器的配置
  2. [engine] Podman的默认配置
  3. [service_destinations] 远程服务配置
  4. [secrets] 有关secrets插件驱动程序信息
  5. [network] 网络特殊配置

系统配置

当你在非特权模式下运行Podman时,将使用 /etc/subuid和/etc/subgid 文件来制定容器的UID范围。Podman会读取这俩个文件以获取分配给你的用户账户UID和GID范围。然后Podma启动 /usr/bin/newuidmap 和 /usr/bin/newgidmap ,验证podman制定的UID和GID范围是否实际分配给你。某些情况下,需要手动修改这些文件以便添加UID。

与Systemd集成

Systemd是Linux事实上的init系统。Podman接受systemd的强大功能,Podman鼓励用户将systemd单元文件与Podman命令一起使用。

在容器中运行systemd

在容器中将systemd作为初始PID运行,然后允许systemd启动容器内的一个或多个服务。这种思路认为,容器化服务应该像在虚拟机中一样启动。这种方式允许在同一容器中运行多个服务,利用本地通信路径,加快将大型多服务应用程序转换为容器。另外,systemd在容器中的另一个巨大优势是init系统会处理僵尸程序的清理工作,这样当容器进程异常退出的适合,如果PID1不回收它们,它们就会悬挂并且永不消失。

Podman的设计旨在支持两种方法——微服务和多服务容器。Podman检查容器的cmd选项,然后为init系统启动systemd,接着它自动以systemd模式启动容器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[sujx@docker ~]$ podman pull ubi9-init
[sujx@docker ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.access.redhat.com/ubi9-init latest 2e10efedbde9 3 days ago 251 MB
# 容器内程序启动是由init启动
[sujx@docker ~]$ podman inspect ubi9-init --format '{{ .Config.Cmd }}'
[/sbin/init]
# 常规容器的启动
# 以nginx为例
[sujx@docker ~]$ podman inspect nginx --format '{{ .Config.Cmd }}'
[nginx -g daemon off;]
# 以ubuntu为例
[sujx@docker ~]$ podman inspect ubuntu --format '{{ .Config.Cmd }}'
[/bin/bash]

# 如果无参数启动systemd容器,可以看到容器启动后是先启动systemd
# 此时通过Ctrl-C是无法停止容器,只有通过其他终端来终止
[sujx@docker ~]$ podman run -ti ubi9-init
systemd 252-46.el9_5.2 running in system mode (+PAM +AUDIT +SELINUX -APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN -IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD -BPF_FRAMEWORK +XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified)
Detected virtualization container-other.
Detected architecture x86-64.

Welcome to Red Hat Enterprise Linux 9.5 (Plow)!

Initializing machine ID from container UUID.
Queued start job for default target Graphical Interface.
[ OK ] Created slice Slice /system/modprobe.
[ OK ] Started Dispatch Password Requests to Console Directory Watch.
[ OK ] Started Forward Password Requests to Wall Directory Watch.
[ OK ] Reached target Local File Systems.
[ OK ] Reached target Network is Online.
[ OK ] Reached target Path Units.
[ OK ] Reached target Remote File Systems.
[ OK ] Reached target Slice Units.
[ OK ] Reached target Swaps.

# podman通过systemd发生停止信号,杀死最近启动的容器
[sujx@docker ~]$ podman stop -l

容器化的systemd要求

  1. 在/run上挂载tmpfs
  2. 在/tmp上挂载tmpfs
  3. 将/var/log/journald作为tmpfs
  4. container环境变量
  5. STOPSIGNAL=SIGRTMIN+3 systemd接受这个信号才会彻底退出

systemd模式下的Podman容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 创建systemd容器,使用--systemd=always标志以systemd模式启动容器
[sujx@docker ~]$ podman create --rm --name SystemD -ti --systemd=always ubi9-init sh
592a5aaa4eeaedc901a38de957ff709d97e50ec8083e222ebeefbb11dba40120
# 停止参数
[sujx@docker ~]$ podman inspect SystemD --format '{{ .Config.StopSignal }}'
SIGRTMIN+3
# 查看tmpfs挂载
[sujx@docker ~]$ podman start --attach SystemD
sh-5.1# mount |grep -e /tmp -e /run | head -2
tmpfs on /run/secrets type tmpfs (rw,nosuid,nodev,relatime,size=394904k,nr_inodes=98726,mode=700,uid=1000,gid=1000,inode64)
tmpfs on /run/.containerenv type tmpfs (rw,nosuid,nodev,relatime,size=394904k,nr_inodes=98726,mode=700,uid=1000,gid=1000,inode64)
sh-5.1# printenv container
oci

# 创建一个httpd服务的容器Dockerfie
cat >> /home/sujx/podman/Containerfile<EOF
FROM ubi9-init
RUN dnf -y install httpd; dnf -y clean all
RUN systemctl enable --now httpd.service
EOF
# 生成容器
[sujx@docker ~]$ podman build -t my-systemd /home/sujx/podman
# 拉起服务
[sujx@docker ~]$ podman run -d --rm -p 8080:80 -v ./html/:/var/www/html:Z my-systemd
8746e0bf313a4d3c84535623393567f148d4c3d762ce5683b53c679dc9510308
[sujx@docker ~]$ curl localhost:8080
<h1>Goodbye Workd!</h1>

使用journald进行日志记录

1
2
3
4
5
6
7
8
9
# podman默认使用journald来记录日志
[sujx@docker ~]$ podman info --format '{{ .Host.LogDriver }}'
journald
# 输出事件
[sujx@docker ~]$ podman run --rm --name test2 ubi9 echo "Check if logs persist"
Check if logs persist
# 使用主机journalctl来查看容器日志
[sujx@docker ~]$ journalctl -b |grep "Check if logs persist"
Feb 20 21:54:37 docker test2[3249]: Check if logs persist

在系统启动时启动容器

重启容器

Podman通过在systemd单位文件中配置Podman的启动模式。如果容器崩溃或者系统重新启动,就可能需要配置相关参数。

选项 功能 启动时重启
no 容器退出时不重启容器 ×
on-failure 当容器以非零状态退出时重启 ×
always 容器退出时重启,无论其退出状态如何,重试次数无限
1
2
3
# 配置重启策略
[sujx@docker ~]$ podman run -d --restart=always --name Ubuntu ubuntu
cb7a068d99b56107db3afe0b1955d5f210964ae97cecd01e1e85205346b92810

使用Podman作为系统服务

common进程也在systemd服务中运行,用以监视容器进程。systemd不知道容器的存在,它只指导运行在单元文件中的进程,包括容器进程。

Podman具有生成包含最佳默认值的单位文件的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 创建容器
[sujx@docker ~]$ podman create -p 8080:80 --name my-Web nginx
24c372bff6a8cec5ce8f11eca604dd3d84987b17e6585f1d840bf10783991881
# 创建user权限的启动文件
[sujx@docker ~]$ mkdir -p $HOME/.config/systemd/user
[sujx@docker ~]$ podman generate systemd my-Web > $HOME/.config/systemd/user/my-Web.service
# 查看service单元文件
[sujx@docker ~]$ cat $HOME/.config/systemd/user/my-Web.service
[Unit]
Description=Podman container-684673ead27728b8946376cab1ebfc2472cf9f550bcefd1161934ce7d6acc125.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/run/user/1000/containers

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStart=/usr/bin/podman start 684673ead27728b8946376cab1ebfc2472cf9f550bcefd1161934ce7d6acc125
ExecStop=/usr/bin/podman stop \
-t 10 684673ead27728b8946376cab1ebfc2472cf9f550bcefd1161934ce7d6acc125
ExecStopPost=/usr/bin/podman stop \
-t 10 684673ead27728b8946376cab1ebfc2472cf9f550bcefd1161934ce7d6acc125
PIDFile=/run/user/1000/containers/overlay-containers/684673ead27728b8946376cab1ebfc2472cf9f550bcefd1161934ce7d6acc125/userdata/conmon.pid
Type=forking

[Install]
WantedBy=default.target

# 启动服务
[sujx@docker ~]$ systemctl --user daemon-reload
[sujx@docker ~]$ systemctl --user start my-Web.service
[sujx@docker ~]$ systemctl --user status my-Web.service
my-Web.service - Podman container-684673ead27728b8946376cab1ebfc2472cf9f550bcefd1161934ce7d6acc125.service
Loaded: loaded (/home/sujx/.config/systemd/user/my-Web.service; disabled; preset: disabled)
Drop-In: /usr/lib/systemd/user/service.d
└─10-timeout-abort.conf
Active: active (running) since Fri 2025-02-21 11:25:38 CST; 8s ago
Docs: man:podman-generate-systemd(1)
Process: 1460 ExecStart=/usr/bin/podman start 684673ead27728b8946376cab1ebfc2472cf9f550bcefd1161934ce7d6a>
Main PID: 1484 (conmon)
Tasks: 2 (limit: 4580)
Memory: 17.6M (peak: 32.9M)
CPU: 84ms
CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/my-Web.service
# 校验服务
[sujx@docker ~]$ curl localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
# 关闭服务
[sujx@docker ~]$ systemctl --user stop my-Web

分发systemctl单元文件

我们可以通过–new这个开关重新生成一个systemd单元文件,用于在其他系统中使用。这样服务在重启的时候,会拉取镜像和创建新的容器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 重新生成单元文件
[sujx@docker ~]$ podman generate systemd --new my-Web > $HOME/.config/systemd/user/my-Web.service
# 单元文件中容器的EexcStart命令修改为podman run,而不是原来的podman start
[sujx@docker user]$ cat my-Web.service
[Unit]
Description=Podman container-684673ead27728b8946376cab1ebfc2472cf9f550bcefd1161934ce7d6acc125.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStart=/usr/bin/podman run \
--cidfile=%t/%n.ctr-id \
--cgroups=no-conmon \
--rm \
--sdnotify=conmon \
-d \
--replace \
-p 8080:80 \
--name my-Web nginx
ExecStop=/usr/bin/podman stop \
--ignore -t 10 \
--cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm \
-f \
--ignore -t 10 \
--cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all

[Install]
WantedBy=default.target

自动更新容器

Podman可以管理自己的更新,每个节点会监视容器镜像注册服务器中是否出现新的镜像。当新的镜像出现时,节点会拉取镜像并重新创建容器。

这个功能的开启条件有两个:

  1. 容器必须在使用podman generate systemd –new 生成的systemd单元文件中运行
  2. 容器具有特殊的标签 –label “io.containers.autoupdate=registry/local”
1
2
3
4
5
6
7
8
9
10
11
# 创建带标签容器
[sujx@docker ~]$ podman create --label "io.container.autoupdate=regitstry" -p 8081:80 --name my-Http httpd
# 创建单元文件
[sujx@docker ~]$ podman generate systemd my-Http --new >> $HOME/.config/systemd/user/my-Http.service
# 启动服务
[sujx@docker ~]$ systemctl --user daemon-reload
[sujx@docker ~]$ systemctl --user enable --now my-Http.service
# 手动升级,自动拉取所有带标签的容器的新镜像并重启服务
[sujx@docker ~]$ podman autoupdate
# 定时更新,每天检查一次
[sujx@docker ~]$ systemctl --user enable --now podman-auto-update.service

Podman服务

Podman项目支持RESTful API,可以使用podman system service命令创建监听服务应用于响应Podman的API调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# 启动podman的restful API套接字服务
[sujx@docker ~]$ systemctl --user enable podman.socket
[sujx@docker ~]$ systemctl --user start podman.socket
[sujx@docker ~]$ ls $XDG_RUNTIME_DIR/podman/podman.sock
/run/user/1000/podman/podman.sock
# 使用curl探测podman的版本信息
[sujx@docker ~]$ curl -s --unix-socket $XDG_RUNTIME_DIR/podman/podman.sock http://d/v1.0.0/libpod/version |jq
{
"Platform": {
"Name": "linux/amd64/fedora-40"
},
"Components": [
{
"Name": "Podman Engine",
"Version": "5.3.1",
"Details": {
"APIVersion": "5.3.1",
"Arch": "amd64",
"BuildTime": "2024-11-21T08:00:00+08:00",
"Experimental": "false",
"GitCommit": "",
"GoVersion": "go1.22.7",
"KernelVersion": "6.12.15-100.fc40.x86_64",
"MinAPIVersion": "4.0.0",
"Os": "linux"
}
},
{
"Name": "Conmon",
"Version": "conmon version 2.1.12, commit: ",
"Details": {
"Package": "conmon-2.1.12-2.fc40.x86_64"
}
},
{
"Name": "OCI Runtime (crun)",
"Version": "crun version 1.19.1\ncommit: 3e32a70c93f5aa5fea69b50256cca7fd4aa23c80\nrundir: /run/user/1000/crun\nspec: 1.0.0\n+SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +CRIU +LIBKRUN +WASM:wasmedge +YAJL",
"Details": {
"Package": "crun-1.19.1-1.fc40.x86_64"
}
}
],
"Version": "5.3.1",
"ApiVersion": "1.41",
"MinAPIVersion": "1.24",
"GitCommit": "",
"GoVersion": "go1.22.7",
"Os": "linux",
"Arch": "amd64",
"KernelVersion": "6.12.15-100.fc40.x86_64",
"BuildTime": "2024-11-21T08:00:00+08:00"
}
# 使用curl连接podman的默认输出
# 查询本地镜像列表
[sujx@docker ~]$ curl -s --unix-socket $XDG_RUNTIME_DIR/podman/podman.sock http://d/v1.0.0/libpod/images/json |jq
[
{
"Id": "2e10efedbde980518ddeae0d6d42d6d503b1915e2b09edfe2d9ed93453ae4018",
"ParentId": "",
"RepoTags": [
"registry.access.redhat.com/ubi9-init:latest"
],
"RepoDigests": [
"registry.access.redhat.com/ubi9-init@sha256:c80641132b5ba47ce8d806f48405f78085c508f4e6db7d619d208d9752cf53b1",
"registry.access.redhat.com/ubi9-init@sha256:ea7611fcd37de2e2d1b79eac0255efa89eb1f7e82bfecf91739d56f9674f2fe2"
],
"Created": 1739777526,
"Size": 251470246,
"SharedSize": 0,
"VirtualSize": 251470246,

使用Python与Podman交互

我们可以是以哦那个docker-py与Podman服务进行交互

1
2
3
4
5
6
7
8
9
10
11
# 安装工具
[sujx@docker ~]$ dnf -y install podman-py
# 编辑python脚本,podman-py默认链接Podman套接字
[sujx@docker ~]$ cat >./image.py<<EOF
import podman
client=podman.PodmanClient()
print(client.images.list(all=True))
EOF
# 执行测试
[sujx@docker ~]$ python3 image.py
[<Image: 'registry.access.redhat.com/ubi9-init:latest'>, <Image: 'docker.io/library/nginx:latest'>, <Image: 'docker.io/library/ubuntu:latest'>, <Image: 'docker.io/library/httpd:latest'>, <Image: 'docker.io/library/busybox:latest'>]

参考

  1. 了解容器内部和外部的 root
  2. 无根容器的背后发生了什么
  3. 弄懂什么是REST API