2-4-4-Docker使用辅助工具汇总

熊 0 阅读 容器

1. 前言简述

描述:本文是笔者在学习或者应用Docker时候 , 对Docker第三方的工具使用的一个简单总结, 使其为了更好的使用docker应用以及优化和异常的快速定位;

2. 镜像相关工具

2.1. Dive - Docker 镜像分析工具

描述:Dive用来分析docker镜像层信息的一个工具 , 该工具主要用于探索docker镜像层内容以及发现减小docker镜像大小的方法。 官方地址 : https://github.com/wagoodman/dive 基本功能 :

  1. 显示Docker图像内容按层分解 : 当您在左侧选择一个层时 , 将在右侧线上显示该层的所有内容 , 此外 , 您可以使用箭头按键来浏览整个文件树内容。

  2. 指出每层中发生了哪些变化 : 在文件树中标明已修改、添加或删除的文件 , 可以调整此值以显示特定层的更改。

  3. 估计"镜像效率" : 左下方窗格显示基本层信息和一个实验指标 , 用于猜测图像所包含的空间浪费。这可能是跨层的一些重复文件 , 跨层移动文件或不完全删除的文件。提供了一个百分比的“得分”和总浪费的文件空间。

  4. 快速构建/分析周期 : 您可以构建docker镜像并使用一个命令立即进行分析dive build -t some-tag .您只需要将docker build命令用相同的dive build命令替换即可。

  5. CI集成 : 根据图像的效率和浪费的空间 , 分析图像并得到通过/失败的结果。在调用任何有效的dive命令时 , 只需在环境中设置CI=true

  6. 支持多个图像源和容器引擎使用—source选项 , 您可以选择从哪里获取容器图像:dive <your-image> --source <source>

我们常常使用inspect与history来查看镜像的相关信息,但是确实不是很直观遍历,我们需要的是一个简单直白的展示:

# inspect 方式看见镜像各层ID
docker inspect gcc -f "{{.RootFS}}{{println}}{{.Metadata}}"
{layers [sha256:6086e1b289d997dfd19df1ec9366541c49f5545520f9dc65ebd4cd64071497b4 sha256:c53d956ebfec691504fc18c964352728214665e7090e4161ed791979cf200ccf sha256:cf47dfabe08113e9ff7d61d096752678caa00a0b861f673c2577ca2fdf55cfe9 sha256:46a297e68c473255e515971ffcb2dc78f724e60214df479a66bb9b04892afc1b sha256:cfb4ccdac2588557024f7741ba447707fc26304e7d84cf53d481671cb4a23f1c sha256:1be02b7a0bbbc4ff6353fe53cf22cefb4a0849a070d032b900dcbf8700a89b9a sha256:8262cc809f2b0add9b633ab30664f95dbb7761fc857ecfaddfa5654ef602fb9a sha256:00e5a2edc2d269fc9e1465be8a3b572d5d0a62cea4510fa5e941f42653287198 sha256:4d619c17b6de41f14d6742dcb6c3ba679ed53bff4ca43e22686a81b4aa8236bd] }
{0001-01-01 00:00:00 +0000 UTC}
​
# history 镜像各层构建时候执行命令查看
docker history gcc
# IMAGE               CREATED             CREATED BY                                      SIZE
# 21f378ba43ec        4 days ago          /bin/sh -c set -ex;  dpkg-divert --divert /u…   12.7kB
# <missing>           4 days ago          /bin/sh -c set -ex;  echo '/usr/local/lib64'…   53.8kB
# <missing>           4 days ago          /bin/sh -c set -ex;   savedAptMark="$(apt-ma…   382MB
# <missing>           4 days ago          /bin/sh -c #(nop)  ENV GCC_VERSION=10.2.0       0B
# <missing>           5 days ago          /bin/sh -c #(nop)  ENV GCC_MIRRORS=https://f…   0B
# <missing>           5 days ago          /bin/sh -c set -ex;  for key in $GPG_KEYS; d…   29.5kB
# <missing>           5 days ago          /bin/sh -c #(nop)  ENV GPG_KEYS=B215C1633BCA…   0B
# <missing>           5 days ago          /bin/sh -c set -ex;  if ! command -v gpg > /…   0B
# <missing>           5 days ago          /bin/sh -c set -ex;  apt-get update;  DEBIAN…   510MB
# <missing>           5 days ago          /bin/sh -c apt-get update && apt-get install…   146MB
# <missing>           5 days ago          /bin/sh -c set -ex;  if ! command -v gpg > /…   17.5MB
# <missing>           5 days ago          /bin/sh -c apt-get update && apt-get install…   16.5MB
# <missing>           6 days ago          /bin/sh -c #(nop)  CMD ["bash"]                 0B
# <missing>           6 days ago          /bin/sh -c #(nop) ADD file:89dfd7d3ed77fd5e0…   114MB

2.1.1 dive安装

下载地址: https://github.com/wagoodman/dive/releases/

  • Ubuntu/Debian

    wget https://github.com/wagoodman/dive/releases/download/v0.9.2/dive_0.9.2_linux_amd64.deb
    sudo apt install ./dive_0.9.2_linux_amd64.deb
  • RHEL/Centos

    curl -OL https://github.com/wagoodman/dive/releases/download/v0.9.2/dive_0.9.2_linux_amd64.rpm
    rpm -i dive_0.9.2_linux_amd64.rpm
  • Arch Linux

    #Available as dive in the Arch User Repository (AUR).
    yay -S dive
  • mac

    brew install dive
  • 镜像安装方式

    docker pull wagoodman/dive

2.1.2 基础用法

分析一个docker 镜像 , 只需要在dive工具后面添加上镜像的tag即可 :

$ dive <镜像TAG>

除此之外还可以新建一个自己的image , 通过build命令去构建docker镜像后 , 直接进入分析结果 :

$ dive build -t <镜像TAG> .
image-20240216235521955

正如你在上面的截图中看到的那样 , 在终端的左边一栏列出了给定Docker镜像的各个层及其详细内容 , 浪费的空间大小等信息。右边一栏则给出了给定Docker镜像每一层的内容。你可以使用 Ctrl+空格 来在左右栏之间切换 , 使用 UP/DOWN 光标键来在目录树中进行浏览。

按键绑定

  • Ctrl + C : 退出

  • Tab : 在左右栏之间切换 , 在图层和文件树视图之间切换

  • Ctrl + F : 过滤文件

  • PageUp : 向上滚动一页

  • PageDown : 向下滚动一页

  • Ctrl + A : 图层视图 , 查看聚合镜像的修改内容

  • Ctrl + L : 图层视图 , 查看当前图层修改

  • Space : 文件树视图 , 折叠/取消折叠目录

  • Ctrl + Space : 文件树视图 , 折叠/取消折叠所有目录

  • Ctrl + A : 文件树视图 , 显示/隐藏添加的文件

  • Ctrl + R : 文件树视图 , 显示/隐藏已删除的文件

  • Ctrl + M : 文件树视图 , 显示/隐藏修改的文件

  • Ctrl + U : 文件树视图 , 显示/隐藏未修改的文件

  • Ctrl + B : 文件树视图 , 显示/隐藏文件属性

  • PageUp : 文件树视图 , 向上滚动页面

  • PageUp : 文件树视图, 向下滚动页面

注意事项 : 根据您在本地运行的docker版本 , 您可能需要指定docker API版本作为环境变量:

docker run --rm -it \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -e DOCKER_API_VERSION=1.37 \
    wagoodman/dive:latest <dive arguments...>

实际案例:

# 1.简单分析实例
$docker images
# REPOSITORY                           TAG                        IMAGE ID            CREATED             SIZE
# go-hello                             latest                     d1bb1eb974f4        19 hours ago        812MB
$docker run --rm -it \
    -v /var/run/docker.sock:/var/run/docker.sock \
    wagoodman/dive:latest go-hello:latest
# Image Source: docker://go-hello:latest
# Fetching image... (this can take a while for large images)
# Analyzing image...
# Building cache...
docker-tools-images-dive-1

2.1.3 CI集成

描述:当运行环境变量CI=true的dive时dive UI将被绕过 , 取而代之的是分析你的docker图像 , 通过返回代码给它一个通过/失败的指示。目前有三个指标支持通过。

下面是dive-ci文件 , 可以采用--ci-config option指定配置文件

rules:
  # 如果效率测量值低于X% , 则标记为失败。表示为0-1之间的比率。
  lowestEfficiency: 0.95

  # If the amount of wasted space is at least X or larger than X, mark as failed.
  # Expressed in B, KB, MB, and GB.
  #如果浪费的空间量至少为X或大于X , 则标记为失败。以B、KB、MB和GB表示。
  highestWastedBytes: 20MB

  # If the amount of wasted space makes up for X% or more of the image, mark as failed.
  # Note: the base image layer is NOT included in the total image size.
  # Expressed as a ratio between 0-1; fails if the threshold is met or crossed.
  #如果浪费的空间占镜像的X%或更多 , 则标记为失败。
  #注意:基本镜像层不包括在总图像大小中。表示为0-1之间的比率;如果达到或超过阈值 , 则失败。
  highestUserWastedPercent: 0.20

