Docker 和 Podman的区别

安装

Docker安装官方文档

Podman安装官方文档

架构和特权要求

image-20240415183715593

Docker使用client-server架构,其中Docker daemon(服务端)在后台以root权限运行,并通过Docker客户端与之交互。这意味着使用Docker需要root权限或者给用户添加到docker用户组中

[root@docker ~]# ps -ef |grep docker
root        5131       1  0 16:30 ?        00:00:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock   # Docker deamon
root        5768    3870  0 18:27 pts/0    00:00:00 grep --color=auto docker

[csq@docker ~]$ sudo docker version
Client: Docker Engine - Community  # 要使用这个Client需要root权限或者给用户添加到docker用户组里
 Version:           26.0.1
 API version:       1.45
 Go version:        go1.21.9
 Git commit:        d260a54
 Built:             Thu Apr 11 10:54:59 2024
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community   # 这个就是docker deamon,就是后台启用的进程
 Engine:
  Version:          26.0.1
  API version:      1.45 (minimum version 1.24)
  Go version:       go1.21.9
  Git commit:       60b9add
  Built:            Thu Apr 11 10:53:19 2024
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.31
  GitCommit:        e377cd56a71523140ca6ae87e30244719194a521
 runc:
  Version:          1.1.12
  GitCommit:        v1.1.12-0-g51d5e94
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Podman是一个无守护进程的容器运行时,可以在非特权用户下运行,无需特殊权限

[csq@podman ~]$ ps -ef |grep podman  # podman无守护进程(daemon)
csq         5445    5411  0 18:53 pts/0    00:00:00 grep --color=auto podman
[csq@podman ~]$ podman version
Client:       Podman Engine
Version:      4.9.4-dev
API Version:  4.9.4-dev
Go Version:   go1.21.7 (Red Hat 1.21.7-1.el9)
Built:        Wed Mar 20 18:22:46 2024
OS/Arch:      linux/amd64

运行容器方面

docker

[csq@docker ~]$ sudo docker run -it busybox  # 普通用户要加上sudo才行
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
7b2699543f22: Pull complete 
Digest: sha256:c3839dd800b9eb7603340509769c43e146a74c63dca3045a8e7dc8ee07e53966
Status: Downloaded newer image for busybox:latest
/ # ls
bin    dev    etc    home   lib    lib64  proc   root   sys    tmp    usr    var
/ # 

podman

[csq@podman ~]$ podman run -it busybox       # 普通用户可以直接执行            
Resolved "busybox" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/busybox:latest...
Getting image source signatures
Copying blob 7b2699543f22 done   | 
Copying config ba5dc23f65 done   | 
Writing manifest to image destination
/ # ls
bin    dev    etc    home   lib    lib64  proc   root   run    sys    tmp    usr    var
/ # 

安全性(root的权限)

Docker在默认配置下需要root权限或者特权用户访问,这会增加潜在的安全风险。但可以通过配置用户命名空间和其他安全措施来提高安全性

[demo@docker ~]$ groups   # demo用户在docker组里
demo docker
[demo@docker ~]$ sudo more /etc/sudoers  # 不具有sudo的权限
[sudo] demo 的密码:
demo 不在 sudoers 文件中。此事将被报告。
[demo@docker ~]$ docker version  # 可以执行docker命令
Client: Docker Engine - Community
 Version:           26.0.1
 API version:       1.45
 Go version:        go1.21.9
 Git commit:        d260a54
 Built:             Thu Apr 11 10:54:59 2024
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          26.0.1
  API version:      1.45 (minimum version 1.24)
  Go version:       go1.21.9
  Git commit:       60b9add
  Built:            Thu Apr 11 10:53:19 2024
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.31
  GitCommit:        e377cd56a71523140ca6ae87e30244719194a521
 runc:
  Version:          1.1.12
  GitCommit:        v1.1.12-0-g51d5e94
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
# 将sudoers文件挂载出来,并把自己添加到sudoers当中
[demo@docker ~]$ docker run -it -v /etc/sudoers:/root/sudoers busybox sh
/ # cd /root/
~ # ls
sudoers
~ # more sudoers 
Defaults   !visiblepw
Defaults    always_set_home
Defaults    match_group_by_gid
Defaults    always_query_group_plugin
Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
Defaults    env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin
root    ALL=(ALL)       ALL
%wheel  ALL=(ALL)       ALL
csq     ALL=(ALL)       ALL
~ # vi  sudoers   # 将自己添加进去
demo    ALL=(ALL)       ALL
~ # exit
[demo@docker ~]$ sudo more /etc/sudoers   # 之前不可以查看sudoer,现在就可以查看了  
[sudo] demo 的密码:
Defaults   !visiblepw
Defaults    always_set_home
Defaults    match_group_by_gid
Defaults    always_query_group_plugin
Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
Defaults    env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin
root    ALL=(ALL)       ALL
%wheel  ALL=(ALL)       ALL
csq     ALL=(ALL)       ALL
demo    ALL=(ALL)       ALL

