Podman是一个开源的容器运行时项目,提供与Docker相似的功能,可以管理和运行任何符合OCI规范的容器和镜像。Podman提供了一个与Docker兼容的命令行前端来管理容器镜像。其主要的优点有:

  1. 无根模式运行,没有任何额外特权需要;
  2. 不需要守护进程
  3. 原生systemd集成,允许用户创建systemd单元文件并将容器作为系统服务运行。

2024.11 天津·和平区·解放北路·利顺德大酒店

初始安装

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
# 部署
[root@podman ~]# dnf install -y podman podman-docker podman-compose
touch /etc/containers/nodocker
[root@podman ~]# podman -v
podman version 5.3.1
# 配置镜像代理
[root@podman ~]# vim /etc/containers/registries.conf
unqualified-search-registries = ["docker.io"]
[[registry]]
prefix="docker.io"
location="docker.1ms.run"
# 重启服务
[root@podman ~]# systemctl enable podman
[root@podman ~]# systemctl restart podman
# 拉取镜像
[root@podman ~]# podman run hello-world
!... Hello Podman World ...!

.--"--.
/ - - \
/ (O) (O) \
~~~| -=(,Y,)=- |
.---. /` \ |~~
~/ o o \~~~~.----. ~~
| =(X)= |~ / (O (O) \
~~~~~~~ ~| =(Y_)=- |
~~~~ ~~~| U |~~

Project: https://github.com/containers/podman
Website: https://podman.io
Desktop: https://podman-desktop.io
Documents: https://docs.podman.io
YouTube: https://youtube.com/@Podman
X/Twitter: @Podman_io
Mastodon: @Podman_io@fosstodon.org

使用管理

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# 交互式运行容器
[root@podman ~]# podman run -it ubuntu /bin/bash
root@b6089f227b55:/#

# 容器后台运行
[root@podman ~]# podman run -itd --name ubuntu_test ubuntu /bin/bash
36811becd0b716687bc8e5ab0c6c29cd64ee159ceac1d2f7b7a685e69f7b7ea1
[root@podman ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
36811becd0b7 docker.io/library/ubuntu:latest /bin/bash 11 seconds ago Up 12 seconds ubuntu_test

# 使用容器ID进入容器
[root@podman ~]# podman exec -it 368 /bin/bash
root@36811becd0b7:/#

# 启动容器
[root@podman ~]# podman start ubuntu_test
ubuntu_test
# 停止容器
[root@podman ~]# podman stop ubuntu_test
WARN[0010] StopSignal SIGTERM failed to stop container ubuntu_test in 10 seconds, resorting to SIGKILL
ubuntu_test
# 重启容器
[root@podman ~]# podman restart ubuntu_test
ubuntu_test
# 删除容器
[root@podman ~]# podman rm -f ubuntu_test
WARN[0010] StopSignal SIGTERM failed to stop container ubuntu_test in 10 seconds, resorting to SIGKILL
ubuntu_test
# 删除所有容器
[root@podman ~]# podman rm -f $(podman ps -aq)
b6089f227b55
155c6d4d9fae
115938151fc0
1395177f65e0
c1f9a18de6bd

# 查看pod属性
[root@podman ~]# podman inspect ubuntu_test
[
{
"Id": "98f6fb407b3cf7d3c4094ead7df7a3e1b45151bd88b2ff0df48e065476a8286c",
"Created": "2025-01-15T21:11:54.305532006+08:00",
"Path": "/bin/bash",
"Args": [
"/bin/bash"
],
"State": {
"OciVersion": "1.2.0",
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 5638,
"ConmonPid": 5636,
"ExitCode": 0,
"Error": "",
"StartedAt": "2025-01-15T21:11:54.565491536+08:00",
"FinishedAt": "0001-01-01T00:00:00Z",
"CgroupPath": "/machine.slice/libpod-98f6fb407b3cf7d3c4094ead7df7a3e1b45151bd88b2ff0df48e065476a8286c.scope",
"CheckpointedAt": "0001-01-01T00:00:00Z",
"RestoredAt": "0001-01-01T00:00:00Z"
},
"Image": "b1d9df8ab81559494794e522b380878cf9ba82d4c1fb67293bcf931c3aa69ae4",
"ImageDigest": "sha256:80dd3c3b9c6cecb9f1667e9290b3bc61b78c2678c02cbdae5f0fea92cc6734ab",
"ImageName": "docker.io/library/ubuntu:latest",
"Rootfs": "",
"Pod": "",

# 从宿主机向容器复制文件
[root@podman ~]# cat helloworld.txt
Hello World!
[root@podman ~]# podman cp helloworld.txt ubuntu_test:/home
[root@podman ~]# podman exec -it ubuntu_test /bin/bash
root@98f6fb407b3c:/# cd /home/
root@98f6fb407b3c:/home# ls
helloworld.txt ubuntu
root@98f6fb407b3c:/home# cat helloworld.txt
Hello World!

# 从容器向宿主机复制文件
root@98f6fb407b3c:/home# mv helloworld.txt OneWorld.txt
[root@podman ~]# podman cp ubuntu_test:/home/OneWorld.txt /tmp
[root@podman ~]# cat /tmp/OneWorld.txt
Hello World!

# 资源限制,限制使用1核cpu,2GB内存
podman run --cpus=1 -m=2g --name nginx -d docker.io/library/nginx
Trying to pull docker.io/library/nginx:latest...

[root@podman ~]# podman stats
ID NAME CPU % MEM USAGE / LIMIT MEM % NET IO BLOCK IO PIDS CPU TIME AVG CPU %
070a8c63fb69 nginx 0.00% 1.884MB / 2.147GB 0.09% 1.726kB / 838B 8.192kB / 20.48kB 2 15.93ms 0.02%

镜像管理

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
# 拉取镜像
[root@podman ~]# podman pull node:22-alpine

# 查看已有镜像
[root@podman ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/node 22-alpine 546c0b137912 10 days ago 161 MB
docker.io/library/nginx latest 9bea9f2796e2 7 weeks ago 196 MB
docker.io/library/ubuntu latest b1d9df8ab815 8 weeks ago 80.6 MB
docker.io/library/busybox latest af4709625109 3 months ago 4.52 MB
docker.io/traefik/whoami latest aeef15490f2b 4 months ago 7.01 MB
quay.io/podman/hello latest 5dd467fce50b 7 months ago 787 kB

# 删除镜像
[root@podman ~]# podman rmi 5dd
Untagged: quay.io/podman/hello:latest
Deleted: 5dd467fce50b56951185da365b5feee75409968cbab5767b9b59e325fb2ecbc0

# 生成镜像
[root@podman ~]# podman run -it ubuntu:24.04
Resolved "ubuntu" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/ubuntu:24.04...
Getting image source signatures
Copying blob de44b265507a skipped: already exists
Copying config b1d9df8ab8 done |
Writing manifest to image destination
root@3f5c2dbde6c0:/# apt update && apt upgrade -y && apt install vim
root@3f5c2dbde6c0:/# exit

# podman不支持-m参数
[root@podman ~]# podman commit -a "sujx@live.cn" 3f5c2 ubuntu:24.04.1
Getting image source signatures
Copying blob 687d50f2f6a6 skipped: already exists
Copying blob 01b59003fab2 done |
Copying config 4c10e10b43 done |
Writing manifest to image destination
4c10e10b437b46c62f3175097dce553d01ef3b9ec4a390c68da35b93a2e42b44

[root@podman ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/ubuntu 24.04.1 4c10e10b437b 21 seconds ago 199 MB

自定义镜像

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
# 创建Podmanfile
[root@podman ~]# cat > ./Podmanfile <<EOF
FROM node:22-alpine
MAINTAINER sujx@live.cn
EXPOSE 4000

RUN npm config set registry https://registry.npmmirror.com \
&& npm install -g hexo-cli --save \
&& mkdir /opt/blog \
&& cd /opt \
&& hexo init blog \
&& cd /opt/blog \
&& npm install hexo-renderer-pug hexo-renderer-stylus --save \
&& npm install hexo-wordcount --save \
&& npm install hexo-douban --save \
&& npm install hexo-generator-sitemap --save \
&& npm install hexo-generator-feed --save \
&& npm install hexo-generator-baidu-sitemap --save\
&& npm install hexo-generator-searchdb --save \
&& npm install hexo-theme-butterfly --save \
&& npm install hexo-butterfly-extjs --save \
&& npm install hexo-butterfly-tag-plugins-plus --save \
&& npm install hexo-pdf --save \
&& npm install hexo-deployer-git --save \
&& npm install hexo-deployer-ali-oss --save \
&& npm uninstall hexo-generator-index --save \
&& npm install hexo-generator-index-pin-top --save \
&& npm install hexo-asset-image --save

CMD cd /opt/blog && hexo clean && hexo g && hexo server
EOF

[root@podman ~]# podman build -f Podmanfile -t hexo:v1
[root@podman ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/hexo v1 5a535420cf24 6 minutes ago 962 MB

容器网络

端口暴露

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
# 端口暴露
[root@podman ~]# podman run -itd --name busybox-test -p80 busybox
b02b05b1881f8aa0cbca93f905a6559729e0a5c0e3be69adae2877d146579143
[root@podman ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b02b05b1881f docker.io/library/busybox:latest sh 5 seconds ago Up 6 seconds 0.0.0.0:38171->80/tcp busybox-test
[root@podman ~]# podman exec -it b02 /bin/sh
/ # cd /var/
/var # ls
spool www
/var # httpd -h www
/var # netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 :::80 :::* LISTEN 5/httpd

# 端口映射,把容器的端口映射为宿主机的一个特定或者随机端口,使得外部用户可以访问服务器内部服务,其原理是在容器底层做了iptables的地址转发,转出的流量做SNAT源地址转发,转入的流量做DNAT目标地址转发。

# 指定端口转发
[root@podman ~]# podman run -itd --name myipaddr -p 80:80 traefik/whoami
bbcc67b5fb1ce98b51335755c13498e87ace3da420b5a430001738cb27768e28
[root@podman ~]# curl 127.0.0.1
Hostname: bbcc67b5fb1c
IP: 127.0.0.1
IP: ::1
IP: 10.88.0.5
IP: fe80::c79:daff:fe48:4cb8
RemoteAddr: 10.88.0.1:55560
GET / HTTP/1.1
Host: 127.0.0.1
User-Agent: curl/8.6.0
Accept: */*

网络架构

Podman的网络架构有4种模式:

  1. 桥接模式(默认)
  2. non模式(仅本地回环)
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
# 桥接模式(默认)
[root@podman ~]# podman inspect myipaddr |grep IPAdd*
"IPAddress": "10.88.0.5",
"IPAddress": "10.88.0.5",

# none模式(仅本地回环)
[root@podman ~]# podman run -d --name=network-none --net=none nginx
539143ba161c73617ac1fd15e74a599753a71ce9658326bc5b8ebacaae114b86
[root@podman ~]# podman inspect 539143 |grep IPAdd*
"IPAddress": "",
"IPAddress": "",

# host模式,容器使用当前主机IP
root@podman ~]# podman run --network=host nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/01/18 16:47:15 [notice] 1#1: using the "epoll" event method
2025/01/18 16:47:15 [notice] 1#1: nginx/1.27.3
2025/01/18 16:47:15 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14)
2025/01/18 16:47:15 [notice] 1#1: OS: Linux 6.12.9-100.fc40.x86_64
2025/01/18 16:47:15 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2025/01/18 16:47:15 [notice] 1#1: start worker processes
2025/01/18 16:47:15 [notice] 1#1: start worker process 24
127.0.0.1 - - [18/Jan/2025:16:47:22 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.6.0" "-"

# container:<id>模式,容器之间共享Network Namespace,荣期间进程通过lo网卡通信
[root@podman ~]# podman run -itd --name bb busybox
365cf25286131e596f3aef54c43fed1b83e5be5ecc5f18e4de98242812f4002d
[root@podman ~]# podman run -d --name nginx --network=container:bb nginx
1287874746dcc6f72158b8fdb1ddf07ba13bdda06bd5a04bfdecaf86426fb927
[root@podman ~]# podman exec -it bb /bin/sh
[root@podman ~]# curl 10.88.0.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

网络实现

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
# 查看网络模式,可以看到名为podman的网桥
[root@podman ~]# podman network ls
NETWORK ID NAME DRIVER
2f259bab93aa podman bridge
# 查看podman网桥信息
[root@podman ~]# ip a
……
5: podman0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether ca:2c:2d:8d:b8:21 brd ff:ff:ff:ff:ff:ff
inet 10.88.0.1/16 brd 10.88.255.255 scope global podman0
valid_lft forever preferred_lft forever
inet6 fe80::c82c:2dff:fe8d:b821/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
6: veth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master podman0 state UP group default qlen 1000
link/ether fa:55:23:21:f6:c3 brd ff:ff:ff:ff:ff:ff link-netns netns-0e73c46a-0951-048b-fbc8-5e25f3d52e72
inet6 fe80::18b5:62ff:fec9:3476/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
# 查看NAT规则
[root@podman ~]# iptables -L -t nat

Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
NETAVARK-HOSTPORT-MASQ all -- anywhere anywhere
NETAVARK-1D8721804F16F all -- 10.88.0.0/16 anywhere

Chain NETAVARK-1D8721804F16F (1 references)
target prot opt source destination
ACCEPT all -- anywhere 10.88.0.0/16
MASQUERADE all -- anywhere !base-address.mcast.net/4

本地存储

存储卷

1
2
# 将本地web文件夹挂载到容器中,使用本地文件进行存储
podman run -itd -v /root/web:/var/www/html -p 8080:80 httpd

存储容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 通过创建多个容器,使用容器来存储数据
[root@podman ~]# podman run -itd --name db_data -v /db_data ubuntu
8e48de5ce3d36803352052643734689b2a2250ef9e3558253342e603b315b94a
[root@podman ~]# podman run -id --name db1 --volumes-from db_data ubuntu
83c227c5c077582cd700862508958d41e0532023ead11c95953aae0c4bc6faef
# 查看存储容器内容
[root@podman ~]# podman exec -it 8e48de /bin/bash
root@8e48de5ce3d3:/# ls
bin boot db_data dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@8e48de5ce3d3:/# ls db_data/
root@8e48de5ce3d3:/# cd db_data/
root@8e48de5ce3d3:/db_data# touch TestDB
root@8e48de5ce3d3:/db_data# exit
exit
# 查看应用容器内容
[root@podman ~]# podman exec -it 83c227 /bin/bash
root@83c227c5c077:/# ls /db_data/
TestDB
root@83c227c5c077:/# exit
exit

# 查看文件实际位置
[root@podman ~]# ls /var/lib/containers/storage/volumes/84a3b4a00b1557b6754f1ed9633294df117697d1608adc91701b335297caa61f/_data/
TestDB

性能监控

1
2
3
4
5
6
7
8
9
# stats命令 查看当前主机上容器的具体资源占用情况
[root@podman _data]# podman stats
ID NAME CPU % MEM USAGE / LIMIT MEM % NET IO BLOCK IO PIDS CPU TIME AVG CPU %
8e48de5ce3d3 db_data 0.01% 606.2kB / 4.044GB 0.01% 1.942kB / 978B 9.97MB / 4.096kB 1 29.762ms 0.01%
83c227c5c077 db1 0.00% 241.7kB / 4.044GB 0.01% 1.216kB / 978B 0B / 4.096kB 1 10.716ms 0.00%
# top命令 查看容器内的应用使用情况
[root@podman _data]# podman top 83c22
USER PID PPID %CPU ELAPSED TTY TIME COMMAND
root 1 0 0.000 7m29.133340188s ? 0s /bin/bash