2.2 Skopeo - 镜像同步工具

描述: 对容器映像和容器映像注册表的各种操作; 我们从以下的两个利用场景中可以看见看见此工具妙用;

应用场景1 , 如何在机器上pull拉取Registry A Harbor中的镜像 , 然后构造完成后重新打上Tag然后再Push到另外一个registry B Harbor上去,相当于一个同步镜像操作 , 但和harbor里在带的那个镜像同步还有很大的不同 , 我们仅仅需要同步特定tag的镜像 , 而不是整个harbor或者 project 里的全部镜像;目前我们的做法还是最简单的方式 , 使用docker命令行的方式来pull镜像 , 然后打tag接着push到B harbor。但是啊 , 当同步二三百个的镜像 , 或者镜像的总大小几十GB的时候这种原始的方法速度还是太慢了 , 于是就思考有没有另一个工具可以直接将registry A中的某个镜像同步到registry B中去。简单的说使用 skopeo copy 两个registry中的镜像时 , skopeo请求两个registry API直接copy original blob到另一个registry , 这样免去了像docker pull –> docker tag –> docker push 那样pull镜像对镜像进行解压缩 , push镜像进行压缩。尤其是在搬运一些较大的镜像(几GB 或者几十 GB的镜像 , 比如 nvidia/cuda ) , 使用skopeo copy的加速效果十分明显。

应用场景2 , 由于国内拉取某些镜像太不友好 , 则此时采用外网的VPS先进行下载然后再从我们VPS上拉取下载镜像,但是由于VPS本地存储太小而默认docker pull在下载镜像时候利用docker-untar将下载的镜像进行解压并保存在本地docker家目录之中会导致存储不够 , 想象一哈只下载而不解压即减小了包的大小又解压下载传输速度何乐而不为呢?所以得请出本章节的主人公Skopeo镜像工具;

学习了前面的Docker容器镜像仓库存储原理(前世今身)与搬运技巧,我们知道registry中存储的镜像layer压缩包格式是 vnd.docker.image.rootfs.diff.tar.gzip它是一个tar.gz类型的文件;

下面是镜像在Harbor中的存储路径我们可以利用其开探究镜像在Registry中存储的;

  1. harbor的存储目录

    tree
    `-- registry
        `-- v2      # registry V2 版本
            |-- blobs # blobs 目录下存储镜像的 raw 数据 , 存储的最小单元为 layer
            |   `-- sha256
            |       |-- 39
            |       |-- cb
            |       `-- f7
            `-- repositories # 镜像的元数据信息
                `-- library
                    `-- alpine
  2. 镜像的manifest是针对registry服务端的配置信息

    {
       "schemaVersion": 2,
       "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
       "config": {
          "mediaType": "application/vnd.docker.container.image.v1+json",
          "size": 1507,
          "digest": "sha256:f70734b6a266dcb5f44c383274821207885b549b75c8e119404917a61335981a"
       },
       "layers": [
          {
             "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
             "size": 2813316,
             "digest": "sha256:cbdbe7a5bc2a134ca8ec91be58565ec07d037386d1f1d8385412d224deafca08"
          }
       ]
    }
  3. 仔细看一下digest 和下面文件夹的名称 , 他们是一一对应的 , 因为manifest信息就是镜像在registry中存储的信息。

    tree
    |-- [  20]  blobs
    |   `-- [  36]  sha256
    |       |-- [  78]  39
    |       |   `-- [  18]  39eda93d15866957feaee28f8fc5adb545276a64147445c64992ef69804dbf01
    |       |       `-- [ 528]  data
    |       |-- [  78]  cb
    |       |   `-- [  18]  cbdbe7a5bc2a134ca8ec91be58565ec07d037386d1f1d8385412d224deafca08
    |       |       `-- [2.7M]  data
    |       `-- [  78]  f7
    |           `-- [  18]  f70734b6a266dcb5f44c383274821207885b549b75c8e119404917a61335981a
    |               `-- [1.5K]  data
    `-- [  21]  repositories
        `-- [  20]  library
            `-- [  55]  alpine
                |-- [  20]  _layers
                |   `-- [ 150]  sha256
                |       |-- [  18]  cbdbe7a5bc2a134ca8ec91be58565ec07d037386d1f1d8385412d224deafca08
                |       |   `-- [  71]  link
                |       `-- [  18]  f70734b6a266dcb5f44c383274821207885b549b75c8e119404917a61335981a
                |           `-- [  71]  link
                |-- [  35]  _manifests
                |   |-- [  20]  revisions
                |   |   `-- [  78]  sha256
                |   |       `-- [  18]  39eda93d15866957feaee28f8fc5adb545276a64147445c64992ef69804dbf01
                |   |           `-- [  71]  link
                |   `-- [  20]  tags
                |       `-- [  34]  latest
                |           |-- [  18]  current
                |           |   `-- [  71]  link
                |           `-- [  20]  index
                |               `-- [  78]  sha256
                |                   `-- [  18]  39eda93d15866957feaee28f8fc5adb545276a64147445c64992ef69804dbf01
                |                       `-- [  71]  link
                `-- [   6]  _uploads
    26 directories, 8 files

上述中的2.7 MB data文件是一个gzip压缩格式文件 , 我们可以使用tar命令将其解压开来;

cd registry/v2/blobs/sha256/cb/cbdbe7a5bc2a134ca8ec91be58565ec07d037386d1f1d8385412d224deafca08
sh-4.2# file data
data: gzip compressed data
sh-4.2# mkdir layer
sh-4.2# tar -xvf data -C layer/  #解压到 layer 目录下
sh-4.2# tree -L 1 -d layer #  alpine 镜像查看其解压目录您会发现他是一个文件系统
layer
|-- bin
|-- dev
|-- etc
|-- home
|-- lib
|-- media
|-- mnt
|-- opt
|-- proc
|-- root
|-- run
|-- sbin
|-- srv
|-- sys
|-- tmp
|-- usr
`-- var

