关于容器:Docker-大势已去Podman-即将崛起

4次阅读

共计 11976 个字符,预计需要花费 30 分钟才能阅读完成。

Podman 简介

什么是 Podman?

Podman 是一个开源的容器运行时我的项目,可在大多数 Linux 平台上应用。Podman 提供与 Docker 十分类似的性能。正如后面提到的那样,它不须要在你的零碎上运行任何守护过程,并且它也能够在没有 root 权限的状况下运行。

Podman 能够治理和运行任何合乎 OCI(Open Container Initiative)标准的容器和容器镜像。Podman 提供了一个与 Docker 兼容的命令行前端来治理 Docker 镜像。

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

Podman 和 Docker 的次要区别是什么?
  • dockers 在实现 CRI 的时候,它须要一个守护过程,其次须要以 root 运行,因而这也带来了安全隐患。
  • podman 不须要守护程序,也不须要 root 用户运行,从逻辑架构上,比 docker 更加正当。
  • 在 docker 的运行体系中,须要多个 daemon 能力调用到 OCI 的实现 RunC。
  • 在容器治理的链路中,Docker Engine 的实现就是 dockerd
  • daemon,它在 linux 中须要以 root 运行,dockerd 调用 containerd,containerd 调用 containerd-shim,而后能力调用 runC。顾名思义 shim 起的作用也就是“垫片”,防止父过程退出影响容器的运训
  • podman 间接调用 OCI,runtime(runC),通过 common 作为容器过程的管理工具,但不须要 dockerd 这种以 root 身份运行的守护过程。
  • 在 podman 体系中,有个称之为 common 的守护过程,其运行门路通常是 /usr/libexec/podman/conmon,它是各个容器过程的父过程,每个容器各有一个,common 的父则通常是 1 号过程。podman 中的 common 其实相当于 docker 体系中的 containerd-shim。

图中所体现的事件是,podman 不须要守护过程,而 dorker 须要守护过程。在这个图的示意中,dorcker 的 containerd-shim 与 podman 的 common 被归在 Container 一层。

Podman 的应用与 docker 有什么区别?

podman 的定位也是与 docker 兼容,因而在应用下面尽量凑近 docker。在应用方面,能够分成两个方面来说,一是零碎构建者的角度,二是使用者的角度。

在零碎构建者方面,用 podman 的默认软件,与 docker 的区别不大,只是在过程模型、过程关系方面有所区别。如果习惯了 docker 几个关联过程的调试办法,在 podman 中则须要适应。能够通过 pstree 命令查看过程的树状构造。总体来看,podman 比 docker 要简略。因为 podman 比 docker 少了一层 daemon,因而重启的机制也就不同了。

在使用者方面,podman 与 docker 的命令根本兼容,都包含容器运行时(run/start/kill/ps/inspect),本地镜像(images/rmi/build)、镜像仓库(login/pull/push)等几个方面。因而 podman 的命令行工具与 docker 相似,比方构建镜像、启停容器等。甚至能够通过 alias docker=podman 能够进行替换。因而,即使应用了 podman,依然能够应用 docker.io 作为镜像仓库,这也是兼容性最要害的局部。

Podman 常用命令

容器
podman run           创立并启动容器
podman start       #启动容器
podman ps          #查看容器
podman stop        #终止容器
podman restart     #重启容器
podman attach      #进入容器
podman exec        #进入容器
podman export      #导出容器
podman import      #导入容器快照
podman rm          #删除容器
podman logs        #查看日志
镜像
podman search             #检索镜像
docke pull                #获取镜像
podman images             #列出镜像
podman image Is           #列出镜像
podman rmi                #删除镜像
podman image rm           #删除镜像
podman save               #导出镜像
podman load               #导入镜像
podmanfile                #定制镜像(三个)podman build              #构建镜像
    podman run              #运行镜像
    podmanfile              #罕用指令(四个)COPY                    #复制文件
        ADD                     #高级复制
        CMD                     #容器启动命令
        ENV                     #环境变量
        EXPOSE                  #裸露端口

部署 Podman

// 装置 podman
[root@localhost ~]# yum -y install podman