配置用户命名空间

Docker提供了一种称为用户命名空间的安全功能,它使得一个容器中的进程可以运行在一个虚拟的UID/GID空间中,从而将容器中的特权进程与主机系统分离出来,提高容器的安全性

# 第一步:在Docker daemon配置文件(/etc/docker/daemon.json)中加入用户命名空间的配置
{
   "userns-remap": "default"
}
# 这将配置Docker运行用户命名空间,并将容器内的UID/GID映射到主机上的一个非特权用户(default)


# 第二步:配置/etc/subuid和/etc/subgid文件,这些文件定义了用户到UID/GID的映射关系
csq:100000:65536
demo:165536:65536
# 这条配置定义了dockremap用户的UID从100000开始,分配65536个UID
# 同样的,还要为该用户分配一个GID范围


# 第三步:重启Docker daemon,使得配置生效
systemctl restart docker.service
# 此时,Docker容器应用就运行在一个特定用户空间了。


# 第四步:验证用户命名空间
[demo@docker ~]$ docker run -it -v /etc/sudoers:/root/sudoers busybox sh
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
7b2699543f22: Pull complete 
Digest: sha256:c3839dd800b9eb7603340509769c43e146a74c63dca3045a8e7dc8ee07e53966
Status: Downloaded newer image for busybox:latest
/ # more /root/sudoers 
more: /root/sudoers: Permission denied  # 看不到了
/ # 


# 如果还是希望root用户来启动容器呢,可以使用--userns=host来解决
[demo@docker ~]$ docker run -it --userns=host  -v /etc/sudoers:/root/sudoers busybox sh 
/ # more /root/sudoers 
Defaults   !visiblepw
Defaults    always_set_home
Defaults    match_group_by_gid
Defaults    always_query_group_plugin
Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
Defaults    env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin
root    ALL=(ALL)       ALL
%wheel  ALL=(ALL)       ALL
csq     ALL=(ALL)       ALL
# 此时,容器root用户映射到宿主root用户,容器普通用户映射到宿主普通用户
# 等同于不使用User Namespace的默认情况

Podman可以在非特权用户下运行,并使用用户命名空间、Linux安全模块(如SELinux)等技术来提供更强的容器安全性

[csq@podman ~]$ podman run -it -v /etc/sudoers:/root/sudoers busybox sh
/ # cd /root/
~ # ls
sudoers
~ # more sudoers   # 无法进行修改
more: sudoers: Permission denied

镜像管理方面

Docker可以通过Docker Hub等公共或私有镜像仓库来获取和分享镜像

[csq@docker ~]$ sudo docker pull nginx
[sudo] csq 的密码:
Using default tag: latest
latest: Pulling from library/nginx
13808c22b207: Pull complete 
6fcdffcd79f0: Pull complete 
fbf231d461b3: Pull complete 
c9590dd9c988: Pull complete 
b4033143d859: Pull complete 
abaefc5fcbde: Pull complete 
bcef83155b8b: Pull complete 
Digest: sha256:9ff236ed47fe39cf1f0acf349d0e5137f8b8a6fd0b46e5117a401010e56222e1
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest  # 通过Docker Hub获取镜像

与Docker兼容的Podman可以直接使用Docker镜像,但它还支持OCI(Open Container Initiative)标准的镜像