看了上面的流程此时您或许能够明白在当前仅仅为了同步两个registry上的镜像使用 docker pull –> docker tag –> docker push 操作的弊端; 在Docker pull时镜像会对Registry上的Layer进行下载到本地然后解压,在使用docker pull拉取镜像的时候使用ps 查看一下进程就会找到docker-untar这个进程 , 它的目的是为了减少网络传输的流量以及节约时间;

# 对于一些较大的镜像比如2G以上 , 有时候镜像 layer 已经 download 完了 , 但是还在进行镜像的解压缩 , 性能的瓶颈也就在了解压镜像这一块。
docker-untar /var/lib/docker/overlay2/a076db6567c7306f3cdab6040cd7d083ef6a39d125171353eedbb8bde7f203b4/diff

而Skopeo就是一个可以直接将Registry上的Blob复制到另外一个Registry仓库里 , 中间不涉及对镜像的Layer的解压缩; Skopeo官网地址: https://github.com/containers/skopeo

特点:

  • skopeo是一个命令行实用程序 , 执行对容器的图像和图像库的各种操作。

  • skopeo不要求用户运行 , 作为根用户做它的大部分操作。

  • skopeo不需要守护进程来运行 , 以执行其操作。

  • skopeo可以用OCI图像以及原来的码头工人V2图像工作 , 如docker.io和quay.io登记 , 私人注册 , 本地目录和本地OCI布局目录。

Skopeo可以执行如下的操作:

  • 从和到各种存储机制复制的图像。例如 , 你可以从一个注册表复制到另一个图像 , 而不需要特权。

  • 检查显示出其特性 , 包括其的层的远程图像 , 而无需将Images拉到主机。

  • 从图像库中删除图像。

  • 当需要存放库 , skopeo可以通过身份验证适当凭据和证书。

