终于可以像使用 Docker 一样丝滑地使用 Containerd 了!

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有追求的工程师一般都是有技术洁癖的,云原生的世界更是如此,"},{"type":"codeinline","content":[{"type":"text","text":"Kubernetes"}]},{"type":"text","text":" 虽然制定了容器运行时接口("},{"type":"codeinline","content":[{"type":"text","text":"CRI"}]},{"type":"text","text":")标准,但早期能用的容器运行时只有 "},{"type":"codeinline","content":[{"type":"text","text":"Docker"}]},{"type":"text","text":",而 "},{"type":"codeinline","content":[{"type":"text","text":"Docker"}]},{"type":"text","text":" 又不适配这个标准,于是给 "},{"type":"codeinline","content":[{"type":"text","text":"Docker"}]},{"type":"text","text":" 开了后门,花了大量的精力去适配它。后来有了更多的容器运行时可以选择后,Kubernetes 就不得不重新考量要不要继续适配 Docker 了,因为每次更新 Kubelet 都要考虑与 Docker 的适配问题。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/06\/062b6ad6c3b81b544ff04b0fcea52313.gif","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"标准这个东西就是这样,我定好标准,你兼容了就一起玩,不兼容就拜拜,它就像两个人在一起的底线,你可以重,你可以丑,你也可以不完善,但是你不兼容标准就真的不能一起玩了,于是 Kubernetes 就把 Docker 踢出了群聊。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/f5\/f55e5c1cff02c328d45d35a3bf49c45f.gif","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最终 Kubernetes 选择了 "},{"type":"codeinline","content":[{"type":"text","text":"Containerd"}]},{"type":"text","text":",时至今日 "},{"type":"codeinline","content":[{"type":"text","text":"Containerd"}]},{"type":"text","text":" 已经变成一个工业级的容器运行时了,它足够简单、健壮,可移植性也很强。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"现有 CLI 的不足"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"虽然 Docker 能干的事情,现在 "},{"type":"codeinline","content":[{"type":"text","text":"Containerd"}]},{"type":"text","text":" 都能干,但 "},{"type":"codeinline","content":[{"type":"text","text":"Containerd"}]},{"type":"text","text":" 还有一个非常明显的缺陷:"},{"type":"text","marks":[{"type":"strong"}],"text":"CLI 不够友好"},{"type":"text","text":"。它无法像 Docker 和 Podman 一样通过一条简单的命令启动一个容器,它的两个 CLI 工具 "},{"type":"text","marks":[{"type":"strong"}],"text":"ctr"},{"type":"sup","content":[{"type":"text","text":"[1]"}],"marks":[{"type":"strong"}]},{"type":"text","text":" 和 "},{"type":"text","marks":[{"type":"strong"}],"text":"crictl"},{"type":"sup","content":[{"type":"text","text":"[2]"}],"marks":[{"type":"strong"}]},{"type":"text","text":" 都无法实现这么一件非常简单的需求,而这个需求是大多数人都需要的,我总不能为了在本地测试容器而专门部署一个 Kubernetes 集群吧?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/b6\/b63089c51a1f4b3c531e97a4c6f827f4.gif","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ctr 的设计对人类不太友好,例如缺少以下这些和 Docker 类似的功能:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"docker run -p "}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"docker run --restart=always"}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通过凭证文件 "},{"type":"codeinline","content":[{"type":"text","text":"~\/.docker\/config.json"}]},{"type":"text","text":" 来拉取镜像"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"docker logs"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除此之外还有一个 CLI 工具叫 "},{"type":"codeinline","content":[{"type":"text","text":"crictl"}]},{"type":"text","text":",和 "},{"type":"codeinline","content":[{"type":"text","text":"ctr"}]},{"type":"text","text":" 一样不太友好。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"为了解决这个痛点,Containerd 官方推出了一个新的 CLI 叫 "},{"type":"text","marks":[{"type":"strong"}],"text":"nerdctl"},{"type":"sup","content":[{"type":"text","text":"[3]"}],"marks":[{"type":"strong"}]},{"type":"text","text":"。nerdctl 的使用体验和 docker 一样顺滑,例如:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → nerdctl run -d -p 8080:80 --name=nginx --restart=always nginx"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"nerdctl 只是 docker 的复制品?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"nerdctl"}]},{"type":"text","text":" 的目标并不是单纯地复制 docker 的功能,它还实现了很多 docker 不具备的功能,例如延迟拉取镜像("},{"type":"text","marks":[{"type":"strong"}],"text":"lazy-pulling"},{"type":"sup","content":[{"type":"text","text":"[4]"}],"marks":[{"type":"strong"}]},{"type":"text","text":")、镜像加密("},{"type":"text","marks":[{"type":"strong"}],"text":"imgcrypt"},{"type":"sup","content":[{"type":"text","text":"[5]"}],"marks":[{"type":"strong"}]},{"type":"text","text":")等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/e4\/e474dc7547ee35fd88dfc0e9e7896fac.png","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"延迟拉取镜像功能可以参考这篇文章:"},{"type":"text","marks":[{"type":"strong"}],"text":"Containerd 使用 Stargz Snapshotter 延迟拉取镜像"},{"type":"sup","content":[{"type":"text","text":"[6]"}],"marks":[{"type":"strong"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"虽然这些功能预计最终也会在 Docker 中实现,但"},{"type":"text","marks":[{"type":"strong"}],"text":"可能需要几个月甚至几年的时间"},{"type":"sup","content":[{"type":"text","text":"[7]"}],"marks":[{"type":"strong"}]},{"type":"text","text":",因为 Docker 目前的设计只使用一小部分 "},{"type":"codeinline","content":[{"type":"text","text":"Containerd"}]},{"type":"text","text":" 子系统。将来 Docker 有可能重构代码以使用完整的 "},{"type":"codeinline","content":[{"type":"text","text":"Containerd"}]},{"type":"text","text":",但目前还没看到什么实质性进展。所以 "},{"type":"codeinline","content":[{"type":"text","text":"Containerd"}]},{"type":"text","text":" 社区决定创建一个新的 CLI 来更友好地使用 "},{"type":"codeinline","content":[{"type":"text","text":"Containerd"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"nerdctl 试用"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你可以从 "},{"type":"text","marks":[{"type":"strong"}],"text":"nerdctl 的 release"},{"type":"sup","content":[{"type":"text","text":"[8]"}],"marks":[{"type":"strong"}]},{"type":"text","text":" 中下载最新的可执行文件,每一个版本都有两种可用的发行版:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"nerdctl--linux-amd64.tar.gz"}]},{"type":"text","text":" : 只包含 nerdctl。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"nerdctl-full--linux-amd64.tar.gz"}]},{"type":"text","text":" : 包含了 nerdctl 和相关依赖组件(containerd, runc, CNI, …)。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你已经安装了 Containerd,只需要选择前一个发行版,否则就选择完整版。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"安装好 nerdctl 后,就可以使用 nerdctl 来运行容器了:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → nerdctl run -d -p 80:80 --name=nginx --restart=always nginx:alpine\n\ndocker.io\/library\/nginx:alpine:                                                   resolved       |++++++++++++++++++++++++++++++++++++++|\nindex-sha256:d33e9e24389d7d8b90fe2bcc2dd1bc09b4d235e916ba9d5d9a71cf52e340edb6:    done           |++++++++++++++++++++++++++++++++++++++|\nmanifest-sha256:c1f4e1974241c3f9ddb2866b2bf8e7afbceaa42dae82aabda5e946d03f054ed2: done           |++++++++++++++++++++++++++++++++++++++|\nconfig-sha256:bfad9487e175364fd6315426feeee34bf5e6f516d2fe6a4e9b592315e330828e:   done           |++++++++++++++++++++++++++++++++++++++|\nlayer-sha256:29d3f97df6fd99736a0676f9e57e53dfa412cf60b26d95008df9da8197f1f366:    done           |++++++++++++++++++++++++++++++++++++++|\nlayer-sha256:9aae54b2144e5b2b00c610f8805128f4f86822e1e52d3714c463744a431f0f4a:    done           |++++++++++++++++++++++++++++++++++++++|\nlayer-sha256:a5f0adaddd5456b7c5a3753ab541b5fad750f0a6499a15f63571b964eb3e2616:    done           |++++++++++++++++++++++++++++++++++++++|\nlayer-sha256:5df810e1c460527fe400cdd2cab62228f5fb3da0f2dce86a6a6c354972f19b6e:    done           |++++++++++++++++++++++++++++++++++++++|\nlayer-sha256:345aee38d3533398e0eb7118e4323a8970f7615136f2170dfb2b0278bbd9099d:    done           |++++++++++++++++++++++++++++++++++++++|\nlayer-sha256:e6a4c36d7c0e358e5fc02ccdac645b18b85dcfec09d4fb5f8cbdc187ce9467a0:    done           |++++++++++++++++++++++++++++++++++++++|\nelapsed: 5.7 s                                                                    total:  9.4 Mi (1.6 MiB\/s)\n27b55e0b18b10c4c8f34e3ba709614e7b1760a75db061d2ce5183e8b1101ce09\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"查看创建的容器:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → nerdctl ps\n\nCONTAINER ID    IMAGE                             COMMAND                   CREATED          STATUS    PORTS                 NAMES\n3b5faa266a43    docker.io\/library\/nginx:alpine    \"\/docker-entrypoint.…\"    3 minutes ago    Up        0.0.0.0:80->80\/tcp    nginx"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"和 Docker 一样,Containerd 也有一个子命令 "},{"type":"codeinline","content":[{"type":"text","text":"network"}]},{"type":"text","text":":"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → nerdctl network ls\n\nNETWORK ID    NAME               FILE\n0             bridge\n              k8s-pod-network    \/etc\/cni\/net.d\/10-calico.conflist\n              host\n              none"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"来看下默认的 bridge 配置:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"🐳  → nerdctl network inspect bridge\n[\n    {\n        \"CNI\": {\n            \"cniVersion\": \"0.4.0\",\n            \"name\": \"bridge\",\n            \"nerdctlID\": 0,\n            \"plugins\": [\n                {\n                    \"type\": \"bridge\",\n                    \"bridge\": \"nerdctl0\",\n                    \"isGateway\": true,\n                    \"ipMasq\": true,\n                    \"hairpinMode\": true,\n                    \"ipam\": {\n                        \"type\": \"host-local\",\n                        \"routes\": [\n                            {\n                                \"dst\": \"0.0.0.0\/0\"\n                            }\n                        ],\n                        \"ranges\": [\n                            [\n                                {\n                                    \"subnet\": \"10.4.0.0\/24\",\n                                    \"gateway\": \"10.4.0.1\"\n                                }\n                            ]\n                        ]\n                    }\n                },\n                {\n                    \"type\": \"portmap\",\n                    \"capabilities\": {\n                        \"portMappings\": true\n                    }\n                },\n                {\n                    \"type\": \"firewall\"\n                },\n                {\n                    \"type\": \"tuning\"\n                }\n            ]\n        },\n        \"NerdctlID\": 0\n    }\n]\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看到 "},{"type":"codeinline","content":[{"type":"text","text":"network"}]},{"type":"text","text":" 子命令背后还是 CNI 在运作,与 docker network 子命令原理不同。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"构建镜像"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"nerdctl"}]},{"type":"text","text":" 也可以和 "},{"type":"codeinline","content":[{"type":"text","text":"buildkit"}]},{"type":"text","text":" 结合使用来构建容器镜像,需要先下载 buildkit 的可执行文件:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → wget https:\/\/github.com\/moby\/buildkit\/releases\/download\/v0.8.2\/buildkit-v0.8.2.darwin-amd64.tar.gz"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"将其解压到 "},{"type":"codeinline","content":[{"type":"text","text":"$PATH"}]},{"type":"text","text":" 中:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → tar -C \/usr\/local\/ -zxvf buildkit-v0.8.2.linux-amd64.tar.gz"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"编写 systemd unit 文件:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"# \/etc\/systemd\/system\/buildkit.service\n[Unit]\nDescription=BuildKit\nDocumentation=https:\/\/github.com\/moby\/buildkit\n\n[Service]\nExecStart=\/usr\/local\/bin\/buildkitd --oci-worker=false --containerd-worker=true\n\n[Install]\nWantedBy=multi-user.target"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"启用 buildkit.service 并设置开机自动运行:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → systemctl enable --now buildkit.service"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面以 "},{"type":"text","marks":[{"type":"strong"}],"text":"KubeSphere"},{"type":"sup","content":[{"type":"text","text":"[9]"}],"marks":[{"type":"strong"}]},{"type":"text","text":" 项目为例,展示如何使用 "},{"type":"codeinline","content":[{"type":"text","text":"nerdctl"}]},{"type":"text","text":" 来构建镜像。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先克隆 KubeSphere 官方仓库:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → git clone --depth=1 https:\/\/github.com.cnpmjs.org\/kubesphere\/kubesphere.git"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"进入仓库目录,编译二进制文件:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → cd kubesphere\n🐳  → make ks-apiserver"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"将二进制文件拷贝到 "},{"type":"codeinline","content":[{"type":"text","text":"Dockerfile"}]},{"type":"text","text":" 目录:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → cp bin\/cmd\/ks-apiserver build\/ks-apiserver"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"进入 "},{"type":"codeinline","content":[{"type":"text","text":"Dockerfile"}]},{"type":"text","text":" 目录,修改 Dockerfile:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"# Copyright 2020 The KubeSphere Authors. All rights reserved.\n# Use of this source code is governed by an Apache license\n# that can be found in the LICENSE file.\nFROM alpine:3.11\n\nARG HELM_VERSION=v3.5.2\n\nRUN apk add --no-cache ca-certificates\n# install helm\nRUN wget https:\/\/get.helm.sh\/helm-${HELM_VERSION}-linux-amd64.tar.gz && \\\n    tar xvf helm-${HELM_VERSION}-linux-amd64.tar.gz && \\\n    rm helm-${HELM_VERSION}-linux-amd64.tar.gz && \\\n    mv linux-amd64\/helm \/usr\/bin\/ && \\\n    rm -rf linux-amd64\n# To speed up building process, we copy binary directly from make\n# result instead of building it again, so make sure you run the\n# following command first before building docker image\n#   make ks-apiserver\n#\nCOPY  ks-apiserver \/usr\/local\/bin\/\n\nEXPOSE 9090\nCMD [\"sh\"]"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"构建镜像:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → cd build\/ks-apiserver\n\n🐳  → nerdctl build -t ks-apiserver .\n[+] Building 22.6s (9\/9) FINISHED\n => [internal] load build definition from Dockerfile                                                                                                                                0.0s\n => => transferring dockerfile: 812B                                                                                                                                                0.0s\n => [internal] load .dockerignore                                                                                                                                                   0.0s\n => => transferring context: 2B                                                                                                                                                     0.0s\n => [internal] load metadata for docker.io\/library\/alpine:3.11                                                                                                                      1.0s\n => [1\/4] FROM docker.io\/library\/alpine:3.11@sha256:bf5fa774f08a9ed2cb301e522b769d43d48124315a4ec50eae3228d03b9dc558                                                                7.9s\n => => resolve docker.io\/library\/alpine:3.11@sha256:bf5fa774f08a9ed2cb301e522b769d43d48124315a4ec50eae3228d03b9dc558                                                                0.0s\n => => sha256:9b794450f7b6db7c944ba1f4161edb68cb535052fe7db8ac06e613516c4a658d 2.10MB \/ 2.82MB                                                                                     21.4s\n => => extracting sha256:9b794450f7b6db7c944ba1f4161edb68cb535052fe7db8ac06e613516c4a658d                                                                                           0.1s\n => [internal] load build context                                                                                                                                                   1.0s\n => => transferring context: 115.87MB                                                                                                                                               1.0s\n => [2\/4] RUN apk add --no-cache ca-certificates                                                                                                                                    2.7s\n => [3\/4] RUN wget https:\/\/get.helm.sh\/helm-v3.5.2-linux-amd64.tar.gz &&     tar xvf helm-v3.5.2-linux-amd64.tar.gz &&     rm helm-v3.5.2-linux-amd64.tar.gz &&     mv linux-amd64  4.7s\n => [4\/4] COPY  ks-apiserver \/usr\/local\/bin\/                                                                                                                                        0.2s\n => exporting to oci image format                                                                                                                                                   5.9s\n => => exporting layers                                                                                                                                                             4.6s\n => => exporting manifest sha256:d7eb2a90496678d11ac5c363b7743ffe2b8e23e7071b94556a5e3231f50f5a6e                                                                                   0.0s\n => => exporting config sha256:8eb6a5187ce958e76c8d37e18221d88f25b48dd7e6672021d0fce21bb071f284                                                                                     0.0s\n => => sending tarball                                                                                                                                                              1.3s\nunpacking docker.io\/library\/ks-apiserver:latest (sha256:d7eb2a90496678d11ac5c363b7743ffe2b8e23e7071b94556a5e3231f50f5a6e)...done\nunpacking overlayfs@sha256:d7eb2a90496678d11ac5c363b7743ffe2b8e23e7071b94556a5e3231f50f5a6e (sha256:d7eb2a90496678d11ac5c363b7743ffe2b8e23e7071b94556a5e3231f50f5a6e)...done"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"查看构建好的镜像:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"🐳  → nerdctl images\n\nREPOSITORY                                                   TAG       IMAGE ID        CREATED          SIZE\nalpine                                                       3.11      bf5fa774f08a    3 seconds ago    2.7 MiB\nks-apiserver                                                 latest    d7eb2a904966    6 minutes ago    57.7 MiB"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"关于 nerdctl 的更多用法,可以参考"},{"type":"text","marks":[{"type":"strong"}],"text":"官方仓库的 README"},{"type":"sup","content":[{"type":"text","text":"[10]"}],"marks":[{"type":"strong"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"总结"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从行业趋势来看,Docker 已经和 Kubernetes 社区渐行渐远,以 "},{"type":"codeinline","content":[{"type":"text","text":"Containerd"}]},{"type":"text","text":" 为代表的实现了 "},{"type":"codeinline","content":[{"type":"text","text":"CRI"}]},{"type":"text","text":" 接口的容器运行时将会受到 Kubernetes 的青睐。但纯粹使用 Containerd 还是有诸多困扰,比如不方便通过 CLI 来创建管理容器,有了 "},{"type":"codeinline","content":[{"type":"text","text":"nerdctl"}]},{"type":"text","text":" 这个 CLI 工具,就就可以填补 Containerd 易用性的空缺,让你在单机上也能愉快地使用 Containerd。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"脚注"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[1]ctr: "},{"type":"text","marks":[{"type":"italic"}],"text":"https:\/\/github.com\/containerd\/containerd\/tree\/master\/cmd\/ctr"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[2]crictl: "},{"type":"text","marks":[{"type":"italic"}],"text":"https:\/\/github.com\/kubernetes-sigs\/cri-tools"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[3]nerdctl: "},{"type":"text","marks":[{"type":"italic"}],"text":"https:\/\/github.com\/containerd\/nerdctl"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[4]lazy-pulling: "},{"type":"text","marks":[{"type":"italic"}],"text":"https:\/\/github.com\/containerd\/nerdctl\/blob\/master\/docs\/stargz.md"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[5]imgcrypt: "},{"type":"text","marks":[{"type":"italic"}],"text":"https:\/\/github.com\/containerd\/imgcrypt"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[6]Containerd 使用 Stargz Snapshotter 延迟拉取镜像: "},{"type":"text","marks":[{"type":"italic"}],"text":"https:\/\/fuckcloudnative.io\/posts\/startup-containers-in-lightning-speed-with-lazy-image-distribution-on-containerd\/"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[7]可能需要几个月甚至几年的时间: "},{"type":"text","marks":[{"type":"italic"}],"text":"https:\/\/github.com\/moby\/moby\/pull\/41002"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[8]nerdctl 的 release: "},{"type":"text","marks":[{"type":"italic"}],"text":"https:\/\/github.com\/containerd\/nerdctl\/releases"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[9]KubeSphere: "},{"type":"text","marks":[{"type":"italic"}],"text":"https:\/\/github.com\/kubesphere\/kubesphere"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[10]官方仓库的 README: "},{"type":"text","marks":[{"type":"italic"}],"text":"https:\/\/github.com\/containerd\/nerdctl"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule"},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"头图:Unsplash"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作者:米开朗基杨"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:https:\/\/mp.weixin.qq.com\/s\/Bjn0s5qRh2H9I__mAYh4jg"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:终于可以像使用 Docker 一样丝滑地使用 Containerd 了!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"来源:KubeSphere云原生 - 微信公众号 [ID:gh_f5606464ef2f]"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章