// 仓库配置
[root@localhost ~]# vim /etc/containers/registries.conf
[registries.search]
registries = ['registry.access.redhat.com', 'registry.redhat.io', 'docker.io'] // 这个是查找,从这三个中央查找,如果只留一个,则只在一个源里查找
unqualified-search-registries = ["registry.fedoraproject.org", "registry.access.redhat.com", "registry.centos.org", "docker.io"] // 这里也要改为一个

[registries.insecure]
registries = [10.0.0.1]   // 这里写那些 http 的仓库,比方 harbor

// 配置加速器
[registries.search]
registries = ['https://l9h8fu9j.mirror.aliyuncs.com','docker.io']

应用 Podman

应用 Podman 十分的简略,Podman 的指令跟 Docker 大多数都是雷同的。上面咱们来看几个罕用的例子:

运行一个容器
[root@localhost ~]# podman run -d --name httpd docker.io/library/httpd
Trying to pull docker.io/library/httpd...
Getting image source signatures
Copying blob e5ae68f74026 done  
Copying blob d3576f2b6317 done  
Copying blob bc36ee1127ec done  
Copying blob f1aa5f54b226 done  
Copying blob aa379c0cedc2 done  
Copying config ea28e1b82f done  
Writing manifest to image destination
Storing signatures
0492e405b9ecb05e6e6be1fec0ac1a8b6ba3ff949df259b45146037b5f355035

// 查看镜像
[root@localhost ~]# podman images
REPOSITORY                  TAG      IMAGE ID       CREATED       SIZE
docker.io/library/httpd     latest   ea28e1b82f31   11 days ago   148 MB
列出运行的容器
[root@localhost ~]# podman ps
CONTAINER ID  IMAGE                             COMMAND           CREATED             STATUS                 PORTS  NAMES
0492e405b9ec  docker.io/library/httpd:latest    httpd-foreground  About a minute ago  Up About a minute ago         httpd

留神:如果在 ps 命令中增加 -a,Podman 将显示所有容器。

查看正在运行的容器

您能够“查看”正在运行的容器的元数据和无关其本身的详细信息。咱们甚至能够应用 inspect 子命令查看调配给容器的 IP 地址。因为容器以无根模式运行,因而未调配 IP 地址,并且该值将在查看的输入中列为“无”。

[root@localhost ~]# podman inspect -l | grep IPAddress\":"SecondaryIPAddresses": null,"IPAddress":"10.88.0.5",

[root@localhost ~]# curl 10.88.0.5
<html><body><h1>It works!</h1></body></html>

留神:-l 是最新容器的便当参数。您还能够应用容器的 ID 代替 -l。

查看一个运行中容器的日志
选项
    --latest        #最近的
    
[root@localhost ~]# podman logs --latest
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.88.0.5. Set the'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.88.0.5. Set the'ServerName' directive globally to suppress this message
[Mon Dec 13 15:17:53.690844 2021] [mpm_event:notice] [pid 1:tid 140665160166720] AH00489: Apache/2.4.51 (Unix) configured -- resuming normal operations
[Mon Dec 13 15:17:53.690946 2021] [core:notice] [pid 1:tid 140665160166720] AH00094: Command line: 'httpd -D FOREGROUND'
10.88.0.1 - - [13/Dec/2021:15:19:48 +0000] "GET / HTTP/1.1" 200 45
10.88.0.1 - - [13/Dec/2021:15:20:47 +0000] "GET / HTTP/1.1" 200 45
查看一个运行容器中的过程资源应用状况

能够应用 top 察看容器中的 nginx pid

语法:

    podman top <container_id>  
[root@localhost ~]# podman top httpd
USER       PID   PPID   %CPU    ELAPSED            TTY   TIME   COMMAND
root       1     0      0.000   15m38.599711321s   ?     0s     httpd -DFOREGROUND 
www-data   7     1      0.000   15m38.599783256s   ?     0s     httpd -DFOREGROUND 
www-data   8     1      0.000   15m38.599845342s   ?     0s     httpd -DFOREGROUND 
www-data   9     1      0.000   15m38.599880444s   ?     0s     httpd -DFOREGROUND 
进行一个运行中的容器
[root@localhost ~]# podman stop --latest
2f3edf712621d3a41e03fa8c7f6a5cdba56fbbad43a7a59ede26cc88f31006c4
[root@localhost ~]# podman ps
CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES
删除一个容器
[root@localhost ~]# podman rm --latest
2f3edf712621d3a41e03fa8c7f6a5cdba56fbbad43a7a59ede26cc88f31006c4
[root@localhost ~]# podman ps -a
CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES

以上这些个性基本上都和 Docker 一样,Podman 除了兼容这些个性外,还反对了一些新的个性。

上传镜像

例如,如果咱们想在 docker.io 上分享咱们新建的 Nginx 容器镜像,这很容易。首先登录码头:

[root@localhost nginx]# tree 
.
├── Dockerfile
└── files
    └── nginx-1.20.1.tar.gz

[root@localhost nginx]# cat Dockerfile 
FROM docker.io/library/centos

ENV PATH /usr/local/nginx/sbin:$PATH
ADD files/nginx-1.20.1.tar.gz /usr/src
RUN useradd -r -M -s /sbin/nologin nginx && \
    yum -y install pcre-devel openssl openssl-devel gd-devel gcc gcc-c++ make && \
    mkdir -p /var/log/nginx && \
    cd /usr/src/nginx-1.20.1 && \
    ./configure \
    --prefix=/usr/local/nginx \
    --user=nginx \
    --group=nginx \
    --with-debug \
    --with-http_ssl_module \
    --with-http_realip_module \
    --with-http_image_filter_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_stub_status_module \
    --http-log-path=/var/log/nginx/access.log \
    --error-log-path=/var/log/nginx/error.log && \
  make && make install

CMD ["nginx","-g","daemon off"]
[root@localhost nginx]# podman build -t nginx .
// 批改镜像名
 [root@localhost ~]# podman tag docker.io/library/nginx:latest docker.io/1314444/test:latest

// 登录并上传镜像
[root@localhost ~]# podman login docker.io // 须要通知其要登录到 docker 仓库
[root@localhost ~]# podman login docker.io
Username: 1314444        #账户
Password: ********        #明码
Login Succeeded!

[root@localhost nginx]# podman push docker.io/1314444/test:latest  // 上传镜像
Getting image source signatures
Copying blob 38c40d6c2c85 done
Copying blob fee76a531659 done
Copying blob c2adabaecedb done
Copying config 7f3589c0b8 done
Writing manifest to image destination
Copying config 7f3589c0b8 done
Writing manifest to image destination
Storing signatures


