Containerd的前世今⽣和保姆级⼊门教程
1. Containerd 的前世今⽣
很久以前,Docker 强势崛起,以“镜像”这个⼤招席卷全球,对其他容器技术进⾏致命的降维打击,使其毫⽆招架之⼒,就连 Google 也不例外。Google 为了不被拍死在沙滩上,被迫拉下脸⾯(当然,跪舔是不可能的),希望 Docker 公司和⾃⼰联合推进⼀个开源的容器运⾏时作为 Docker 的核⼼依赖,不然就⾛着瞧。Docker 公司觉得⾃⼰的智商被侮辱了,⾛着瞧就⾛着瞧,谁怕谁啊!
很明显,Docker 公司的这个决策断送了⾃⼰的⼤好前程,造成了今天的悲剧。
紧接着,Google 联合 Red Hat、IBM 等⼏位巨佬连哄带骗忽悠 Docker 公司将libcontainer捐给中⽴的社区(OCI,Open Container Intiative),并改名为runc,不留⼀点 Docker 公司的痕迹~~
这还不够,为了彻底扭转 Docker ⼀家独⼤的局⾯,⼏位⼤佬⼜合伙成⽴了⼀个基⾦会叫CNCF(Cloud Native Computing Fundation),这个名字想必⼤家都很熟了,我就不详细介绍了。CNCF 的⽬标很明确,既然在当前的维度上⼲不过 Docker,⼲脆往上爬,升级到⼤规模容器编排的维度,以此来击败 Docker。
Docker 公司当然不⽢⽰弱,搬出了 Swarm 和 Kubernetes 进⾏ PK,最后的结局⼤家都知道了,Swar
m 战败。然后 Docker 公司耍了个⼩聪明,将⾃⼰的核⼼依赖Containerd捐给了 CNCF,以此来标榜 Docker 是⼀个 PaaS 平台。
很明显,这个⼩聪明⼜⼤⼤加速了⾃⼰的灭亡。
巨佬们⼼想,想当初想和你合作搞个中⽴的核⼼运⾏时,你死要⾯⼦活受罪,就是不同意,好家伙,现在⾃⼰搞了⼀个,还捐出来了,这是什么操作?也罢,这倒省事了,我就直接拿Containerd来做⽂章吧。
⾸先呢,为了表⽰ Kubernetes 的中⽴性,当然要搞个标准化的容器运⾏时接⼝,只要适配了这个接⼝的容器运⾏时,都可以和我⼀起玩耍哦,第⼀个⽀持这个接⼝的当然就是Containerd啦。⾄于这个接⼝的名字,⼤家应该都知道了,它叫 CRI(Container Runntime Interface)。
这样还不⾏,为了蛊惑 Docker 公司,Kubernetes 暂时先委屈⾃⼰,专门在⾃⼰的组件中集成了⼀个shim(你可以理解为垫⽚),⽤来将 CRI 的调⽤翻译成 Docker 的 API,让Docker 也能和⾃⼰愉快地玩耍,温⽔煮青蛙,养肥了再杀。。。
就这样,Kubernetes ⼀边假装和 Docker 愉快玩耍,⼀边背地⾥不断优化 Containerd 的健壮性以及和 CRI 对接的丝滑性。现在 Containerd 的翅膀已经完全硬了,是时候卸下我的伪装,和 Docker say bye bye 了。后⾯的事情⼤家也都知道了~~
Docker 这门技术成功了,Docker 这个公司却失败了。
2. Containerd 架构
时⾄今⽇,Containerd 已经变成⼀个⼯业级的容器运⾏时了,连⼝号都有了:超简单!超健壮!可移植性超强!
当然,为了让 Docker 以为⾃⼰不会抢饭碗,Containerd 声称⾃⼰的设计⽬的主要是为了嵌⼊到⼀个更⼤的系统中(暗指 Kubernetes),⽽不是直接由开发⼈员或终端⽤户使⽤。
事实上呢,Containerd 现在基本上啥都能⼲了,开发⼈员或者终端⽤户可以在宿主机中管理完整的容器⽣命周期,包括容器镜像的传输和存储、容器的执⾏和管理、存储和⽹络等。⼤家可以考虑学起来了。
学习 Containerd 最好的时机是关注云原⽣实验室后,其次是现在,看完了再关注也不迟 。
先来看看 Containerd 的架构:
可以看到 Containerd 仍然采⽤标准的 C/S 架构,服务端通过GRPC协议提供稳定的 API,客户端通过调⽤服务端的 API 进⾏⾼级的操作。
为了解耦,Containerd 将不同的职责划分给不同的组件,每个组件就相当于⼀个⼦系统(subsystem)。连接不同⼦系统的组件被称为模块。
总体上 Containerd 被划分为两个⼦系统:
Bundle : 在 Containerd 中,Bundle包含了配置、元数据和根⽂件系统数据,你可以理解为容器的⽂件系统。⽽ Bundle ⼦系统允许⽤户从镜像中提取和打包 Bundles。
Runtime : Runtime ⼦系统⽤来执⾏ Bundles,⽐如创建容器。
其中,每⼀个⼦系统的⾏为都由⼀个或多个模块协作完成(架构图中的Core部分)。每⼀种类型的模块都以插件的形式集成到 Containerd 中,⽽且插件之间是相互依赖的。例如,上图中的每⼀个长虚线的⽅框都表⽰⼀种类型的插件,包括Service Plugin、Metadata Plugin、GC Plugin、Runtime Plugin等,其中Service Plugin⼜会依赖 Metadata Plugin、GC Plugin 和 Runtime Plugin。每⼀个⼩⽅框都表⽰⼀个细分的插件,例如Metadata Plugin依赖 Containers Plugin、Content Plugin 等。总之,万物皆插件,插件就是模块,模块就是插件。
这⾥介绍⼏个常⽤的插件:
Content Plugin : 提供对镜像中可寻址内容的访问,所有不可变的内容都被存储在这⾥。
Snapshot Plugin : ⽤来管理容器镜像的⽂件系统快照。镜像中的每⼀个 layer 都会被解压成⽂件系统快照,类似于 Docker 中的graphdriver。
Metrics : 暴露各个组件的监控指标。
从总体来看,Containerd 被分为三个⼤块:Storage、Metadata和Runtime,可以将上⾯的架构图提炼⼀下:
这是使⽤对Docker、crio和Containerd的性能测试结果,包括启动、停⽌和删除容器,以⽐较它们所耗的时间:
可以看到 Containerd 在各个⽅⾯都表现良好,总体性能还是优越于Docker和crio的。
3. Containerd 安装
了解了 Containerd 的概念后,就可以动⼿安装体验⼀把了。本⽂的演⽰环境为Ubuntu 18.04。
安装依赖
为 seccomp 安装依赖:
→ sudo apt-get update
→ sudo apt-get install libseccomp2
下载并解压 Containerd 程序
Containerd 提供了两个压缩包,⼀个叫containerd-${VERSION}.${OS}-${ARCH}.,另⼀个叫cri-containerd-${VERSION}.${OS}-${ARCH}.。其中cri-containerd-${VERSION}.${OS}-${ARCH}.包含了所有 Kubernetes 需要的⼆进制⽂件。如果你只是本地测试,可以选择前⼀个压缩包;如果是作为 Kubernetes 的容器运⾏时,需要选择后⼀个压缩包。Containerd 是需要调⽤runc的,⽽第⼀个压缩包是不包含runc⼆进制⽂件的,如果你选择第⼀个压缩包,还需要提前安装 runc。所以我建议直接使⽤cri-containerd压缩包。
⾸先从下载最新版本的压缩包,当前最新版本为 1.4.3:
→ wget github/containerd/containerd/releases/download/v1.4.3/cri-containerd-cni-1.4.
# 也可以替换成下⾯的 URL 加速下载
→ wget /containerd/containerd/releases/download/v1.4.3/cri-containerd-cni-1.4.
可以通过 tar 的-t选项直接看到压缩包中包含哪些⽂件:
→ tar -tf cri-containerd-cni-1.4.
etc/
etc/cni/
etc/cni/net.d/
etc/cni/net.flist
etc/crictl.yaml
etc/systemd/
etc/systemd/system/
etc/systemd/system/containerd.service
usr/
usr/local/
usr/local/bin/
usr/local/bin/containerd-shim-runc-v2
usr/local/bin/ctr
usr/local/bin/containerd-shim
usr/local/bin/containerd-shim-runc-v1
usr/local/bin/crictl
usr/local/bin/critest
usr/local/bin/containerd
usr/local/sbin/
usr/local/sbin/runc
opt/
opt/cni/
opt/cni/bin/
opt/cni/bin/vlan
opt/cni/bin/host-local
opt/cni/bin/flannel
opt/cni/bin/bridge
opt/cni/bin/host-device
opt/cni/bin/tuning
ubuntu使用入门教程opt/cni/bin/firewall
opt/cni/bin/bandwidth
opt/cni/bin/ipvlan
opt/cni/bin/sbr
opt/cni/bin/dhcp
opt/cni/bin/portmap
opt/cni/bin/ptp
opt/cni/bin/static
opt/cni/bin/macvlan
opt/cni/bin/loopback
opt/containerd/
opt/containerd/cluster/
opt/containerd/cluster/version
opt/containerd/cluster/gce/
opt/containerd/cluster/plate
opt/containerd/cluster/gce/configure.sh
opt/containerd/cluster/gce/cloud-init/
opt/containerd/cluster/gce/cloud-init/master.yaml
opt/containerd/cluster/gce/cloud-init/node.yaml
opt/containerd/cluster/gce/env
直接将压缩包解压到系统的各个⽬录中:
→ sudo tar -C / -xzf cri-containerd-cni-1.4.
将/usr/local/bin和/usr/local/sbin追加到~/.bashrc⽂件的$PATH环境变量中:
export PATH=$PATH:/usr/local/bin:/usr/local/sbin
⽴即⽣效:
→ source ~/.bashrc
查看版本:
→ ctr version
Client:
Version: v1.4.3
Revision: 269548fa27e0089a8b8278fc4fc781d7f65a939b
Go version: go1.15.5
Server:
Version: v1.4.3
Revision: 269548fa27e0089a8b8278fc4fc781d7f65a939b
UUID: d1724999-91b3-4338-9288-9a54c9d52f70
⽣成配置⽂件
Containerd 的默认配置⽂件为/etc/l,我们可以通过命令来⽣成⼀个默认的配置:
→ mkdir /etc/containerd
→ containerd config default > /etc/l
镜像加速
由于某些不可描述的因素,在国内拉取公共镜像仓库的速度是极慢的,为了节约拉取时间,需要为 Containerd 配置镜像仓库的mirror。Containerd 的镜像仓库 mirror 与 Docker 相⽐有两个区别:
Containerd 只⽀持通过CRI拉取镜像的 mirror,也就是说,只有通过crictl或者 Kubernetes 调⽤时 mirror 才会⽣效,通过ctr拉取是不会⽣效的。
Docker只⽀持为Docker Hub配置 mirror,⽽Containerd⽀持为任意镜像仓库配置 mirror。
配置镜像加速之前,先来看下 Containerd 的配置结构,乍⼀看可能会觉得很复杂,复杂就复杂在 plugin 的配置部分:
[plugins]
[plugins."v1.scheduler"]
pause_threshold = 0.02
deletion_threshold = 0
mutation_threshold = 100
schedule_delay = "0s"
startup_delay = "100ms"
[plugins."i"]
disable_tcp_service = true
stream_server_address = "127.0.0.1"
stream_server_port = "0"
stream_idle_timeout = "4h0m0s"
enable_selinux = false
sandbox_image = "io/pause:3.1"
stats_collect_period = 10
systemd_cgroup = false
enable_tls_streaming = false
max_container_log_line_size = 16384
disable_cgroup = false
disable_apparmor = false
restrict_oom_score_adj = false
max_concurrent_downloads = 3
disable_proc_mount = false
[plugins."i".containerd]
snapshotter = "overlayfs"
default_runtime_name = "runc"
no_pivot = false
[plugins."i".containerd.default_runtime]
runtime_type = ""
runtime_engine = ""
runtime_root = ""
privileged_without_host_devices = false
[plugins."i".containerd.untrusted_workload_runtime]
runtime_type = ""
runtime_engine = ""
runtime_root = ""
privileged_without_host_devices = false
[plugins."i".containerd.runtimes]
[plugins."i".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v1"
runtime_engine = ""
runtime_root = ""
privileged_without_host_devices = false
[plugins."i"i]
bin_dir = "/opt/cni/bin"
conf_dir = "/etc/cni/net.d"
max_conf_num = 1
conf_template = ""
[plugins."i".registry]
[plugins."i".registry.mirrors]
[plugins."i".registry.mirrors."docker.io"]
endpoint = ["registry-1.docker.io"]
[plugins."i".x509_key_pair_streaming]
tls_cert_file = ""
tls_key_file = ""
[plugins."io.containerd.internal.v1.opt"]
path = "/opt/containerd"
[plugins."io.containerd.start"]
interval = "10s"
[plugins."adata.v1.bolt"]
content_sharing_policy = "shared"
[plugins."ups"]
no_prometheus = false
[plugins."io.containerd.runtime.v1.linux"]
shim = "containerd-shim"
runtime = "runc"
runtime_root = ""
no_shim = false
shim_debug = false
[plugins."io.containerd.runtime.v2.task"]
platforms = ["linux/amd64"]
[plugins."io.containerd.service.v1.diff-service"]
default = ["walking"]
[plugins."io.containerd.snapshotter.v1.devmapper"]
root_path = ""
pool_name = ""
base_image_size = ""
每⼀个顶级配置块的命名都是plugins."vx.xxx"这种形式,其实每⼀个顶级配置块都代表⼀个插件,其中vx表⽰插件的类型,vx 后⾯的 xxx 表⽰插件的ID。可以通过ctr⼀览⽆余:
→ ctr plugin ls
TYPE ID PLATFORMS STATUS
顶级配置块下⾯的⼦配置块表⽰该插件的各种配置,⽐如 cri 插件下⾯就分为containerd、cni和registry的配置,⽽ containerd 下⾯⼜可以配置各种 runtime,还可以配置默认的runtime。
镜像加速的配置就在 cri 插件配置块下⾯的 registry 配置块,所以需要修改的部分如下:
[plugins."i".registry]
[plugins."i".registry.mirrors]
[plugins."i".registry.mirrors."docker.io"]
endpoint = ["dockerhub.mirrors.nwafu.edu"]
[plugins."i".registry.mirrors."io"]
endpoint = ["registry.aliyuncs/k8sxio"]
[plugins."i".registry.mirrors."gcr.io"]
endpoint = ["xxx"]
registry.mirrors."xxx" : 表⽰需要配置 mirror 的镜像仓库。例如,registry.mirrors."docker.io"表⽰配置 docker.io 的 mirror。
endpoint : 表⽰提供 mirror 的镜像加速服务。例如,这⾥推荐使⽤西北农林科技⼤学提供的镜像加速服务作为docker.io的 mirror。
⾄于gcr.io,⽬前还没有公共的加速服务。我⾃⼰掏钱搭了个加速服务,拉取速度⼤概是3M/s左右,有
加速需求的同学可以通过号:cloud-native-yang 加我为好友再详细咨询。
存储配置
Containerd 有两个不同的存储路径,⼀个⽤来保存持久化数据,⼀个⽤来保存运⾏时状态。
root = "/var/lib/containerd"
state = "/run/containerd"
root⽤来保存持久化数据,包括Snapshots, Content, Metadata以及各种插件的数据。每⼀个插件都有⾃⼰单独的⽬录,Containerd 本⾝不存储任何数据,它的所有功能都来⾃于已加
载的插件,真是太机智了。
→ tree -L 2 /var/lib/containerd/
/var/lib/containerd/
├── t
│├── blobs
│└── ingest
├── i
│├── containers
│└── sandboxes
├── adata.v1.bolt
│└── meta.db
├── io.containerd.runtime.v1.linux
│└── k8s.io
├── io.containerd.runtime.v2.task
├── io.containerd.snapshotter.v1.aufs
│└── snapshots
├── io.containerd.snapshotter.v1.btrfs
├── io.containerd.snapshotter.v1.native
│└── snapshots
├── io.containerd.snapshotter.v1.overlayfs
│├── metadata.db
│└── snapshots
└── tmpmounts
18 directories, 2 files
state⽤来保存临时数据,包括 sockets、pid、挂载点、运⾏时状态以及不需要持久化保存的插件数据。
→ tree -L 2 /run/containerd/
/run/containerd/
├── containerd.sock
├── pc
├── i
│├── containers
│└── sandboxes
├── io.containerd.runtime.v1.linux
│└── k8s.io
├── io.containerd.runtime.v2.task
└── runc
└── k8s.io
8 directories, 2 files
OOM
还有⼀项配置需要留意:
oom_score = 0
Containerd 是容器的守护者,⼀旦发⽣内存不⾜的情况,理想的情况应该是先杀死容器,⽽不是杀死 Containerd。所以需要调整 Containerd 的OOM权重,减少其被 OOM Kill 的⼏率。最好是将oom_score的值调整为⽐其他守护进程略低的值。这⾥的 oom_socre 其实对应的是/proc/<pid>/oom_socre_adj,在早期的 Linux 内核版本⾥使⽤oom_adj来调整权重, 后来改⽤oom_socre_adj了。该⽂件描述如下:
The value of /proc/<pid>/oom_score_adj is added to the badness score before it
is used to determine which task to kill. Acceptable values range from -1000
(OOM_SCORE_ADJ_MIN) to +1000 (OOM_SCORE_ADJ_MAX). This allows userspace to
polarize the preference for oom killing either by always preferring a certain
task or completely disabling it. The lowest possible value, -1000, is
equivalent to disabling oom killing entirely for that task since it will always
report a badness score of 0.
在计算最终的badness score时,会在计算结果是中加上oom_score_adj ,这样⽤户就可以通过该在值来保护某个进程不被杀死或者每次都杀某个进程。其取值范围为-1000到1000。如果将该值设置为-1000,则进程永远不会被杀死,因为此时badness score永远返回0。
建议 Containerd 将该值设置为-999到0之间。如果作为 Kubernetes 的 Worker 节点,可以考虑设置为-999。
Systemd 配置
建议通过 systemd 配置 Containerd 作为守护进程运⾏,配置⽂件在上⽂已经被解压出来了:
→ cat /etc/systemd/system/containerd.service
# Copyright The containerd Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# /licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[Unit]
Description=containerd container runtime
Documentation=containerd.io
After=network.target local-fs.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=1048576
# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
这⾥有两个重要的参数:
Delegate : 这个选项允许 Containerd 以及运⾏时⾃⼰管理⾃⼰创建的容器的cgroups。如果不设置这个选项,systemd 就会将进程移到⾃⼰的cgroups中,从⽽导致Containerd ⽆法正确获取容器的资源使⽤情况。
KillMode : 这个选项⽤来处理 Containerd 进程被杀死的⽅式。默认情况下,systemd 会在进程的 cgroup 中查并杀死 Containerd 的所有⼦进程,这肯定不是我们想要
的。KillMode字段可以设置的值如下。
control-group(默认值):当前控制组⾥⾯的所有⼦进程,都会被杀掉
process:只杀主进程
mixed:主进程将收到 SIGTERM 信号,⼦进程收到 SIGKILL 信号
none:没有进程会被杀掉,只是执⾏服务的 stop 命令。
我们需要将 KillMode 的值设置为process,这样可以确保升级或重启 Containerd 时不杀死现有的容器。
现在到了最关键的⼀步:启动 Containerd。执⾏⼀条命令就完事:
→ systemctl enable containerd --now
接下来进⼊本⽂最后⼀部分:Containerd 的基本使⽤⽅式。本⽂只会介绍 Containerd 的本地使⽤⽅法,即本地客户端ctr的使⽤⽅法,不会涉及到crictl,后⾯有机会再介绍
crictl。
4. Containerd 快速安装
如果你想在⼀分钟内快速装好 Kubernetes 和 Containerd,可以使⽤来部署。该项⽬旨在做⼀个简单⼲净轻量级稳定的 kubernetes 安装⼯具,⼀条命令,离线安装,包含所有依
赖,内核负载不依赖 haproxy keepalived,纯 golang 开发,99 年证书。1.12.0 版本的离线包搭载了最新版本的 Containerd,还⽀持arm64架构,简直就是简直了。
部署⽅法特别简单,⾸先下载并安装sealos, sealos是个 golang 的⼆进制⼯具,直接下载拷贝到bin⽬录即可, release页⾯也可下载:
→ wget -c sealyun.oss-cn-beijing.aliyuncs/latest/sealos
→ chmod +x sealos && mv sealos /usr/bin
下载离线资源包:
→ wget -c sealyun.oss-cn-beijing.aliyuncs/7b6af025d4884fdd5cd51a674994359c-1.18.0/kube1.18.
安装⼀个三 master 的⾼可⽤ Kubernetes 集:
→ sealos init --passwd 123456
--master 192.168.0.2 --master 192.168.0.3 --master 192.168.0.4
--node 192.168.0.5
--pkg-url /root/kube1.18.
--version v1.18.0
然后就完事了。。。
5. ctr 使⽤
ctr ⽬前很多功能做的还没有 docker 那么完善,但基本功能已经具备了。下⾯将围绕镜像和容器这两个⽅⾯来介绍其使⽤⽅法。
镜像
镜像下载:
→ ctr i pull docker.io/library/nginx:alpine
docker.io/library/nginx:alpine: resolved |++++++++++++++++++++++++++++++++++++++|
index-sha256:efc93af57bd255ffbfb12c89ec0714dd1a55f16290eb26080e3d1e7e82b3ea66: done |++++++++++++++++++++++++++++++++++++++|
manifest-sha256:6ceeeab513f7d15cea38c1f8dfe5455323b5a1bfd568516b3b0ee70406f75247: done |++++++++++++++++++++++++++++++++++++++|
config-sha256:0fde4fb87e476fd1655b3f04f55aa5b4b3ef7de7c701eb46573bb5a5dcf66fd2: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:abaddf4965e5e9ce9953f2e136b3bf9cc15365adbcf0c68b108b1cc26c12b1be: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:05e7bc50f07f000e9993ec0d264b9ffcbb9a01a4d69c68f556d25e9811a8f7f4: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:c78f7f670e47cf98494e7dbe08e463d34c160bf6a5939a2155ff4438cb8b0e80: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:ce77cf6a2ede66c463dcdd39f1a43cfbac3723a99e94f697bc20faee0f7cce1b: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:3080fd9f46494247c9298a6a3d9694f03f6a32898a07ffbe1c17a0752bae5c4e: done |++++++++++++++++++++++++++++++++++++++|
elapsed: 17.3s total: 8.7 Mi (513.8 KiB/s)
unpacking linux/amd64 sha256:
done
本地镜像列表查询:
→ ctr i ls
REF TYPE DIGEST SIZE PLATFORMS LABELS docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:efc93af57bd255ffbfb12c89ec0714dd1a55f16290eb26080e3d1e7e82b3ea66 9.3 MiB linux/386,linux/amd64,linux/arm/v6,linux/a 这⾥需要注意PLATFORMS,它是镜像的能够运⾏的平台标识。
将镜像挂载到主机⽬录:
→ ctr i mount docker.io/library/nginx:alpine /mnt
→ tree -L 1 /mnt
/mnt
├── bin
├── dev
├── docker-entrypoint.d
├── docker-entrypoint.sh
├── etc
├── home
├── lib
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin
├── srv
├── sys
├── tmp
├── usr
└── var
18 directories, 1 file
将镜像从主机⽬录上卸载:
→ ctr i unmount /mnt
将镜像导出为压缩包:
→ ctr i export docker.io/library/nginx:alpine
从压缩包导⼊镜像:
→ ctr i import
其他操作可以⾃⼰查看帮助:
→ ctr i --help
NAME:
ctr images - manage images
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论