手把手教你从 Docker 迁移到 Podman

40 次阅读 0 点赞 0 评论 10 分钟原创技术教程

本文带你完成 Docker 到 Podman 的平滑迁移。掌握各平台安装方法、命令对照映射与 Rootless 安全容器模式,通过 Node.js + Redis 实战跑通多容器应用,摆脱 Docker daemon 的资源瓶颈。

#Podman #Docker #容器 #Docker替代 #Rootless #后端实战 #运维
手把手教你从 Docker 迁移到 Podman

手把手教你从 Docker 迁移到 Podman

CI 服务器频繁 OOM Kill,排查后发现 Docker daemon 在容器数量攀升后成了定时炸弹:一个守护进程管理数百个容器,daemon 一挂,所有容器跟着遭殃。换成 Podman 后,同样的机器连续运行数月零故障。这篇教程带你把本地开发环境也平稳迁过来。

你将完成什么

学完本文,你能在自己的系统上装好 Podman,把常用 Docker 命令无缝迁移,用 Rootless 模式以普通用户身份安全运行容器,并独立跑通一个完整的 Node.js + Redis 容器化应用。

前置条件

  • 操作系统:Linux(Ubuntu/Debian/Fedora/CentOS),Mac/Windows 通过虚拟机支持
  • Linux 内核版本:4.0+
  • 基础知识:了解 Docker 基本概念(镜像、容器、端口映射、卷挂载)
  • 磁盘空间:约 200MB(无驻留守护进程,体积轻量)

安装 Podman

Podman 在各平台安装方式差异较大,跨过这一步后面就是纯操作。

Linux(Ubuntu 示例)

bash 复制代码
## 更新包索引
sudo apt update

## 安装 Podman
sudo apt install -y podman

## 验证安装
podman --version
## 输出示例:podman version 5.x.x

Fedora/CentOS 系直接用 sudo dnf install podmansudo yum install podman。主流发行版已将 Podman 纳入官方仓库,无需像 Docker 那样手动添加外部源。

Mac / Windows

Mac 和 Windows 内核缺乏 Linux 的 cgroup 和 namespace 隔离机制,Podman 通过轻量虚拟机来支撑容器运行:

bash 复制代码
## Homebrew 安装
brew install podman

## 初始化虚拟机(首次下载约 500MB)
podman machine init

## 启动虚拟机
podman machine start

## 后续命令自动转发到虚拟机执行
podman run hello-world

默认虚拟机内存占用不到 1GB,比 Docker Desktop 轻量许多。


Docker 命令迁移

Podman CLI 与 Docker 高度兼容,常用命令直接替换即可:

Docker 命令 Podman 命令
docker run podman run
docker ps podman ps
docker images podman images
docker pull podman pull
docker stop podman stop
docker exec podman exec
docker logs podman logs
docker rm podman rm
docker build podman build
docker compose podman-composepodman compose

运行 Hello World

bash 复制代码
podman run quay.io/podman/hello

Podman 默认使用 quay.io 仓库,但完全兼容 Docker Hub,之前的 nginxredis 镜像命令无需修改。

运行 Nginx 示例

bash 复制代码
## 拉取镜像
podman pull nginx:alpine

## 前台运行,端口映射 8080
podman run -d --name my-nginx -p 8080:80 nginx:alpine

## 查看容器
podman ps

## 停止并清理
podman stop my-nginx
podman rm my-nginx

外层体验几乎一致,底层区别在于彻底移除了 Docker daemon


Rootless 模式——普通用户的容器安全实践

Docker 默认需要 root 权限,能执行 docker 命令的用户实质上持有宿主机 root 访问权。Podman 原生支持 rootless 模式,容器内 root 映射为宿主机普通用户,攻击面大幅收缩。

配置步骤

bash 复制代码
## 检查子 UID/GID 映射
cat /etc/subuid
## 预期:yourname:100000:65536

cat /etc/subgid

## 缺失时手动添加
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER

## 安装 rootless 网络依赖
sudo apt install -y slirp4netns fuse-overlayfs

## 普通用户直接运行
podman run -d --name secure-nginx -p 8080:80 nginx:alpine

验证生效

bash 复制代码
## 查看进程归属(应显示你的用户名而非 root)
ps aux | grep conmon

## 确认 rootless 状态
podman info | grep -i rootless
## 输出 true

实战:Node.js + Redis 多容器应用

创建项目代码

bash 复制代码
mkdir podman-demo && cd podman-demo

cat > package.json << 'EOF'
{
  "name": "podman-demo",
  "version": "1.0.0",
  "main": "app.js",
  "dependencies": {
    "express": "^4.18.2",
    "redis": "^4.6.0"
  }
}
EOF

cat > app.js << 'EOF'
const express = require('express');
const { createClient } = require('redis');

const app = express();
const PORT = 3000;

let redisClient;

(async () => {
  redisClient = createClient({ url: 'redis://redis-podman:6379' });
  redisClient.on('error', err => console.log('Redis 连接失败:', err));
  await redisClient.connect();
})().catch(console.error);

app.get('/', async (req, res) => {
  const count = await redisClient.incr('visits');
  res.send(`这是第 ${count} 次访问(Podman 版)\n`);
});

app.listen(PORT, '0.0.0.0', () => {
  console.log(`服务已启动: http://0.0.0.0:${PORT}`);
});
EOF

编写 Containerfile

Podman 完全兼容 Dockerfile,也可使用推荐的 Containerfile 命名:

dockerfile 复制代码
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]

组建容器网络

bash 复制代码
## 创建专属网络
podman network create app-network

## 运行 Redis 加入网络
podman run -d --name redis-podman \
  --network app-network \
  redis:alpine

## 构建应用镜像
podman build -t my-node-app .

## 运行应用容器
podman run -d --name node-app \
  --network app-network \
  -p 3000:3000 \
  my-node-app

同网络内容器可通过容器名 DNS 解析,代码中的 redis-podman:6379 直接可达 Redis 服务。

验证运行

bash 复制代码
podman ps

curl http://localhost:3000
## 输出:这是第 1 次访问(Podman 版)

curl http://localhost:3000
## 输出:这是第 2 次访问(Podman 版)

常见问题与踩坑提醒

Mac/Windows 端口映射

podman machine 虚拟机的端口映射有时不直接生效,可通过以下命令查看虚拟机 IP 进行访问:

bash 复制代码
podman machine ssh ip address show podman0

Rootless 端口限制

非 root 用户无法绑定 1024 以下端口,映射时需使用高位端口(如 8080)。若必须使用 80 端口,可切换 root 模式或前置 Nginx 反代。

podman-compose 安装

若项目依赖 docker-compose.yml,需单独安装编排工具:

bash 复制代码
## Ubuntu/Debian
sudo apt install -y podman-compose

## 或使用 pip
pip install podman-compose

## 直接使用
podman-compose up -d

Podman 5.x 已内建 podman compose 命令(兼容 podman-compose 层),5+ 版本通常无需额外安装。


总结与延伸

本次迁移覆盖了安装部署、命令对照、Rootless 安全配置到多容器网络编排的全流程。Podman 的无守护进程架构降低了资源占用,原生 Rootless 支持提升了生产环境安全性。若团队正受困于 Docker daemon 稳定性或合规审计的权限要求,Podman 是值得落地的方案。

延伸探索方向

  • 研究 Podman Pod 功能:多容器共享同一网络命名空间,概念类似 Kubernetes Pod
  • 尝试 podman generate kube:将运行中容器直接导出为 K8s YAML,打通本地到 K8s 部署链路
  • 了解 Buildah:同生态镜像构建工具,支持无 Dockerfile 构建

遇到问题欢迎交流讨论。

最后更新:2026-06-05T10:03:36

评论 (0)

发表评论

blog.comments.form.loading
0/500
加载评论中...