什么是podman?

什么是podman?

Podman是一种容器管理工具,因此在了解在Podman之前我们先了解一下什么是容器。通过这篇文章我将会先让你了解容器的概念以及它和Podman的关系。

什么是容器

先从容器说起,在传统部署中,你需要装系统、配置环境、装工具等各种依赖。而所谓的容器,就是将这些依赖“打包”在一个标准化的盒子里,无论在哪台机器上运行这个容器,它的行为都是一致的。这也就解决了一个经典的问题:“可是在我的机器上就没有问题呀”。

那怎么做出来一个容器呢?这就要提到镜像,对一个镜像使用运行命令,就会产生一个运行的容器。所以看出来了么,镜像和容器的关系,就如同面向对象编程语言中类与对象的关系。我猜看到这里你肯定要问了,那要怎么做一个镜像呢?没错,得到一个容器的关键其实是制作一个镜像。

制作一个镜像其实非常简单,你只需要一个类似清单一样的文件,列出你需要的基础镜像,需要用到的依赖,执行一些镜像在生成容器过程中的命令,例如切换容器内的工作目录、复制源代码、下载依赖、打包代码等等,然后对这个文件执行一个生成镜像的命令。接下来我们以一个简单的node镜像文件为例。

# 基础镜像为最新的alpha版本的node
FROM node:alpha 

# 设定工作目录
WORKDIR /usr/src/app

# 复制依赖文件
COPY package.json package-lock.json 

# 下载依赖
RUN npm ci --include=dev

# 复制源代码
COPY src ./src

# 执行构建命令
RUN npm build

# 设置环境变量
ENV NODE_ENV=production
ENV PORT=3000

# 列出当前所有文件
RUN ls -la .

# 最后执行运行程序的命令 一个容器就开始运行了
CMD ["node", "dist/index.js"]


这就是一个镜像文件的大概内容,看到了么,它其实很简单,就像一个记录“流水账”的账单一样,最后我们将其保存为一个名为Dockerfile的文件,这样我们就完成了一个镜像文件。

接下来我们执行构建镜像的命令。在命令行里,将目录切换到镜像文件所在的目录,以podman的命令为例,在命令行执行:

podman build -t customer_name

执行这个命令后会生成一个名为customer_name的镜像。命令中的“-t ”就是指镜像名称(tag)。我们还可以在命令行里执行:

podman images

命令列出所有的镜像。接下来我们就可以执行:
podman run -d --name customer_container_name customer_name

来通过这个镜像得到一个运行的容器。这个命令中的“-d”是指在后台(detached)模式下运行,而“--name customer_container_name”就是给这个容器起一个名字,这之后的“customer_name”则是你之前那个镜像的名字。然后我们可以执行:

podman ps

命令列出所有的正在运行的容器。到这里你已经通过编写镜像文件,再构建镜像,然后运行镜得到了一个运行的容器。在这之后,你可以通过在命令行里执行:

podman stop customer_container_name 或者 podman stop [id]

来停止这个容器(这里的id就是podman ps命令中列出的id)。

Podman和容器

相信到了这里,你已经对Podman已经有了基本的了解。它可以帮助你管理容器的整个生命周期(创建、启动、停止、删除、监控、网络、存储、日志等)。通过官网可以下载适合平台的内容。

除了Podman以外,还有 Docker、containerd、CRI-O、LXC/LXD 等常见容器引擎,它们各有定位和优势。另外还有Kubernetes这样的容器编排系统,它在更高层次对容器进行分布式管理。说到这里,你可能会发现镜像文件的名字“Dockerfile”似乎和Docker有着千丝万缕的联系,你的感觉是对的,这就不得不提到Podman和Docker的关系。

Podman和Docker

简单来说,Podman 可以理解为 Docker 的“后起之秀”和“无守护进程版本”。Podman几乎所有的命令都和Docker一样,也就是说将“podman ps”换成“docker ps”就变成了Docker的命令了!

那么它们区别在哪里呢?这得先提到“containerd”,它是一个 容器运行时(runtime),最初是 Docker 的一部分,后来被独立出来,成为 CNCF(云原生基金会)维护的独立项目它专注于做“容器运行的底层逻辑”:镜像管理、快照、容器生命周期管理等,现在 Kubernetes 等容器编排系统,通常都是通过 containerd 来真正运行容器的。所以Docker容器其实是通过Docker Engine (dockerd)、containerd来执行底层的runc最终运行起来的。而Podman没有 dockerd(无守护进程),使用底层运行时 CRI-O 或直接 runc,可以 rootless 运行。

到此,我们已经理清了Podman和容器的基本概念和逻辑,在之后的内容中,将进一步探索Podman的各种常用命令及其参数,还有它的网络、pod、密钥等相关概念的使用,以及如何构建一些常用的容器。