// 请留神,咱们将四层推送到咱们的注册表,当初可供其他人共享。疾速浏览一下:[root@localhost ~]# podman inspect 1314444/test:nginx
// 输入:[
    {
        "Id": "7f3589c0b8849a9e1ff52ceb0fcea2390e2731db9d1a7358c2f5fad216a48263",
        "Digest": "sha256:7822b5ba4c2eaabdd0ff3812277cfafa8a25527d1e234be028ed381a43ad5498",
        "RepoTags": [
            "docker.io/1314444/test:nginx",
        ......

总而言之,Podman 使查找、运行、构建和共享容器变得容易

配置别名

如果习惯了应用 Docker 命令,能够间接给 Podman 配置一个别名来实现无缝转移。你只须要在 .bashrc 下退出以下行内容即可:

[root@localhost ~]# echo "alias docker=podman" >> .bashrc
source .bashrc
[root@localhost ~]# alias
alias cp='cp -i'
alias docker='podman'
.......
用户操作

在容许没有 root 特权的用户运行 Podman 之前,管理员必须装置或构建 Podman 并实现以下配置。

cgroup V2Linux 内核性能容许用户限度普通用户容器能够应用的资源,如果应用 cgroupV2 启用了运行 Podman 的 Linux 发行版,则可能须要更改默认的 OCI 运行时。某些较旧的版本 runc 不适用于 cgroupV2,必须切换到备用 OCI 运行时 crun。

[root@localhost ~]# yum -y install crun     //centos8 零碎自带

[root@localhost ~]# vi /usr/share/containers/containers.conf 
    446 # Default OCI runtime
    447 # 
    448 runtime = "crun"      // 勾销正文并将 runc 改为 crun

[root@localhost ~]# podman run -d --name web -p 80:80 docker.io/library/nginx
c8664d2e43c872e1e5219f82d41f63048ed3a5ed4fb6259c225a14d6c243677f

[root@localhost ~]# podman inspect web | grep crun
        "OCIRuntime": "crun",
            "crun",
装置 slirp4netns 和 fuse-overlayfs

在普通用户环境中应用 Podman 时,倡议应用 fuse-overlayfs 而不是 VFS 文件系统,至多须要版本 0.7.6。当初新版本默认就是了。

[root@localhost ~]# yum -y install slirp4netns

[root@localhost ~]# yum -y install fuse-overlayfs
[root@localhost ~]# vi /etc/containers/storage.conf
77 mount_program = "/usr/bin/fuse-overlayfs"     // 勾销正文
/etc/subuid 和 /etc/subgid 配置

Podman 要求运行它的用户在 /etc/subuid/etc/subgid文件中列出一系列 UID,shadow-utils 或 newuid 包提供这些文件

[root@localhost ~]# yum -y install shadow-utils

能够在 /etc/subuid 和 /etc/subgid 查看,每个用户的值必须惟一且没有任何重叠。

[root@localhost ~]# useradd zz
[root@localhost ~]# cat /etc/subuid
zz:100000:65536
[root@localhost ~]# cat /etc/subgid
zz:100000:65536

// 启动非特权 ping 
[root@localhost ~]# sysctl -w "net.ipv4.ping_group_range=0 200000" // 大于 100000 这个就示意 tom 能够操作 podman
net.ipv4.ping_group_range = 0 200000

这个文件的格局是 USERNAME:UID:RANGE

  • 中 /etc/passwd 或输入中列出的用户名 getpwent。
  • 为用户调配的初始 UID。
  • 为用户调配的 UID 范畴的大小。

该 usermod 程序可用于为用户调配 UID 和 GID,而不是间接更新文件。

[root@localhost ~]# usermod --add-subuids 200000-201000 --add-subgids 200000-201000 hh
grep hh /etc/subuid /etc/subgid
/etc/subuid:hh:200000:1001
/etc/subgid:hh:200000:1001
用户配置文件

三个次要的配置文件是 container.conf、storage.confregistries.conf。用户能够依据须要批改这些文件。

  • container.conf

    // 用户配置文件
    [root@localhost ~]# cat /usr/share/containers/containers.conf
    [root@localhost ~]# cat /etc/containers/containers.conf
    [root@localhost ~]# cat ~/.config/containers/containers.conf  // 优先级最高

    如果它们以该程序存在。每个文件都能够笼罩特定字段的前一个文件。

  • 配置 storage.conf 文件

    1./etc/containers/storage.conf
    2.$HOME/.config/containers/storage.conf

    在普通用户中 /etc/containers/storage.conf 的一些字段将被疏忽

    [root@localhost ~]#  vi /etc/containers/storage.conf
    [storage]
    
    # Default Storage Driver, Must be set for proper operation.
    driver = "overlay"        #此处改为 overlay
    .......
    mount_program = "/usr/bin/fuse-overlayfs"        #勾销正文
    
    [root@localhost ~]# sysctl user.max_user_namespaces=15000  #如果版本为 8 以下,则须要做以下操作:

    在普通用户中这些字段默认

    graphroot="$HOME/.local/share/containers/storage"
    runroot="$XDG_RUNTIME_DIR/containers"
  • registries.conf

配置按此程序读入, 这些文件不是默认创立的, 能够从 /usr/share/containers 或复制文件 /etc/containers 并进行批改。

1./etc/containers/registries.conf
2./etc/containers/registries.d/*
3.HOME/.config/containers/registries.conf
受权文件

此文件外面写了 docker 账号的明码,以加密形式显示

[root@localhost ~]# podman login
Username: 1314444
Password: 
Login Succeeded!
[root@localhost ~]# cat /run/user/0/containers/auth.json 
{
        "auths": {
                "registry.fedoraproject.org": {"auth": "MTMxNDQ0NDpIMjAxNy0xOA=="}
        }
}

普通用户是无奈看见 root 用户的镜像的

//root 用户
[root@localhost ~]# podman images
REPOSITORY                  TAG      IMAGE ID       CREATED       SIZE
docker.io/library/httpd     latest   ea28e1b82f31   11 days ago   146 MB

// 普通用户
[root@localhost ~]# su - zz
[zz@localhost ~]$ podman images
REPOSITORY  TAG         IMAGE ID    CREATED     SIZE

  • 容器与 root 用户一起运行,则 root 容器中的用户实际上就是主机上的用户。
  • UID GID 是在 /etc/subuid 和 /etc/subgid 等中用户映射中指定的第一个 UID GID。
  • 如果普通用户的身份从主机目录挂载到容器中,并在该目录中以根用户身份创立文件,则会看到它实际上是你的用户在主机上领有的。
应用卷
[root@localhost ~]# su - zz
[zz@localhost ~]$ pwd
/home/zz
[zz@localhost ~]$ mkdir /home/zz/data

[zz@localhost ~]$ podman run -it -v "$(pwd)"/data:/data docker.io/library/busybox /bin/sh
Trying to pull docker.io/library/busybox:latest...
Getting image source signatures
Copying blob 3cb635b06aa2 done  
Copying config ffe9d497c3 done  
Writing manifest to image destination
Storing signatures
/ # ls
bin   data  dev   etc   home  proc  root  run   sys   tmp   usr   var
/ # cd data/
/data # ls
/data # touch 123
/data # ls -l
total 0
-rw-r--r--    1 root     root             0 Dec 13 00:17 123
在主机上查看
[zz@localhost ~]$ ll data/
总用量 0
-rw-r--r-- 1 zz zz 0 12 月 13 00:17 123

// 写入文件
[zz@localhost ~]$ echo "hell world" >> 123
[zz@localhost ~]$ cat 123
hell world
容器里查看
/data # cat 123
hell world

// 咱们能够发现在容器外面的文件的属主和属组都属于 root,那么如何能力让其属于 tom 用户呢?上面通知你答案
/data # ls -l
total 4
-rw-rw-r--    1 root     root            12 Dec 13 00:20 123

// 只有在运行容器的时候加上一个 --userns=keep-id 即可。[zz@localhost ~]$ podman run -it --name test -v "$(pwd)"/data:/data --userns=keep-id docker.io/library/busybox /bin/sh
~ $ cd data/
/data $ ls -l
total 4
-rw-r--r--    1 zz       zz              11 Dec 13 00:21 123

应用普通用户映射容器端口时会报“permission denied”的谬误

[zz@localhost ~]$ podman run  -d -p 80:80 httpd
Error: rootlessport cannot expose privileged port 80, you can add 'net.ipv4.ip_unprivileged_port_start=80' to /etc/sysctl.conf (currently 1024), or choose a larger port number (>= 1024): listen tcp 0.0.0.0:80: bind: permission denied

普通用户能够映射 >= 1024 的端口

[zz@localhost ~]$ podman run  -d -p 1024:80 httpd
58613a6bdc70d4d4f9f624583f795a62a610596d166f0873bdff8fb26aa15092
[zz@localhost ~]$ ss -anlt
State       Recv-Q      Send-Q           Local Address:Port           Peer Address:Port      Process      
LISTEN      0           128                    0.0.0.0:22                  0.0.0.0:*                      
LISTEN      0           128                          *:1024                      *:*                      
LISTEN      0           128                       [::]:22                     [::]:* 

配置 echo‘net.ipv4.ip_unprivileged_port_start=80’>> /etc/sysctl.conf 后能够映射大于等于 80 的端口

[root@localhost ~]# echo  'net.ipv4.ip_unprivileged_port_start=80'  >> /etc/sysctl.conf
[root@localhost ~]# sysctl -p
net.ipv4.ip_unprivileged_port_start = 80

[zz@localhost ~]$ podman run -d -p 80:80 httpd
1215455a0c300d78e7bf6afaefc9873f818c6b0f26affeee4e2bc17954e72d8e
[zz@localhost ~]$ ss -anlt
State       Recv-Q      Send-Q           Local Address:Port           Peer Address:Port      Process      
LISTEN      0           128                    0.0.0.0:22                  0.0.0.0:*                      
LISTEN      0           128                          *:1024                      *:*                      
LISTEN      0           128                          *:80                        *:*                      
LISTEN      0           128                       [::]:22                     [::]:*  

链接:https://blog.csdn.net/qq_4828…

正文完
 0