2.2.1 安装与语法

  • 仓库软件安装

    # yum/dnf/zypper/brew
    sudo dnf install skopeo || sudo yum install skopeo
    
    # openSUSE
    sudo zypper install skopeo
    
    # alpine
    sudo apk add skopeo
    
    # macOS
    brew install skopeo
  • 源码build安装但是需要注意要构建skopeo二进制文件 , 您至少需要Go 1.12。

    git clone https://github.com/containers/skopeo skopeo
    cd !$ && git checkout v1.0.0
    make binary
    # Ubuntu上构建:参数使其构建的二进制可执行文件可以在各Linux发行版正常运行
    # make binary-static DISABLE_CGO=1
    cp skopeo /usr/bin/

    Tips : 如果在Ubuntu构建时候没有为make加上指定参数时候然后将生成的二进制文件发送都CentOS机器下进行运行时候会产生动态链接库异常;

    # 问题描述:
    skopeo: error while loading shared libraries: libdevmapper.so.1.02.1: cannot open shared object file: No such file or directory
    
    # 解决办法在编译的时候加上 DISABLE_CGO=1 参数为程序s静态链接库:
    ldd skopeo_d #
            linux-vdso.so.1 (0x00007ffed9e66000)
            libgpgme.so.11 => /usr/lib/x86_64-linux-gnu/libgpgme.so.11 (0x00007f94aed2e000)
            libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f94aeb0f000)
            libdevmapper.so.1.02.1 => /lib/x86_64-linux-gnu/libdevmapper.so.1.02.1 (0x00007f94ae8a4000)
            libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f94ae4b3000)
            libassuan.so.0 => /usr/lib/x86_64-linux-gnu/libassuan.so.0 (0x00007f94ae2a0000)
            libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f94ae08b000)
            /lib64/ld-linux-x86-64.so.2 (0x00007f94b0ac4000)
            libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f94ade63000)
            libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007f94adc45000)
            libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f94ad8a7000)
            libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f94ad635000)
            libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f94ad431000)
            librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f94ad229000)
    
    # 加上 DISABLE_CGO=1 编译后的二进制可执行文件
    ldd skopeo_s #
            not a dynamic executable

  • 语法 : skopeo [global options] command [command options] [arguments...]

  • Command

    • copy : 复制一个镜像从 A 到B , 这里的A和B可以为本地docker镜像或者registry上的镜像。

    • delete : 删除一个镜像 , 可以是本地docker镜像或者registry上的镜像

    • help : 查看命令帮助手册

    • inspect : 查看镜像的元数据信息(image config详细信息)

    • list-tags : 列出一个registry上某个镜像的所有 tag,在某些脚本中可以进行使用;

    • login : 登录到某个registry,和docker login类似

    • logout : 退出已经登录到某个registry的auth信息,和docker logout类似

    • manifest-digest : 计算文件的清单摘要

    • standalone-sign : 使用本地文件创建签名

    • standalone-verify : 验证本地文件的签名

  • global options

    • --insecure-policy : 选项用于忽略安全策略配置文件

2.2.2 skopeo支持的镜像格式

无论我们的src镜像还是desc镜像都要满足以下格式才可以。

  • containers-storage: , 位于本地containers/storage镜像存储中的镜像。位置和镜像存储都在/etc/containers/storage.conf 中指定。

  • dir:path : 一个现有的本地目录路径,将清单、层 tarball 和签名存储为单独的文件。这是一种非标准化格式,主要用于调试或非侵入式容器检查。

  • docker://docker-reference : 实现“Docker Registry HTTP API V2”的仓库中的镜像。默认情况下,使用中的授权状态$XDG_RUNTIME_DIR/containers/auth.json,这是使用设置的skopeo login。

  • docker-archive:path[:docker-reference] 镜像存储在的docker save格式文件中。docker-reference仅在创建此类文件时使用,并且不得包含摘要。

  • docker-daemon:docker-reference : 存储在docker守护程序内部存储中的镜像docker-reference。docker-reference必须包含标签或摘要。或者,在读取镜像时,格式也可以是docker-daemon:algo:digest(镜像 ID)。

  • oci:path:tag : 路径中符合“Open Container Image Layout Specification”的目录中的镜像标签。

值得注意的事上面这几种镜像名称对应着镜像存在的方式 , 并且不同存在的方式对镜像的 layer 处理的方式也不一样 ,

  • 比如 docker:// 这种方式是存在registry上的。

  • 比如 docker-daemon 是存在本地docker pull下来的。

  • 比如 docker-archive 是通过docker save出来的镜像。

上述表达的是同一个镜像 , 只不过是存在的方式不一样而已 , 即同一个镜像有这几种存在的方式就像水有气体、液体、固体一样。

IMAGE NAMES

example

说明

containers-storage:

containers-storage:

dir:

dir:/PATH

docker://

docker://k8s.gcr.io/kube-apiserver:v1.17.5

其名称即为 src 或 dest 镜像名称的前缀

docker-daemon:

docker-daemon:alpine:latest

docker-archive:

docker-archive:alpine.tar (docker save)

oci:

oci:alpine:latest

