由于 Docker 在架构上的依赖比较多,存在单点故障,且依赖于特权账号运行,需要启动有 docker 服务,才能运行 docker cli。 出现了很多替代 docker,不依赖于特权账号,普通用户可以跑,也不依赖于后台服务的工具,比如 podman, img 等。

我的Mac 上面的 Docker Desktop 越来越吃 CPU,跑起来机器非常卡顿, 看了几种不同的方案,podman 跟 docker 的兼容性非常好,可以很容易迁移到 podman上,决定从 docker 迁移到 podman。

参考:

Transitioning from Docker to Podman | Red Hat Developer

开始使用

Mac 上面安装 podman, 并启动 podman machine,命令如下。 由于 podman 需要在 linux 上运行,需要启动一个 linux virtual machine,virtual machine 用 qemu 来运行。

brew install qemu
brew install podman

podman machine init --disk-size 80 --memory=4096

podman machine start

alias docker=podman

然后就可以愉快地使用 podman  命令, 或者 docker 命令来操作了。

注意: 这里初始化 podman 机器的时候, 设定了磁盘大小是 80G,内存是 4G。如果小了,后面再跑很麻烦,需要重新初始化。因此初始化的时候就设置好。根据自己机器的情况来设置,我的机器内存是 16G,从中分 4G 到 podman。

本文到此结束。 后面演示一下基于 Alpine 构建一个 nginx http server 基础镜像的手工过程(自动的过程使用 Dockerfile),手工的过程可以体验一下 docker commit 的使用。

基于 Alpine 构建一个 nginx HTTP 镜像

参考前面链接的文档,我们把 apache httpd 替换成 nginx web 服务,来构建一个静态web 服务器的镜像,并且使用镜像启动容器。 如下的内容既适用于 podman, 也适用于 docker。 前面我们做了 alias docker=podman

1). 首先拉取到 alpine 的镜像:

docker pull alpine:3.15.1

2). 接下来启动一个容器, 交互式的方式(-it)进入到容器中:

podman run -it --name nginx alpine:latest /bin/sh

3). 在容器中安装 curl, nginx, 配置 nginx 的 web root

上面命令进入到启动的 alpine 容器中之后,然后在容器中安装 curl, nginx, 创建存放静态 web 页面的目录 /data/nginx/html。

apk add curl
apk add nginx

mkdir -p /data/nginx/html/
mkdir -p /etc/nginx/conf.d/

我们把 虚拟主机的 nginx conf 配置放在 /etc/nginx/conf.d/ 目录,还是在容器中运行命令, 编辑 /etc/nginx/nginx.conf 文件:

vi /etc/ninx/nginx.conf

在 http 节点的末尾加上配置:

include /etc/nginx/conf.d/*.conf;

然后,在容器中编辑 /etc/nginx/conf.d/nginx.host.default.conf 文件, 设置 /data/nginx/html 为默认的 web 根路径。

$ vim /etc/nginx/conf.d/nginx.host.default.conf 

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;

    location / {
        root   /data/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /data/nginx/html;
    }
}

以上配置使得 nginx 在启动的时候, 会监听本机的 localhost:80 端口,为 /data/nginx/html 目录提供静态页面的 http 访问服务。

接下来 Web 站创建一个首页文件:

echo "hello nginx" > /data/nginx/index.html

启动 nginx, 测试 web 页:

nginx

curl http://localhost

能看到输出 hello world。 在如上命令运行完之后,运行 exit 或者 Ctrl + D 退出正在运行的容器。

4). 退出容器,提交镜像

## 提交手工构建的镜像
docker commit nginx nginx:v1

## 列出镜像
docker images

能看到下面的内容
REPOSITORY                TAG         IMAGE ID      CREATED        SIZE
localhost/nginx           v1          2b33eaf5cf67  6 seconds ago  12 MB
docker.io/library/alpine  3.15.1      e9adb5357e84  23 hours ago   5.86 MB

5).使用构建的镜像启动新容器,端口映射到本机

使用如下命令, 基于镜像 nginx:v1 启动容器, 把容器中的 80 端口映射到本机的 8080。

后面的 sh -c "nginx && tail -f /dev/null" 表示在容器中带参数执行 sh 这个命令。sh 里面启动 nginx 然后执行一个永远不退出的 tail -f。

podman run -p 8080:80 -dt nginx:v1 sh -c "nginx && tail -f /dev/null"

然后访问 http://localhost:8080 就能看到页面的内容 hello world 了。

使用 Dockerfile 自动构建 nginx 服务基础镜像,可以参考这里: