如何使用 podman 替代 docker
dockerpodmandocker composepodman composepodman-composerootless dockerrootless podmanrootless container
2262 Words
2025-07-16 16:00 +0000
前言
早就听闻 podman 是 docker 的替代者,而且 podman 默认不需要用 root 用户来运行一个类似 dockerd 的守护进程,更加安全,此外 podman 的命令也基本与 docker 的命令保持一致,迁移过来也十分简单.
本文将以使用者的角度,简单聊聊如何使用 podman 替代 docker.
没有特别说明的话,本文使用 Ubuntu 24.04 操作系统来演示 podman 的使用.
安装 podman 以及简单使用
安装 podman 其实非常简单,直接从官方源安装即可:
sudo apt install -y podman
安装完成之后即可直接使用 podman 命令了,他的用法与 docker 命令基本一样.你甚至可以安装一个包 podman-docker
,从而让你继续使用 docker 命令,但是实际上是操作 podman 容器.注意,这里的 podman-docker 包与 docker 包是冲突的,所以安装这个包就不能保留 docker 包了.
podman 默认不需要一个类似 dockerd 的守护进程,而且默认是可以以非 root 身份管理和运行容器的,他也不需要加入一个类似 docker 组的特殊权限组.
一般的,我们建议直接以普通用户的身份来执行 podman 命令.
podman 的配置
为了让 podman 用起来更像 docker 那样,我们可以配置一下 podman 的镜像仓库,创建并编辑 /etc/containers/registries.conf.d/10-unqualified-search-registries.conf
,内容如下:
unqualified-search-registries = ["docker.io"]
podman/docker 的快速入门介绍
如图所示,我们可以以 Docker 镜像为中心快速入门 docker 的使用.当然,这个对于 podman 也是同样适用的.
- 我们使用
docker run
命令来从一个 docker 镜像创建出来一个容器,然后在容器内进行各种操作.一般建议使用docker run -it --rm
,这样当你退出容器的时候就会自动删除了.实际生产环境很少直接使用docker run
命令了,一般建议使用 docker compose 来管理. docker commit
可以把正在运行的容器保存为镜像,但是我们一般不建议使用,因为它保存的镜像文件往往太大,也无法重复.- 最佳实践是从
Dockerfile
使用docker build
命令构建镜像.关于 Dockerfile 的编写,请参考这个文档,主要掌握FROM, COPY, CMD, ENV, ARG, WORKDIR
这几个指令,其他指令可以暂时忽略. - 从仓库拉取镜像可以使用
docker pull
命令.一般我们不需要推送自己的镜像到仓库去,如果有需要可以查阅docker push
命令和对应仓库站点的说明(比如如何注册和登录). - 更多的时候我们可能需要在机器 A 导出镜像文件,然后导入到机器 B.导出镜像为文件可以使用命令
docker save
,一般建议使用压缩,例如docker save nginx:latest | zstd -o nginx.tar.zst
.导出只需要使用docker load -i nginx.tar.zst
即可.除非你用了很老版本的操作系统和 docker 版本,否则导入的时候是自动支持解压的,我们不需要额外的处理.
本小结内容整理自 docker-for-env-without-internet-access,如有需要也可以参考.
一些扩展
使用 docker 命令(非 podman-docker)来管理 podman 容器
实际上 podman 有一个 systemd 服务可以启动的,只是 podman 本身是不需要它的.这个服务提供兼容 docker 1.40 API 的层,也就是说启动这个服务之后,可以直接使用原生的 docker 命令来操作 podman 容器,就好像使用 docker 命令跟 dockerd 守护进程通信一样.
sudo systemctl stop docker.socket
sudo systemctl stop docker.service
# 这里我们使用普通用户 ubuntu
sudo loginctl enable-linger ubuntu
# 这里我们直接启动 podman.socket
# 也可以启动 podman.service,差别在于前者只会在有请求的时候才会去真正的启动 podman.socket
systemctl --user start podman.socket
systemctl --user enable podman.socket
# 设置 DOCKER_HOST 为 podman.socket,让 docker 跟这个套接字通信
# 这个配置也可以写到 .bashrc 里去
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock
这样,我们就可以直接使用 docker 命令来操作 podman 容器了.例如,docker info
输出:
host:
arch: amd64
buildahVersion: 1.33.7
cgroupControllers:
- cpu
- memory
- pids
cgroupManager: systemd
cgroupVersion: v2
conmon:
package: conmon_2.1.10+ds1-1build2_amd64
path: /usr/bin/conmon
version: 'conmon version 2.1.10, commit: unknown'
cpuUtilization:
idlePercent: 99.88
systemPercent: 0.04
userPercent: 0.07
cpus: 2
databaseBackend: sqlite
distribution:
codename: noble
distribution: ubuntu
version: "24.04"
eventLogger: journald
freeLocks: 2046
hostname: aws.butui.me
idMappings:
gidmap:
- container_id: 0
host_id: 1000
size: 1
- container_id: 1
host_id: 100000
size: 65536
uidmap:
- container_id: 0
host_id: 1000
size: 1
- container_id: 1
host_id: 100000
size: 65536
kernel: 6.8.0-1031-aws
linkmode: dynamic
logDriver: journald
memFree: 118321152
memTotal: 958533632
networkBackend: netavark
networkBackendInfo:
backend: netavark
dns:
package: aardvark-dns_1.4.0-5_amd64
path: /usr/lib/podman/aardvark-dns
version: aardvark-dns 1.4.0
package: netavark_1.4.0-4_amd64
path: /usr/lib/podman/netavark
version: netavark 1.4.0
ociRuntime:
name: crun
package: crun_1.14.1-1_amd64
path: /usr/bin/crun
version: |-
crun version 1.14.1
commit: de537a7965bfbe9992e2cfae0baeb56a08128171
rundir: /run/user/1000/crun
spec: 1.0.0
+SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +WASM:wasmedge +YAJL
os: linux
pasta:
executable: /usr/bin/pasta
package: passt_0.0~git20240220.1e6f92b-1_amd64
version: |
pasta unknown version
Copyright Red Hat
GNU General Public License, version 2 or later
<https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
remoteSocket:
exists: true
path: /run/user/1000/podman/podman.sock
security:
apparmorEnabled: false
capabilities: CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT
rootless: true
seccompEnabled: true
seccompProfilePath: /usr/share/containers/seccomp.json
selinuxEnabled: false
serviceIsRemote: false
slirp4netns:
executable: /usr/bin/slirp4netns
package: slirp4netns_1.2.1-1build2_amd64
version: |-
slirp4netns version 1.2.1
commit: 09e31e92fa3d2a1d3ca261adaeb012c8d75a8194
libslirp: 4.7.0
SLIRP_CONFIG_VERSION_MAX: 4
libseccomp: 2.5.5
swapFree: 0
swapTotal: 0
uptime: 45h 7m 1.00s (Approximately 1.88 days)
variant: ""
plugins:
authorization: null
log:
- k8s-file
- none
- passthrough
- journald
network:
- bridge
- macvlan
- ipvlan
volume:
- local
registries:
search:
- docker.io
store:
configFile: /home/ubuntu/.config/containers/storage.conf
containerStore:
number: 2
paused: 0
running: 2
stopped: 0
graphDriverName: overlay
graphOptions: {}
graphRoot: /home/ubuntu/.local/share/containers/storage
graphRootAllocated: 19682557952
graphRootUsed: 3230658560
graphStatus:
Backing Filesystem: extfs
Native Overlay Diff: "true"
Supports d_type: "true"
Supports shifting: "false"
Supports volatile: "true"
Using metacopy: "false"
imageCopyTmpDir: /var/tmp
imageStore:
number: 2
runRoot: /run/user/1000/containers
transientStore: false
volumePath: /home/ubuntu/.local/share/containers/storage/volumes
version:
APIVersion: 4.9.3
Built: 0
BuiltTime: Thu Jan 1 08:00:00 1970
GitCommit: ""
GoVersion: go1.22.2
Os: linux
OsArch: linux/amd64
Version: 4.9.3
明显看到,这些都是 podman 的信息.
docker-compose 和 podman-compose
直接使用 docker 或者 podman 命令过于简陋,上 k3s 或者 k8s 又过于复杂.这个时候 docker-compose 或者 podman-compose 就是一个比较好的折中选择,它使用一个简单的 docker-compose.yaml
文件来描述启动一个项目需要启动的服务(容器),然后只需要一个 docker compose up -d
或者 podman compose up -d
即可启动服务,非常简单好用.
podman compose
实际上可以使用 podman-compose 也可以使用 docker-compose.如果后者已经安装了,默认它会优先使用 docker-compose.特别注意的是,docker-compose 有 v1 和 v2 两个差别较大的版本,建议使用 v2.
此外,docker-compose 实际上还是需要跟 dockerd 通信,因此要让 podman 能够正常使用 docker-compose 的话,需要使用 podman.socket 的.
你可以可以参考文档来设置让 podman 默认使用哪一个.
一般认为 podman-compose 对 docker compose 的兼容性有一些小问题,例如环境变量的设置,见 issue #491.建议优先选择 docker-compose.
当然了,实际上你也可以直接使用 docker compose
命令的.
小结
本文简单介绍了如何使用 podman 替代 docker,还给出了 podman compose 的相关用法,以及如何使用 docker 命令来操作 podman 容器等.
- 仅安装 podman 和 podman-compose,不安装 docker,直接使用 podman 替代 docker 命令,基本的命令以及 podman compose 都是可以正常使用的.
- 安装 podman 和 docker-compose-v2(docker 可能会被作为依赖安装),启动
podman.socket/service
,禁用和停止docker.socket/service
,配置环境变量DOCKER_HOST
,正常使用 docker 命令,实际操作的是 podman 容器.当然,也可以用 podman 命令.