1. 什么是 Docker?

Docker 是一个开源的应用容器引擎,属于 Linux 容器的一种封装,Docker 提供简单易用的容器使用接口,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上。容器是完全使用沙箱机制,相互之间不会有任何接口。

Docker 是目前很流行的 Linux 容器解决方案,即使 Docker 是目前管理 Linux 容器的一个非常方便的工具,但它也有两个缺点:

  • Docker 需要在你的系统上运行一个守护进程。
  • Docker 是以 root 身份在你的系统上运行该守护程序。

这些缺点的存在可能有一定的安全隐患,为了解决这些问题,下一代容器化工具 Podman 出现了 。

2. 什么是 Podman ?

Podman 是一个开源的容器运行时项目,可在大多数 Linux 平台上使用。Podman 提供与 Docker 非常相似的功能。正如前面提到的那样,它不需要在你的系统上运行任何守护进程,并且它也可以在没有 root 权限的情况下运行。

Podman 可以管理和运行任何符合 OCI(Open Container Initiative)规范的容器和容器镜像。Podman 提供了一个与 Docker 兼容的命令行前端来管理 Docker 镜像。

Podman 官网地址: https://podman.io/

Podman 项目地址: https://github.com/containers/libpod

3. 安装 PodmanPodman

目前已支持大多数发行版本通过软件包来进行安装,下面我们来举几个常用发行版本的例子。

  • Fedora / CentOS
1sudo yum -y install podman 
  • Ubuntu
1sudo apt-get update -qq 
2sudo apt-get install -qq -y software-properties-common uidmap 
3sudo add-apt-repository -y ppa:projectatomic/ppa 
4sudo apt-get update -qq 
5sudo apt-get -qq -y install podman 
  • MacOS
1brew cask install podman

安装成功后进行初始化与启动

  • 初始化
1podman machine init
2
3Downloading VM image: fedora-coreos-38.20230819.2.0-qemu.x86_64.qcow2.xz: done
4Extracting compressed file
5Image resized.
6Machine init complete
7To start your machine run:
8
9 podman machine start
  • 启动(我使用最新版也是报gvproxy错误,网上查看以前旧版本同样有这个问题。)
1podman machine start
2
3Starting machine "podman-machine-default"
4Error: unable to start host networking: "could not find \"gvproxy\" in one of [/usr/local/opt/podman/libexec /opt/homebrew/bin /opt/homebrew/opt/podman/libexec /usr/local/bin /usr/local/Cellar/podman/
54.1.1/libexec /usr/local/lib/podman /usr/libexec/podman /usr/lib/podman].  To resolve this error, set the helper_binaries_dir key in the `[engine]` section of containers.conf to the directory containing your helper binaries."

解决方法: 编辑配置文件vim ~/.config/containers/containers.conf在engine后面填加如下内容。具体Homebrew的位置每台电脑不一样,可以通过echo $PATH查看。

1[engine]
2  helper_binaries_dir=["/usr/local/Homebrew/Cellar/podman/4.1.1/bin","/usr/local/Homebrew/Cellar/podman/4.1.1/libexec"]

再次启动成功

 1podman machine start
 2Starting machine "podman-machine-default"
 3Waiting for VM ...
 4Mounting volume... /Users/xzeu:/Users/xzeu
 5
 6This machine is currently configured in rootless mode. If your containers
 7require root permissions (e.g. ports < 1024), or if you run into compatibility
 8issues with non-podman clients, you can switch using the following command:
 9
10 podman machine set --rootful
11
12API forwarding listening on: /Users/xzeu/.local/share/containers/podman/machine/podman-machine-default/podman.sock
13
14The system helper service is not installed; the default Docker API socket
15address can't be used by podman. If you would like to install it run the
16following commands:
17
18 sudo /usr/local/Homebrew/Cellar/podman/4.1.1/bin/podman-mac-helper install
19 podman machine stop; podman machine start
20
21You can still connect Docker API clients by setting DOCKER_HOST using the
22following command in your terminal session:
23
24 export DOCKER_HOST='unix:///Users/xzeu/.local/share/containers/podman/machine/podman-machine-default/podman.sock'
25
26Machine "podman-machine-default" started successfully
  • RHEL 7
1sudo subscription-manager repos --enable=rhel-7-server-extras-rpms 
2sudo yum -y install podman 
  • Arch Linux
1sudo pacman -S podman

更多系统的安装方法,可参考官方文档:https://github.com/containers/libpod/blob/master/install.md

4. 使用 Podman

使用Podman 非常的简单,Podman 的指令跟 Docker 大多数都是相同的。下面我们来看几个常用的例子:

运行一个容器