2.2.3 基础实例

  • login/logout命令

    1. 配置文件认证

      # 与 配置 Docker registry 一样需要在
      /etc/docker/deamon.json
      # 或者~/.docker/config.json中配置
      jq "." ~/.docker/config.json
      {
        "auths": {
          "https://index.docker.io/v1/": {
            "auth": "d2sddaqWM7bSVlJFpmQE43Sw=="
          }
        },
        "HttpHeaders": {
          "User-Agent": "Docker-Client/19.03.5 (linux)"
        },
        "experimental": "enabled"
      }
    2. 对注册表进行身份验证

      $ skopeo login --user USER docker://myregistrydomain.com:5000
      # Password:
      $ skopeo inspect --creds=testuser:testpassword docker://myregistrydomain.com:5000/busybox
      $ skopeo copy --src-creds=testuser:testpassword docker://myregistrydomain.com:5000/private oci:local_oci_image
      # $ skopeo inspect docker://myregistrydomain.com:5000/busybox
      $ skopeo logout docker://myregistrydomain.com:5000

  • inspect命令:

    1. skopeo能够检查容器注册表上的存储库并获取图像层(检查存储库)

      $ skopeo inspect docker://registry.fedoraproject.org/fedora:latest
      $ skopeo inspect docker-daemon:alpine:latest --raw | jq "."
      {
          "Name": "registry.fedoraproject.org/fedora",
          "Digest": "sha256:58de585a231aca14a511347bc85b912a6f000159b49bc2b0582032911e5d3a6c",
          "RepoTags": [
              "30-aarch64",
              "30-ppc64le",
              "30-s390x",
              "30-x86_64",
              "30",
              "latest",
              "rawhide",
              "30-armhfp",
              "31-aarch64",
              "31-x86_64",
              "31",
              "31-armhfp",
              "31-s390x",
              "31-ppc64le",
              "32-aarch64",
              "32-ppc64le",
              "32-s390x",
              "32-x86_64",
              "32",
              "33-aarch64",
              "33-ppc64le",
              "33-s390x",
              "33-x86_64",
              "33"
          ],
          "Created": "2020-07-09T06:49:06Z",
          "DockerVersion": "1.10.1",
          "Labels": {
              "license": "MIT",
              "name": "fedora",
              "vendor": "Fedora Project",
              "version": "32"
          },
          "Architecture": "amd64",
          "Os": "linux",
          "Layers": [
              "sha256:dd9f43919ba05f05d4f783c31e83e5e776c4f5d29dd72b9ec5056b9576c10053"
          ],
          "Env": [
              "DISTTAG=f32container",
              "FGC=f32",
              "container=oci"
          ]
      }
    2. 显示来自fedora的容器配置:latest

      $ skopeo inspect --config docker://registry.fedoraproject.org/fedora:latest  | jq
      $ skopeo inspect --config docker-daemon:alpine:latest | jq "."
      {
        "created": "2020-05-29T21:19:46.363518345Z",
        "architecture": "amd64",
        "os": "linux",
        "config": {
          "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
          ],
          "Cmd": [
            "/bin/sh"
          ]
        },
        "rootfs": {
          "type": "layers",
          "diff_ids": [
            "sha256:50644c29ef5a27c9a40c393a73ece2479de78325cae7d762ef3cdc19bf42dd0a"
          ]
        },
        "history": [
          {
            "created": "2020-05-29T21:19:46.192045972Z",
            "created_by": "/bin/sh -c #(nop) ADD file:c92c248239f8c7b9b3c067650954815f391b7bcb09023f984972c082ace2a8d0 in / "
          },
          {
            "created": "2020-05-29T21:19:46.363518345Z",
            "created_by": "/bin/sh -c #(nop)  CMD [\"/bin/sh\"]",
            "empty_layer": true
          }
        ]
      }
    3. 显示未验证的图像摘要

      $ skopeo inspect docker://registry.fedoraproject.org/fedora:latest | jq '.Digest'
      "sha256:655721ff613ee766a4126cb5e0d5ae81598e1b0c3bcf7017c36c4d72cb092fe9"

  • copy命令

    可以在各种存储机制之间复制容器图像 , 包括:

    • Container registries: The Quay, Docker Hub, OpenShift, GCR, Artifactory ...

    • Container Storage backends : github.com/containers/storage (Backend for Podman, CRI-O, Buildah and friends)

    • Docker daemon storage

    • Local directories

    • Local OCI-layout directories

    实际上skopeo可以导出为其他格式比如oci、oci-archive、ostree等

    $ skopeo copy docker-daemon:alpine:latest oci:alpine
    $ skopeo copy oci:busybox_ocilayout:latest dir:existingemptydirectory
    $ tree -h alpine
    # alpine
    # ├── [4.0K]  blobs
    # │   └── [4.0K]  sha256
              # 是否感觉很相似实际上对应着Overlay2中digest中data文件
              # 镜像的 mainfaet 文件
    # │       ├── [ 348]  1c6f747c933450c5169f349f2a57b9d31e833c0452e1ec712b8aab0cbfea4d2c
    # │       # 镜像文件系统gzip压缩文件
    #         ├── [2.8M]  3eee30c545e47333e6fe551863f6f29c3dcd850187ae3f37c606adb991444886
              # 镜像的 image config 文件
    # │       └── [ 583]  af88fdb253aac46693de7883c9c55244327908c77248d7654841503f744aae8b
    # ├── [ 186]  index.json
    # └── [  31]  oci-layout

    1. 从docker daemon复制导出镜像到本地 , 直接通过http下载目标镜像并存储为/tmp/nginx.tar,此文件可以直接通过docker load命令导入

      $ skopeo --insecure-policy copy docker-daemon:nginx:1.17.6 docker-archive:/tmp/nginx.tar 
      # 将会从 docker daemon 导出镜像到 /tmp/nginx.tar
    2. 从一个Registry A复制Registry B之中;

      $ skopeo copy docker://quay.io/buildah/stable docker://registry.internal.company.com/buildah
    3. 该命令将会直接通过http下载目标镜像并存储为/tmp/nginx.tar,此文件可以直接通过docker load命令导入

      skopeo --insecure-policy copy docker://nginx:1.17.9 docker-archive:/tmp/nginx.tar
    4. 从k8s.gcr.io/kube-apiserver:v1.17.5复制镜像到index.docker.io/webpsh/kube-apiserver:v1.17.5

      $ skopeo copy docker://k8s.gcr.io/kube-apiserver:v1.17.5 docker://index.docker.io/webpsh/kube-apiserver:v1.17.5 --dest-authfile /root/.docker/config.json
      Getting image source signatures
      Copying blob 597de8ba0c30 done # 直接 copy 镜像 layer 的 blob 它是在 registry 进行压缩存储的格式
      Copying blob e13a88fa950c done
      Copying config f640481f6d done
      Writing manifest to image destination
      Storing signatures
      
      # pull 下载利用skopeo同步上传的镜像验证是否正确
      $ docker pull webpsh/kube-apiserver:v1.17.5
      v1.17.5: Pulling from webpsh/kube-apiserver
      Digest: sha256:5ddc5c77f52767f2f225a531a257259228d74b32d8aac9cfe087251f998c42f3
      Status: Downloaded newer image for webpsh/kube-apiserver:v1.17.5
      docker.io/webpsh/kube-apiserver:v1.17.5

  • delete - 删除镜像命令

    该命令非常有帮助可以直接调用Registry的API来进行删除镜像;

    $ skopeo delete docker://localhost:5000/imagename:latest

