podman
最佳实践
ubuntu
podman 在 linux 上的最佳实践
- apt install podman
- 安装 podman desktop
- 替换国内源在 podman desktop 设置 registries 中的 Preferred 为 docker.1ms.run

- (可选步骤)在更换源之后, 如果在拉取镜像时还是有点慢. 那么说明podman desktop 还是默认去查找了 docker.io, 需要配置代理加速.


- 可以在image功能中去拉取镜像, 输入镜像名即可搜索相关镜像.

这里没有配置 docker.io 源,但是还是去搜索了docker.io, 这个行为特别奇怪. 如果原来的机器没有安装 docker, 似乎就不会去搜索docker.io. 恰好 docker.io 在国内被禁,所以不配置代理,这里搜索镜像会长时间不可用直到超时.
注意: 在 podman desktop 中配置的 registries 不会影响命令行中的命令. 命令行中使用 podman pull <镜像名> 时还需要去设置. 请参考 镜像源
install
apt install podman
sudo apt install podman
podman 是一个 rootless 的容器管理系统,基本功能和 docker 类似. 相对比docker的优势 Podman vs Docker 2026: Security, Performance & Which to Choose:
- 默认提供 rootless 且无守护进程(daemon), 安全性好
- 提供 pod 的概念,更容易和k8s之类的容器编排调度系统集成
- 完全开源, 提供了兼容 docker 的标准的容器格式规范
image
podman pull redis
直接拉取镜像会报错:
ryefccd@republic:~$ podman pull redis
Error: short-name "redis" did not resolve to an alias and no unqualified-search registries are defined in "/etc/containers/registries.conf"
解决方案有两个:
-
指定某个可以使用的源
podman pull docker.1ms.run/library/postgres:16 -
因为国内的docker镜像源不可使用,所以需要更换国内可以使用的源: https://1ms.run/ 具体配置参考下一节镜像源
镜像源
修改podman国内镜像源(兼容docker)
# 在此文件增加源的配置
sudo vim /etc/containers/registries.conf
# # An array of host[:port] registries to try when pulling an unqualified image, in order.
# unqualified-search-registries = ["example.com"]
unqualified-search-registries = ["docker.1ms.run"]
设置完源以后,就可以直接使用镜像名字下载了
podman pull postgres:16 podman pull postgres:latest podman pull ubuntu
注意: 如果在更换 unqualified-search-registries 之后还是 去 docker.io拉取某些镜像时, 如下所示.
ryefccd@republic:~$ podman pull node
Resolved "node" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
Trying to pull docker.io/library/node:latest...
WARN[0060] Failed, retrying in 1s ... (1/3). Error: initializing source docker://node:latest: pinging container registry registry-1.docker.io: Get "https://registry-1.docker.io/v2/": dial tcp 103.252.115.221:443: i/o timeout
这个表示node在 (/etc/containers/registries.conf.d/shortnames.conf) 设置了别名:
...
# node
"node" = "docker.io/library/node"
那么需要把此 shortnames .conf 别名设置中的 docker.io 都替换成 docker.1ms.run. 具体操作请参看 镜像别名(shortnames)
container
podman pull docker.1ms.run/library/postgres:16
创建容器
podman run --name pg16 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=fccdjny -p 5432:5432 -d postgres
创建容器容器指定网络
podman run -d --name my-container --network my-network nginx
创建网络请参考: 创建网络
exec
非交互式运行:
podman exec pg16 date
交互式运行:
进入一个正在运行的容器中的shell,用于调试
podman exec -it pg16 bash
-i 表示交互式操作 -t 表示使用一个 terminal 终端
操作此pg16容器中的psql客户端
podman exec -it pg16 psql -U postgres
network
podman 在ubuntu中默认的桥接网络配置文件: /etc/cni/net.d/87-podman-bridge.conflist
{
"cniVersion": "0.4.0",
"name": "podman",
"plugins": [
{
"type": "bridge",
"bridge": "cni-podman0",
"isGateway": true,
"ipMasq": true,
"hairpinMode": true,
"ipam": {
"type": "host-local",
"routes": [{ "dst": "0.0.0.0/0" }],
"ranges": [
[
{
"subnet": "10.88.0.0/16",
"gateway": "10.88.0.1"
}
]
]
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
},
{
"type": "firewall"
},
{
"type": "tuning"
}
]
}
查看podman的网络配置
Basic Networking Guide for Podman
podman network ls
ryefccd@republic:~$ podman network ls
NETWORK ID NAME DRIVER
2f259bab93aa podman bridge
查看 podman 网络设置中名为 podman 的网桥配置
podman network inspect podman
ryefccd@republic:~$ podman network inspect podman
[
{
"name": "podman",
"id": "2f259bab93aaaaa2542ba43ef33eb990d0999ee1b9924b557b7be53c0b7a1bb9",
"driver": "bridge",
"network_interface": "podman0",
"created": "2026-01-06T14:29:56.005594914+08:00",
"subnets": [
{
"subnet": "10.88.0.0/16",
"gateway": "10.88.0.1"
}
],
"ipv6_enabled": false,
"internal": false,
"dns_enabled": false,
"ipam_options": {
"driver": "host-local"
}
}
]
如文件所示: dns_enabled : false 表示未开启dns解析. 所以不能通过容器名字去在网络访问容器. 如果需要开启容器名字的dns解析,请参考下一节.
通过容器名字作为域名解析
查看 podman 默认的网络配置, 这个配置默认是保存在内存中的.
podman network inspect podman | jq .[] > ~/.local/share/containers/storage/networks/podman.json
如果需要修改, 需要把此配置导出 ~/.local/share/containers/storage/networks/podman.json 文件, 修改其中的dns_enabled的配置开启,重启容器即可通过容器名字访问(ping).
{
...
"dns_enabled": true,
...
}
alpine 镜像带有ping命令
准备一个带有 ping 命令的容器
podman pull alpine podman run -d –network podman –name a1 alpine sleep infinity
ubuntu容器设置icmp数据包权限
ubnutu 容器如果需要 ping 命令,需要单独设置 ICMP 数据包的权限
podman pull ubuntu podman run -d –cap-add=NET_RAW –name ub ubuntu sleep infinity podman run -itd –cap-add=NET_RAW –name ub ubuntu bash
podman run -d –network podman –name a1 alpine sleep infinity podman run -d –network podman –name a2 alpine sleep infinity podman run -d –name a3 alpine sleep infinity
podman inspect -f ‘{{.NetworkSettings.IPAddress}}’ a1 podman inspect -f ‘{{.NetworkSettings.IPAddress}}’ a2 podman inspect -f ‘{{.NetworkSettings.IPAddress}}’ a3
可以看到 a1 和 a2 容器都分配了ip. a3 没有分配ip, 这是因为podman 创建容器需要显示的传递网络配置才能分配ip和容器名作为域名访问.
ryefccd@republic:~$ podman inspect -f '{{.NetworkSettings.IPAddress}}' a1
10.88.0.2
ryefccd@republic:~$ podman inspect -f '{{.NetworkSettings.IPAddress}}' a2
10.88.0.3
ryefccd@republic:~$ podman inspect -f '{{.NetworkSettings.IPAddress}}' a3
podman exec a1 ping -c 3 a2
ryefccd@republic:~$ podman exec a1 ping -c 3 a2
PING a2 (10.88.0.11): 56 data bytes
64 bytes from 10.88.0.11: seq=0 ttl=42 time=0.049 ms
64 bytes from 10.88.0.11: seq=1 ttl=42 time=0.107 ms
64 bytes from 10.88.0.11: seq=2 ttl=42 time=0.116 ms
--- a2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.049/0.090/0.116 ms
给容器一个固定ip
podman run -d –network podman –ip 10.88.0.6 –name a6 alpine sleep infinity podman run -d –network podman –ip 10.88.0.7 –name a7 alpine sleep infinity
创建网络
Subnet: Specify a custom IP rangenet
podman network create --subnet 192.168.10.0/24 net192
podman network create --subnet 10.0.0.0/24 --ip-range 10.0.0.100-10.0.0.200 my-custom-net
Gateway: Define the gateway IP for the network
podman network create --gateway 192.168.10.1 custom-net
Driver: Choose a specific network driver, such as macvlan or ipvlan (rootful only)
podman network create -d macvlan -o parent=eth0 macvlan-net
Internal: Create a network that is isolated from the host and external internet
podman network create --internal private-net
注意, 新创建的网络默认开启了 dns_enabled: true 的配置
ryefccd@republic:~$ podman network inspect net192
[
{
"name": "net192",
"id": "fdc405841b2ed10679ffe3eacf9e6780af8f852bd9cd27e11355ed3eb751383b",
"driver": "bridge",
"network_interface": "podman3",
"created": "2026-01-07T15:29:51.040501876+08:00",
"subnets": [
{
"subnet": "192.168.10.0/24",
"gateway": "192.168.10.1"
}
],
"ipv6_enabled": false,
"internal": false,
"dns_enabled": true,
"ipam_options": {
"driver": "host-local"
}
}
]
用此网络设备的容器都可以通过容器名互相访问(ping)了.
podman desktop
完成安装后可以在桌面程序上管理容器, pod, 网络和存储卷,也能和k8s进行交互.
在拉取镜像时直接指定 registry 的域名也可以在其中搜索镜像. 如下图所示, 输入 docker.1ms.run 搜索此源镜像:

下面是 /etc/containers/registries.conf 配置中提到的为什么镜像使用全限定名称的原因.
note: risk of using unqualified image names
We recommend always using fully qualified image names including the registry
server (full dns name), namespace, image name, and tag
(e.g., registry.redhat.io/ubi8/ubi:latest). Pulling by digest (i.e.,
quay.io/repository/name@digest) further eliminates the ambiguity of tags.
When using short names, there is always an inherent risk that the image being
pulled could be spoofed. For example, a user wants to pull an image named
foobar from a registry and expects it to come from myregistry.com. If
myregistry.com is not first in the search list, an attacker could place a
different foobar image at a registry earlier in the search list. The user
would accidentally pull and run the attacker’s image and code rather than the
intended content. We recommend only adding registries which are completely
trusted (i.e., registries which don’t allow unknown or anonymous users to
create accounts with arbitrary names). This will prevent an image from being
spoofed, squatted or otherwise made insecure. If it is necessary to use one
of these registries, it should be added at the end of the list.
podman compose
安装 podman-compose
sudo apt install podman-compose
podman-compose兼容 docker-compose, 用来做多容器编排管理.
默认文件是 compose.yaml, compose.yml, docker-compose.yaml or docker-compose.yml
podman compose up -d
如果是以其他文件命名, 可以使用 -f 来指定相关编排文件
podman compose -f my-alternative-name.yml up
只更新其中一个容器, 比如haproxy:
podman compose up -d --force-recreate haproxy
示例
postgresql 容器
Running PostgreSQL with Podman
atlasgo 数据库模式变更管理
apt install podman podman-docker
sudo apt install podman podman-docker
podman 是一个 rootless 的容器管理系统,基本功能和 docker 类似. 只是默认提供 rootless 的模式,安全性比较好. podman-docker 会在 $PATH 路径下设置一个 docker 的脚本命令,实际也是指向 podman 的执行文件. 这个库目的是兼容 docker 去适配一些开发工具行为。比如我们使用的 atlasgo 这个用于管理数据库表字段变更的工具.
atlas migrate diff –env sqlalchemy –dev-url “docker://postgres/16”
此处的 docker://postgres/16 会在命令运行时使用 docker 命令程序去运行 postgres:16 的镜像来做数据库模式变更迁移.
参考
docker 镜像源
境内 Docker 镜像状态监控
毫秒镜像 - 专为中国开发者提供的专业容器仓库服务
docker 的配置文件(/etc/docker/daemon.json):
{
"registry-mirrors": ["docker.1ms.run", "https://mirror.gcr.io",]
}
镜像别名(shortnames)
在 shortnames.conf 文件中还有一些别名设置,检测到某些常用的软件镜像直接就指定了查找源,因为国内的 docker 域名不能访问,所以也需要替换
~$ podman pull hello-world
Resolved "hello-world" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
Trying to pull docker.io/library/hello-world:latest...
...
# docker
"alpine" = "docker.io/library/alpine"
"docker" = "docker.io/library/docker"
"registry" = "docker.io/library/registry"
"hello-world" = "docker.io/library/hello-world"
...
# Ubuntu
"ubuntu" = "docker.io/library/ubuntu"
# Oracle Linux
"oraclelinux" = "container-registry.oracle.com/os/oraclelinux"
# busybox
"busybox" = "docker.io/library/busybox"
# php
"php" = "docker.io/library/php"
# python
"python" = "docker.io/library/python"
# node
"node" = "docker.io/library/node"
...
查看替换结果:
sed ‘s/docker.io/docker.1ms.run/g’ /etc/containers/registries.conf.d/shortnames.conf
在原文件直接替换:
sudo sed ‘s/docker.io/docker.1ms.run/g’ /etc/containers/registries.conf.d/shortnames.conf -i
替换后结果如下:
...
# docker
"alpine" = "docker.1ms.run/library/alpine"
"docker" = "docker.1ms.run/library/docker"
"registry" = "docker.1ms.run/library/registry"
"hello-world" = "docker.1ms.run/library/hello-world"
...
# Ubuntu
"ubuntu" = "docker.1ms.run/library/ubuntu"
# Oracle Linux
"oraclelinux" = "container-registry.oracle.com/os/oraclelinux"
# busybox
"busybox" = "docker.1ms.run/library/busybox"
# php
"php" = "docker.1ms.run/library/php"
# python
"python" = "docker.1ms.run/library/python"
# node
"node" = "docker.1ms.run/library/node"
...
wsl2 proxy 设置
windows 中使用 podman 需要使用 wsl2 作为 podman machine. 在windows 中 C:\Users${USER} 创建 .wslconfig 文件并写入以下配置识别系统代理
[experimental]
autoMemoryReclaim=gradual
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true