1$ podman run -dt -p 8080:8080/tcp  \ 
2-e HTTPD_VAR_RUN=/var/run/httpd  \ 
3-e HTTPD_MAIN_CONF_D_PATH=/etc/httpd/conf.d \ 
4-e HTTPD_MAIN_CONF_PATH=/etc/httpd/conf \ 
5-e HTTPD_CONTAINER_SCRIPTS_PATH=/usr/share/container-scripts/httpd/ \ 
6registry.fedoraproject.org/f27/httpd /usr/bin/run-httpd 

4.1. 列出运行的容器

1podman ps -a 

4.2. 分析一个运行的容器

1$ podman inspect -l | grep IPAddress\": 
2"SecondaryIPAddresses": null, 
3"IPAddress": "", 

4.3. 查看一个运行中容器的日志

1$ sudo podman logs --latest 
210.88.0.1 - - [07/Feb/2018:15:22:11 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.55.1" "-" 
310.88.0.1 - - [07/Feb/2018:15:22:30 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.55.1" "-" 
410.88.0.1 - - [07/Feb/2018:15:22:30 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.55.1" "-" 
510.88.0.1 - - [07/Feb/2018:15:22:31 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.55.1" "-" 
610.88.0.1 - - [07/Feb/2018:15:22:31 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.55.1" "-" 

4.4. 查看一个运行容器中的进程资源使用情况

1$ sudo podman top <container_id> 
2  UID   PID  PPID  C STIME TTY          TIME CMD 
3    0 31873 31863  0 09:21 ?        00:00:00 nginx: master process nginx -g daemon off; 
4  101 31889 31873  0 09:21 ?        00:00:00 nginx: worker process 

4.5. 停止一个运行中的容器

1sudo podman stop --latest 

4.6. 删除一个容器

1sudo podman rm --latest 

以上这些特性基本上都和 Docker 一样,Podman 除了兼容这些特性外,还支持了一些新的特性。

4.7. 给容器设置一个检查点

1sudo podman container checkpoint <container_id> 

需要 CRIU 3.11 以上版本支持,CRIU 项目地址:https://criu.org/

4.8. 根据检查点位置恢复容器

1sudo podman container restore <container_id> 

4.9. 迁移容器

Podman 支持将容器从一台机器迁移到另一台机器。

首先,在源机器上对容器设置检查点,并将容器打包到指定位置。

1sudo podman container checkpoint <container_id> -e /tmp/checkpoint.tar.gz 
2scp /tmp/checkpoint.tar.gz <destination_system>:/tmp

其次,在目标机器上使用源机器上传输过来的打包文件对容器进行恢复。

1sudo podman container restore -i /tmp/checkpoint.tar.gz 

4.10. 配置别名

如果习惯了使用 Docker 命令,可以直接给 Podman 配置一个别名来实现无缝转移。你只需要在 .bashrc 下加入以下行内容即可:

1echo "alias docker=podman" >> .bashrc 
2source .bashrc

4.11. Podman 如何实现开机重启容器

由于 Podman 不再使用守护进程管理服务,所以不能通过守护进程去实现自动重启容器的功能。那如果要实现开机自动重启容器,又该如何实现呢?

其实方法很简单,现在大多数系统都已经采用 Systemd 作为守护进程管理工具。这里我们就可以使用 Systemd 来实现 Podman 开机重启容器,这里我们以启动一个 Nginx容器为例子。

首先,我们先运行一个 Nginx 容器。

1sudo podman run -t -d -p 80:80 --name nginx nginx 

然后,在建立一个 Systemd 服务配置文件。

 1$ vim /etc/systemd/system/nginx_container.service 
 2 
 3[Unit] 
 4Description=Podman Nginx Service 
 5After=network.target 
 6After=network-online.target 
 7 
 8[Service] 
 9Type=simple 
10ExecStart=/usr/bin/podman start -a nginx 
11ExecStop=/usr/bin/podman stop -t 10 nginx 
12Restart=always 
13 
14[Install] 
15WantedBy=multi-user.target

接下来,启用这个 Systemd 服务。

1sudo systemctl daemon-reload 
2sudo systemctl enable nginx_container.service 
3sudo systemctl start nginx_container.service

服务启用成功后,我们可以通过 systemctl status 命令查看到这个服务的运行状况。

 1$ sudo systemctl status nginx_container.service 
 2  nginx_container.service - Podman Nginx Service 
 3   Loaded: loaded (/etc/systemd/system/nginx_container.service; enabled; vendor preset: disabled) 
 4   Active: active (running) since Sat 2019-08-20 20:59:26 UTC; 1min 41s ago 
 5 Main PID: 845 (podman) 
 6    Tasks: 16 (limit: 4915) 
 7   Memory: 37.6M 
 8   CGroup: /system.slice/nginx_container.service 
 9           └─845 /usr/bin/podman start -a nginx 
10
11Aug 20 20:59:26 Ubuntu-dev.novalocal systemd[1]: Started Podman Nginx Service. 

之后每次系统重启后 Systemd 都会自动启动这个服务所对应的容器。