补充说明:

此处为了方便在使用skopeo的时候不用加一堆额外的参数,以OpenSSL生成客户端证书(客户端认证的证书、私钥)为例:

#!/bin/sh
set -e
set -o nounset
cat >ca.conf <<EOF
[ req ]
default_bits  = 2048
distinguished_name = req_distinguished_name
prompt   = no
encrypt_key  = no
x509_extensions  = v3_ca
[ req_distinguished_name ]
CN         = localhost
[ CA_default ]
copy_extensions = copy
[ alternate_names ]
DNS.2=localhost
[ v3_ca ]
subjectAltName=@alternate_names
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical,CA:true
keyUsage=keyCertSign,cRLSign,digitalSignature,keyEncipherment,nonRepudiation
EOF

# 证书签名申请
mkdir -p certs
openssl req -days 365 -x509 -config ca.conf \
    -new -keyout certs/domain.key -out certs/domain.crt

添加信任证书到系统中,根据不同的发行版选择相应的路径和命令行即可。

# CentOS
update-ca-trust force-enable
cp certs/domain.crt /etc/pki/ca-trust/source/anchors/localhost.crt
update-ca-trust

# Ubuntu
cp certs/domain.crt /usr/local/share/ca-certificates/localhost.crt
$ update-ca-certificates

# Debian
cp certs/domain.crt /usr/share/ca-certificates/localhost.crt
echo localhost.crt >> /etc/ca-certificates.conf
update-ca-certificates

3. 容器相关工具

3.1 容器启动参数查看

假如我使用docker run启动了了一个redis容器,而docker run的参数有很多 , 由于时间太久,我已经忘记了当初的启动参数,也并没有使用docker-compose这样的编排工具。

现在我如何进行重启,如何找回此前的启动命令,有没有解决办法? 答案: 当然是有的如下几种方式:

  • docker inpsect

  • reckecod

  • runlike

方式1:docker inpsect 描述:此种方式只是大概知道有哪些参数并不是完整的,而且需要使用者自己生成启动docker容器参数;