[csq@podman ~]$ podman pull nginx
? Please select an image: 
  ▸ registry.access.redhat.com/nginx:latest  # 通过上下左右来确定通过哪个registry拉取image
    registry.redhat.io/nginx:latest
    docker.io/library/nginx:latest
✔ docker.io/library/nginx:latest      # 选择Docker Hub仓库来获取镜像
Trying to pull docker.io/library/nginx:latest...
Getting image source signatures
Copying blob abaefc5fcbde done   | 
Copying blob 13808c22b207 done   | 
Copying blob fbf231d461b3 done   | 
Copying blob 6fcdffcd79f0 done   | 
Copying blob c9590dd9c988 done   | 
Copying blob b4033143d859 done   | 
Copying blob bcef83155b8b done   | 
Copying config c613f16b66 done   | 
Writing manifest to image destination
c613f16b664244b150d1c3644cbc387ec1fe8376377f9419992280eb4a82ff3b

命令方面

命令方面的话docker和podman两个命令提供的功能大差不差

如果习惯docker,还想使用podman可以使用【alias docker=podman】命令别名

[csq@podman ~]$ alias docker=podman

Docker常用命令

管理容器(Containers):

  • docker create:创建一个新的容器但不启动它。

  • docker run:创建并启动一个新的容器。

  • docker start:启动一个或多个已经创建的容器。

  • docker stop:停止一个或多个正在运行的容器。

  • docker restart:重启一个或多个容器。

  • docker pause:暂停一个容器的所有进程。

  • docker unpause:取消暂停一个容器的所有进程。

  • docker kill:杀死一个或多个正在运行的容器。

  • docker rm:删除一个或多个容器。

管理镜像(Images):

  • docker images:列出本地主机上的镜像。

  • docker pull:从远程仓库下载一个镜像。

  • docker build:从Dockerfile构建一个镜像。

  • docker push:将一个本地镜像上传到仓库。

  • docker rmi:删除一个或多个本地镜像。

管理容器资源:

  • docker exec:在运行中的容器中执行命令。

  • docker cp:在容器与本地文件系统之间复制文件。

  • docker logs:查看容器的日志输出。

  • docker stats:显示容器资源的实时统计信息。

管理容器网络(Networking):

  • docker network ls:列出所有网络。

  • docker network create:创建一个网络。

  • docker network connect:将容器连接到一个网络。

  • docker network disconnect:将容器从一个网络断开。

其他常用命令:

  • docker version:显示Docker客户端和服务器的版本信息。

  • docker info:显示Docker系统信息,包括容器、镜像和存储的详细信息。

  • docker inspect:检查容器或镜像的详细配置信息。

Podman常用命令

  • attach: 连接到正在运行的容器以查看其输出和日志。
  • build: 使用 Containerfiles 中的指令构建一个镜像。
  • commit: 基于已更改的容器创建新的镜像。
  • compose: 通过外部提供者(如 docker-compose 或 podman-compose)运行 compose 工作负载。
  • diff: 显示对象文件系统的更改。
  • events: 显示 Podman 系统事件。
  • generate: 基于容器、Pods 或卷生成结构化数据。
  • healthcheck: 管理容器的健康检查。
  • history: 显示指定镜像的历史记录。
  • init: 创建一个或多个容器,但不启动它们。
  • kube: 从结构化文件中运行容器、Pods 或卷。
  • machine: 管理虚拟机。
  • manifest: 操作清单列表和镜像索引。
  • mount: 挂载工作容器的根文件系统。
  • network: 管理网络。
  • port: 列出容器的端口映射或特定映射。
  • push: 将镜像推送到指定的目标。
  • rename: 重命名一个现有容器。
  • rmi: 从本地存储中删除一个或多个镜像。
  • save: 将镜像保存到存档文件中。
  • search: 在镜像仓库中搜索镜像。
  • secret: 管理密钥。
  • tag: 为本地镜像添加额外的名称。
  • unshare: 在修改过的用户命名空间中运行命令。
  • version: 显示 Podman 的版本信息。
  • volume: 管理卷。

内容参考:

https://www.bilibili.com/video/BV1YU4y1p7jG/

https://zhuanlan.zhihu.com/p/607509062#

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