Podman - 一个 Docker 的替代软件

Docker 将容器真正的带入大众视野,引领了容器化风潮,但是 Docker 本身作为一个容器引擎并没有太大的想像空间,毕竟单纯一个容器引擎对用户来说基本没什么用,毕竟用户把应用容器化之后还有很多事情要做,比如编排、扩缩容、访问控制、高可用等等。

Docker 其实也意识到这个问题了,所以一次公布了三个组件:Swarm, Machine 和 Compose ,但是很多公司对此并不太感冒,现在的赢家是 Kubernetes。究其原因我觉得是 Docker 虽然是开源的,但其实并不开放,用户害怕绑定到一家公司上面。Mesosphere 也是同样的情况。

以上是背景,最终也导致了 Docker 里加入的内容越来越多:将其作为一个容器编排工具(Kubernetes)的容器引擎吧,有太多没用的东西,像 Docker network, volume 等等东西容器编排工具其实并不用,因为编排工具有自己的网络和存储。将其作为一个人个开发工具吧,里面的一些像 Docker service 这种东西也基本没什么用。总的来说就是 Docker 在两边都不讨好,更别说很多让人摸不着头脑的 Bug 了,使用的越多会遇到越多的奇怪的 Bug。

Docker 最让我无语的设计就是所有操作都是 守护进程来做的,这个确实有一定的好处,但是也带来了很多不便,比如从私有仓库拉取镜像,要信任这个私有仓库的话需要修改守护进程的配置文件、重启守护进程之后才可以,比如要加个代理也需要重启守护进程,这个操作非常麻烦。

我从 2014 年开始使用 Docker,对其真是又爱又恨,但是随着越来越多的容器引擎出现,Docker 慢慢的也就变成了一个备胎。作为 Kubernetes 最成功的发行版,OpenShift 从 4.1 开始已经默认使用 CRI-O 作为其容器引擎了,而 RedHat 在 2018 年也发布了 Podman(Pod Manager) 套件,兼容 Docker 的大部分命令。

Podman 和 Docker 最主要的区别是 Podman 没有笨重的服务端,并且使用 Kubernetes 的 Pod 作为其单机编排标准,光这两项就已经甩开 Docker 两条大街了。当然 Podman 也有个小小的缺点就是需要借助于 Systemd 才能让容器在机器重启时跟随系统启动,没有 Docker 方便,但是有些人喜欢这种方式有些人不喜欢,作为用户我是不关心怎样跟随系统启动,只要方便就行,显然 Podman 并没有 Docker 方便。

Docker 使用的是其开发的 Compose 来编排多个容器,我对 Compose 不了解,所以就不说它与 Kubernetes Pod 格式的优缺点了,但是我要说的是 Kubernetes 已经是事实上的容器编排标准了,Kubernetes Pod 也被越来越多的人所接受,从这一点上来说 Kubernetes Pod 才是未来。

说说上手使用,我之前写过一篇文章说怎样用 Docker 来部署 PHP + MySQL 的站点,这种方式虽然比传统部署方式简单但是也有非常明显的缺点:当主容器重启后,其他容器就与主容器『失联』了,要挨个重启一下其他容器才行。

Podman 的 Pod 编排方式提供了一个更简单、更理想的部署方式,一个 YAML 文件搞定,能避免 Docker 中的问题,还是同样的例子:部署一个 Nginx + PHP + MySQL/MariaDB 的站点,WordPress 就是这样的站点。假设下面就是你的站点目录结构:

/var/www/html/wordpress
|-- nginx
    |-- mysite.conf
`-- source-dir

其中 mysite.conf 内容大致如下:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name mysite.com www.mysite.com;

    proxy_connect_timeout 4;
    proxy_read_timeout 300;
    proxy_send_timeout 300;

    index  index.php index.html index.htm;

    location / {
        root /var/www/html/wordpress/source-dir;
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        root           /var/www/html/wordpress/source-dir;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/html/wordpress/source-dir$fastcgi_script_name;
        include        fastcgi_params;
    }
}

其中 nginx 目录存放的是 Nginx 配置文件,source-dir 目录是你站点的源码目录,下面就是一个标准的 Kubernetes Pod YAML 文件,大致意思是将本机的/var/lib/mysql与容器里的/var/lib/mysql,本机的/var/www/html/wordpress/nginx与容器里的/etc/nginx/conf.d,本机的/var/www/html/wordpress/source-dir与容器里的/var/www/html/wordpress/source-dir做映射。

---
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: wordpress
  name: wordpress
spec:
  hostname: wordpress
  containers:
  - name: nginx
    image: docker.io/siji/nginx:latest
    ports:
    - containerPort: 80
      hostPort: 80
      protocol: TCP
    - containerPort: 443
      hostPort: 443
      protocol: TCP
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
    volumeMounts:
    - name: nginx-conf
      mountPath: /etc/nginx/conf.d
    - name: nginx-data
      mountPath: /var/www/html/wordpress/source-dir
  - name: mariadb
    image: docker.io/siji/mariadb:10.3
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: 123456
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
    volumeMounts:
    - name: mariadb-data
      mountPath: /var/lib/mysql
  - name: php-fpm
    image: docker.io/siji/php:7-fpm
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities: {}
      privileged: false
      readOnlyRootFilesystem: false
    volumeMounts:
    - name: nginx-data
      mountPath: /var/www/html/wordpress/source-dir
  volumes:
  - name: nginx-conf
    hostPath:
      path: /var/www/html/wordpress/nginx
      type: DirectoryOrCreate
  - name: nginx-data
    hostPath:
      path: /var/www/html/wordpress/source-dir
      type: DirectoryOrCreate
  - name: mariadb-data
    hostPath:
      path: /var/lib/mysql
      type: DirectoryOrCreate
status: {}

保存这个文件为mysite.yaml之后运行如下命令podman play kube mysite.yaml,然后你的 WordPress 博客就起动好了。

用 Podman 这种方式备份与恢复站点非常容易方便,日常使用也可以,我使用 Podman 有两个多月了,没遇到性能问题及 Bug ,倒是遇到了一些缺少的功能,毕竟 Podman 还太年轻,功能也在不断的完善。

作为 Docker 的替代方案,我觉得 Podman 完全可以。