docker inspect -f "{{.Name}}{{println}}{{.Path}} {{.Args}} {{.Config.Cmd}} {{.Config.Env}} {{.Config.Volumes}} {{.Config.Entrypoint}} {{.NetworkSettings.Networks}}" $(docker ps -aq)
/linuxea_redis
/Initialization.sh [] [] 
[REDIS_CONF=on
REQUIRE_PASS=OTdmOWI4ZTM4NTY1M2M4OTZh
MASTER_AUTH=OTdmOWI4ZTM4NTY1M2M4OTZh
MAXCLIENTS_NUM=30
MAXMEMORY_SIZE=1024M
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RS_VSON=5.0.0
RS_USER=redis
RS_VSON_URL=http://download.redis.io/releases/redis-5.0.0.tar.gz
BATADIR=/usr/local/redis
DATADIR=/data/redis
DATALOG=/data/logs
DATACIG=/etc/redis]
map[linuxea_volume:{}] 
[/Initialization.sh] 
map[host:0xc420182000]

方式2:rekcod 描述:借助rekcod打印出更易读的格式docker inspect → docker run ,docker run从现有容器(via docker inspect)反向设计命令。 rekcod可以将以下任何内容转换为docker run命令:

  1. 容器ID /名称(rekcod将调用docker inspect)

  2. 包含docker inspect输出的文件的路径

  3. 原始JSON(docker inspect直接传递输出)

#(1) 系统安装 rekcod
$ yum install npm -y && npm i -g rekcod	
$ docker ps -qa|rekcod
$ rekcod linuxea_redis
docker run --name linuxea_redis --runtime runc -p 6379:6379/tcp --net host --restart no -h LinuxEA-Node172_25_50_250.cluster.com --expose 26379/tcp --expose 6379/tcp -e 'REDIS_CONF=on' -e 'REQUIRE_PASS=OTdmOWI4ZTM4NTY1M2M4OTZh' -e 'MASTER_AUTH=OTdmOWI4ZTM4NTY1M2M4OTZh' -e 'MAXCLIENTS_NUM=30' -e 'MAXMEMORY_SIZE=1024M' -e 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' -e 'RS_VSON=5.0.0' -e 'RS_USER=redis' -e 'RS_VSON_URL=http://download.redis.io/releases/redis-5.0.0.tar.gz' -e 'BATADIR=/usr/local/redis' -e 'DATADIR=/data/redis' -e 'DATALOG=/data/logs' -e 'DATACIG=/etc/redis' -d -t -i --entrypoint "/Initialization.sh" marksugar/redis:5.0.0

#(2) Docker 安装 rekcod
$ docker pull nexdrew/rekcod
$ alias rekcod="docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nexdrew/rekcod"
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nexdrew/rekcod <container>

方式3:runlike 描述:实际runlike被封装为一个名为assaflavie/runlike的Docker镜像。

# 常规语法
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike YOUR-CONTAINER
# 使用别名运行它,例如,将其保存在~/.profile或中~/.bashrc
alias runlike="docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike"
runlike YOUR-CONTAINER #以本地命令运行

# 实际案例
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike eager_saha
# docker run --name=eager_saha --hostname=e35b0d451122 --env=PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin --env=GOLANG_VERSION=1.14.6 --env=GOPATH=/go --log-driver=none --detach=true sha256:7da3d4d2918fc630aca3c4c011df3c9b30d7b79cd7be691718807cfb62bce554 /bin/sh -c 'go build hello.go'

安装使用流程:

#安装
yum install -y python-pip && pip install runlike  #Python2
yum install -y python3 && pip3 install runlike

#用法:
runlike -q <container-name>  #使用-q自动换行

#实例
runlike -p linuxea_redis
docker run \
    --name=linuxea_redis \
    --hostname=LinuxEA-Node172_25_50_250.cluster.com \
    --env=REDIS_CONF=on \
    --env=REQUIRE_PASS=OTdmOWI4ZTM4NTY1M2M4OTZh \
    --env=MASTER_AUTH=OTdmOWI4ZTM4NTY1M2M4OTZh \
    --env=MAXCLIENTS_NUM=30 \
    --env=MAXMEMORY_SIZE=1024M \
    --env=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
    --env=RS_VSON=5.0.0 \

4. UI管理

4.1. dockerui

描述:Dockerui是基于docker API提供图形化页面简单的容器管理系统,支持容器管理和镜像管理;容器信息查看只是画面比较酷,不怎么实用用来看看为以后造轮子也是极好;

$docker pull abh1nav/dockerui
#两种启动方法一种是sock,另外一种是是rest API
$docker run -d -p 9000:9000 -v /var/run/docker.sock:/docker.sock \
--name dockerui abh1nav/dockerui:latest -e="/docker.sock"
docker-tools-images-dockerui-1


参考链接

8.Docker使用辅助工具汇总 (qq.com)