• Containerd高级命令行工具nerdctl安装及使用


    一、实验环境

    1. 实验环境:
    2. 1、win10笔记本
    3. 2、1台centos7.6虚机(vmwrokstation虚机)
    4. cri-containerd-cni-1.5.5-linux-amd64.tar.gz
    5. nerdctl-0.12.1-linux-amd64.tar.gz

    二、实验软件

    GitHub - containerd/nerdctl: contaiNERD CTL - Docker-compatible CLI for containerd, with support for Compose, Rootless, eStargz, OCIcrypt, IPFS, ...

    GitHub - moby/buildkit: concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit

    三、nerdctl安装

    同样直接在 GitHub Release 页面下载对应的压缩包解压到 PATH 路径下即可:

    https://github.com/containerd/nerdctl

    下载nerdctl-0.12.1-linux-amd64.tar.gz软件包:

    1. # 如果没有安装 containerd,则可以下载 nerdctl-full--linux-amd64.tar.gz 包进行安装
    2. ➜ ~ wget https://github.com/containerd/nerdctl/releases/download/v0.12.1/nerdctl-0.12.1-linux-amd64.tar.gz
    3. # 如果有限制,也可以替换成下面的 URL 加速下载
    4. [root@containerd ~]#wget https://download.fastgit.org/containerd/nerdctl/releases/download/v0.12.1/nerdctl-0.12.1-linux-amd64.tar.gz
    5. --2021-10-25 13:13:43-- https://download.fastgit.org/containerd/nerdctl/releases/download/v0.12.1/nerdctl-0.12.1-linux-amd64.tar.gz
    6. Resolving download.fastgit.org (download.fastgit.org)... 88.198.10.254
    7. Connecting to download.fastgit.org (download.fastgit.org)|88.198.10.254|:443... connected.
    8. HTTP request sent, awaiting response... 200 OK
    9. Length: 7528755 (7.2M) [application/octet-stream]
    10. Saving to: ‘nerdctl-0.12.1-linux-amd64.tar.gz’
    11. 100%[===============================================================================================================================>] 7,528,755 3.31MB/s in 2.2s
    12. 2021-10-25 13:13:46 (3.31 MB/s) - ‘nerdctl-0.12.1-linux-amd64.tar.gz’ saved [7528755/7528755][root@containerd ~]#ll -h nerdctl-0.12.1-linux-amd64.tar.gz
    13. -rw-r--r-- 1 root root 7.2M Oct 5 15:10 nerdctl-0.12.1-linux-amd64.tar.gz
    14. [root@containerd ~]#

    解压软件包到相应目录:

    1. [root@containerd ~]#tar tf nerdctl-0.12.1-linux-amd64.tar.gz #先查看下压缩包文件内容
    2. nerdctl
    3. containerd-rootless-setuptool.sh
    4. containerd-rootless.sh
    5. [root@containerd ~]#mkdir -p /usr/local/containerd/bin && tar -zxvf nerdctl-0.12.1-linux-amd64.tar.gz nerdctl && mv nerdctl /usr/local/containerd/bin
    6. nerdctl
    7. [root@containerd ~]#ln -s /usr/local/containerd/bin/nerdctl /usr/bin/nerdctl

    验证:

    1. [root@containerd ~]#nerdctl version
    2. Client:
    3. Version: v0.12.1
    4. Git commit: 6f0c8b7bc63270404c9f5810a899e6bae7546608
    5. Server:
    6. containerd:
    7. Version: v1.5.5
    8. GitCommit: 72cec4be58a9eb6b2910f5d10f1c01ca47d231c0
    9. [root@containerd ~]#

    至此,nerdctl安装完成。

    安装完成后接下来学习下 nerdctl 命令行工具的使用。

    0、nerd帮助命令

    1. [root@containerd ~]#nerdctl
    2. NAME:
    3. nerdctl - Docker-compatible CLI for containerd
    4. USAGE:
    5. nerdctl [global options] command [command options] [arguments...]
    6. VERSION:
    7. 0.12.1
    8. COMMANDS:
    9. run Run a command in a new container
    10. exec Run a command in a running container
    11. ps List containers
    12. logs Fetch the logs of a container. Currently, only containers created with `nerdctl run -d` are supported.
    13. port List port mappings or a specific mapping for the container
    14. stop Stop one or more running containers
    15. start Start one or more running containers
    16. kill Kill one or more running containers
    17. rm Remove one or more containers
    18. pause Pause all processes within one or more containers
    19. unpause Unpause all processes within one or more containers
    20. commit [flags] CONTAINER REPOSITORY[:TAG]
    21. wait Block until one or more containers stop, then print their exit codes.
    22. build Build an image from a Dockerfile. Needs buildkitd to be running.
    23. images List images
    24. pull Pull an image from a registry
    25. push Push an image or a repository to a registry
    26. load Load an image from a tar archive or STDIN
    27. save Save one or more images to a tar archive (streamed to STDOUT by default)
    28. tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
    29. rmi Remove one or more images
    30. events Get real time events from the server
    31. info Display system-wide information
    32. version Show the nerdctl version information
    33. inspect Return low-level information on objects.
    34. top Display the running processes of a container
    35. login Log in to a Docker registry
    36. logout Log out from a Docker registry
    37. compose Compose
    38. completion Show shell completion
    39. help, h Shows a list of commands or help for one command
    40. Management:
    41. container Manage containers
    42. image Manage images
    43. network Manage networks
    44. volume Manage volumes
    45. system Manage containerd
    46. namespace Manage containerd namespaces
    47. GLOBAL OPTIONS:
    48. --debug debug mode (default: false)
    49. --debug-full debug mode (with full output) (default: false)
    50. --address value, -a value, --host value, -H value containerd address, optionally with "unix://" prefix (default: "/run/containerd/containerd.sock") [$CONTAINERD_ADDRESS]
    51. --namespace value, -n value containerd namespace, such as "moby" for Docker, "k8s.io" for Kubernetes (default: "default") [$CONTAINERD_NAMESPACE]
    52. --snapshotter value, --storage-driver value containerd snapshotter (default: "overlayfs") [$CONTAINERD_SNAPSHOTTER]
    53. --cni-path value Set the cni-plugins binary directory (default: "/opt/cni/bin") [$CNI_PATH]
    54. --cni-netconfpath value Set the CNI config directory (default: "/etc/cni/net.d") [$NETCONFPATH]
    55. --data-root value Root directory of persistent nerdctl state (managed by nerdctl, not by containerd) (default: "/var/lib/nerdctl")
    56. --cgroup-manager value Cgroup manager to use ("cgroupfs"|"systemd") (default: "cgroupfs")
    57. --insecure-registry skips verifying HTTPS certs, and allows falling back to plain HTTP (default: false)
    58. --help, -h show help (default: false)
    59. --version, -v print the version (default: false)
    60. [root@containerd ~]#

    1、Run&Exec ​

    🐳nerdctl run

    和 docker run 类似可以使用 nerdctl run 命令运行容器,例如:

    1. ➜ ~ nerdctl run -d -p 80:80 --name=nginx --restart=always nginx:alpine
    2. docker.io/library/nginx:alpine: resolved |++++++++++++++++++++++++++++++++++++++|
    3. index-sha256:bead42240255ae1485653a956ef41c9e458eb077fcb6dc664cbc3aa9701a05ce: done

    可选的参数使用和 docker run 基本一直,比如 -i-t--cpus--memory 等选项,可以使用 nerdctl run --help 获取可使用的命令选项:

    1. [root@containerd ~]#nerdctl run --help
    2. NAME:
    3. nerdctl run - Run a command in a new container
    4. USAGE:
    5. nerdctl run [command options] [arguments...]
    6. OPTIONS:
    7. --help show help (default: false)
    8. --tty, -t (Currently -t needs to correspond to -i) (default: false)
    9. --interactive, -i Keep STDIN open even if not attached (default: false)
    10. --detach, -d Run container in background and print container ID (default: false)
    11. --restart value Restart policy to apply when a container exits (implemented values: "no"|"always") (default: "no")
    12. --rm Automatically remove the container when it exits (default: false)
    13. --pull value Pull image before running ("always"|"missing"|"never") (default: "missing")
    14. --network value, --net value Connect a container to a network ("bridge"|"host"|"none") (default: "bridge")
    15. --dns value Set custom DNS servers
    16. --publish value, -p value Publish a container's port(s) to the host
    17. --hostname value, -h value Container host name
    18. --cpus value Number of CPUs (default: 0)
    19. --memory value, -m value Memory limit
    20. --pid value PID namespace to use
    21. --pids-limit value Tune container pids limit (set -1 for unlimited) (default: -1)
    22. --cgroupns value Cgroup namespace to use, the default depends on the cgroup version ("host"|"private") (default: "host")
    23. --cpuset-cpus value CPUs in which to allow execution (0-3, 0,1)
    24. --cpu-shares value CPU shares (relative weight) (default: 0)
    25. --device value Add a host device to the container
    26. --user value, -u value Username or UID (format: [:])
    27. --security-opt value Security options
    28. --cap-add value Add Linux capabilities
    29. --cap-drop value Drop Linux capabilities
    30. --privileged Give extended privileges to this container (default: false)
    31. --runtime value Runtime to use for this container, e.g. "crun", or "io.containerd.runsc.v1" (default: "io.containerd.runc.v2")
    32. --sysctl value Sysctl options
    33. --gpus value GPU devices to add to the container ('all' to pass all GPUs)
    34. --volume value, -v value Bind mount a volume
    35. --read-only Mount the container's root filesystem as read only (default: false)
    36. --rootfs The first argument is not an image but the rootfs to the exploded container (default: false)
    37. --entrypoint value Overwrite the default ENTRYPOINT of the image
    38. --workdir value, -w value Working directory inside the container
    39. --env value, -e value Set environment variables
    40. --add-host value Add a custom host-to-IP mapping (host:ip)
    41. --env-file value Set environment variables from file
    42. --name value Assign a name to the container
    43. --label value, -l value Set meta data on a container
    44. --label-file value Read in a line delimited file of labels
    45. --cidfile value Write the container ID to the file
    46. --shm-size value Size of /dev/shm
    47. --pidfile value file path to write the task's pid
    48. --ulimit value Ulimit options
    49. [root@containerd ~]#

    🐳nerdctl exec

    同样也可以使用 exec 命令执行容器相关命令,例如:

    1. ➜  ~ nerdctl exec -it nginx /bin/sh
    2. # date
    3. Thu Aug 19 06:43:19 UTC 2021
    4. #

    2、容器管理

    🐳nerdctl ps:列出容器

    使用 nerdctl ps 命令可以列出所有容器。

    1. ➜  ~ nerdctl ps
    2. CONTAINER ID    IMAGE                             COMMAND                   CREATED           STATUS    PORTS                 NAMES
    3. 6e489777d2f7    docker.io/library/nginx:alpine    "/docker-entrypoint.…"    10 minutes ago    Up        0.0.0.0:80->80/tcp    nginx

    同样可以使用 -a 选项显示所有的容器列表,默认只显示正在运行的容器,不过需要注意的是 nerdctl ps 命令并没有实现 docker ps 下面的 --filter--format--last--size 等选项。

    🐳nerdctl inspect:获取容器的详细信息。

    1. ➜ ~ nerdctl inspect nginx
    2. [
    3. {
    4. "Id": "6e489777d2f73dda8a310cdf8da9df38353c1aa2021d3c2270b30eff1806bcf8",
    5. "Created": "2021-08-19T06:35:46.403464674Z",
    6. "Path": "/docker-entrypoint.sh",
    7. "Args": [
    8. "nginx",
    9. "-g",
    10. "daemon off;"
    11. ],
    12. "State": {
    13. "Status": "running",
    14. "Running": true,
    15. "Paused": false,
    16. "Pid": 2002,
    17. "ExitCode": 0,
    18. "FinishedAt": "0001-01-01T00:00:00Z"
    19. },
    20. "Image": "docker.io/library/nginx:alpine",
    21. "ResolvConfPath": "/var/lib/nerdctl/1935db59/containers/default/6e489777d2f73dda8a310cdf8da9df38353c1aa2021d3c2270b30eff1806bcf8/resolv.conf",
    22. "LogPath": "/var/lib/nerdctl/1935db59/containers/default/6e489777d2f73dda8a310cdf8da9df38353c1aa2021d3c2270b30eff1806bcf8/6e489777d2f73dda8a310cdf8da9df38353c1aa2021d3c2270b30eff1806bcf8-json.log",
    23. "Name": "nginx",
    24. "Driver": "overlayfs",
    25. "Platform": "linux",
    26. "AppArmorProfile": "nerdctl-default",
    27. "NetworkSettings": {
    28. "Ports": {
    29. "80/tcp": [
    30. {
    31. "HostIp": "0.0.0.0",
    32. "HostPort": "80"
    33. }
    34. ]
    35. },
    36. "GlobalIPv6Address": "",
    37. "GlobalIPv6PrefixLen": 0,
    38. "IPAddress": "10.4.0.3",
    39. "IPPrefixLen": 24,
    40. "MacAddress": "f2:b1:8e:a2:fe:18",
    41. "Networks": {
    42. "unknown-eth0": {
    43. "IPAddress": "10.4.0.3",
    44. "IPPrefixLen": 24,
    45. "GlobalIPv6Address": "",
    46. "GlobalIPv6PrefixLen": 0,
    47. "MacAddress": "f2:b1:8e:a2:fe:18"
    48. }
    49. }
    50. }
    51. }
    52. ]

    可以看到显示结果和 docker inspect 也基本一致的。

    🐳nerdctl logs:获取容器日志

    查看容器日志是我们平时经常会使用到的一个功能,同样我们可以使用 nerdctl logs 来获取日志数据:

    1. ➜  ~ nerdctl logs -f nginx
    2. ......
    3. 2021/08/19 06:35:46 [notice] 1#1: start worker processes
    4. 2021/08/19 06:35:46 [notice] 1#1: start worker process 32
    5. 2021/08/19 06:35:46 [notice] 1#1: start worker process 33

    同样支持 -f-t-n--since--until 这些选项。

    1. #-n选项:
    2. [root@containerd ~]#nerdctl logs -n 3 nginx_bak
    3. 2021/10/24 23:17:40 [notice] 1#1: start worker process 32
    4. 2021/10/24 23:17:40 [notice] 1#1: start worker process 33
    5. 10.4.0.1 - - [24/Oct/2021:23:42:57 +0000"GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
    6. [root@containerd ~]#

    🐳nerdctl stop:停止容器

    1. ➜  ~ nerdctl stop nginx
    2. nginx
    3. ➜  ~ nerdctl ps
    4. CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES
    5. ➜  ~ nerdctl ps -a
    6. CONTAINER ID    IMAGE                             COMMAND                   CREATED           STATUS    PORTS                 NAMES
    7. 6e489777d2f7    docker.io/library/nginx:alpine    "/docker-entrypoint.…"    20 minutes ago    Up        0.0.0.0:80->80/tcp    nginx

    🐳nerdctl rm:删除容器

    1. ➜  ~ nerdctl rm nginx
    2. You cannot remove a running container f4ac170235595f28bf962bad68aa81b20fc83b741751e7f3355bd77d8016462d. Stop the container before attempting removal or force remove
    3. ➜  ~ nerdctl rm -f ginx
    4. nginx
    5. ➜  ~ nerdctl ps
    6. CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES

    要强制删除同样可以使用 -f 或 --force 选项来操作。

    3、镜像管理

    🐳nerdctl images:镜像列表

    1. ➜  ~ nerdctl images
    2. REPOSITORY    TAG       IMAGE ID        CREATED           SIZE
    3. alpine        latest    eb3e4e175ba6    6 days ago        5.9 MiB
    4. nginx         alpine    bead42240255    29 minutes ago    16.0 KiB

    也需要注意的是没有实现 docker images 的一些选项,比如 --all--digests--filter--format

    nerdctl images 和 ctr i ls的对比,nerctl更友好:

    1. [root@containerd ~]#nerdctl images
    2. REPOSITORY    TAG       IMAGE ID        CREATED         SIZE
    3. nginx         alpine    686aac2769fd    38 hours ago    24.9 MiB
    4. [root@containerd ~]#ctr i ls
    5. REF                            TYPE                                                      DIGEST                                                                  SIZE    PLATFORMS                                                                                LABELS
    6. docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:686aac2769fd6e7bab67663fd38750c135b72d993d0bb0a942ab02ef647fc9c3 9.5 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -
    7. [root@containerd ~]#

    🐳nerdctl pull:拉取镜像

    1. [root@containerd ~]#nerdctl images
    2. REPOSITORY    TAG       IMAGE ID        CREATED         SIZE
    3. nginx         alpine    686aac2769fd    38 hours ago    24.9 MiB
    4. [root@containerd ~]#nerdctl pull busybox #nerdctl很优秀,可以直接接镜像名的,而不像ctr命令那样繁琐。
    5. docker.io/library/busybox:latest:                                                 resolved       |++++++++++++++++++++++++++++++++++++++|
    6. index-sha256:f7ca5a32c10d51aeda3b4d01c61c6061f497893d7f6628b92f822f7117182a57:    done           |++++++++++++++++++++++++++++++++++++++|
    7. manifest-sha256:febcf61cd6e1ac9628f6ac14fa40836d16f3c6ddef3b303ff0321606e55ddd0b: done           |++++++++++++++++++++++++++++++++++++++|
    8. config-sha256:16ea53ea7c652456803632d67517b78a4f9075a10bfdc4fc6b7b4cbf2bc98497:   done           |++++++++++++++++++++++++++++++++++++++|
    9. layer-sha256:24fb2886d6f6c5d16481dd7608b47e78a8e92a13d6e64d87d57cb16d5f766d63:    done           |++++++++++++++++++++++++++++++++++++++|
    10. elapsed: 5.9 s                                                                    total:  753.5  (127.7 KiB/s)                       
    11. [root@containerd ~]#nerdctl images
    12. REPOSITORY    TAG       IMAGE ID        CREATED          SIZE
    13. busybox       latest    f7ca5a32c10d    2 seconds ago    1.2 MiB
    14. nginx         alpine    686aac2769fd    38 hours ago     24.9 MiB
    15. [root@containerd ~]#

    🐳nerdctl push:推送镜像

    当然在推送镜像之前也可以使用 nerdctl login 命令登录到镜像仓库,然后再执行 push 操作。

    可以使用 nerdctl login --username xxx --password xxx 进行登录,使用 nerdctl logout 可以注销退出登录。

    1. [root@containerd ~]#nerdctl push harbor.k8s.local/course/nginx:alpine
    2. [root@containerd ~]#nerdctl login --username xxx --password xxx harbor.k8s.local
    3. [root@containerd ~]#nerdctl logout
    4. Removing login credentials for https://index.docker.io/v1/
    5. [root@containerd ~]#

    🐳nerdctl tag:镜像标签

    使用 tag 命令可以为一个镜像创建一个别名镜像:

    1. ➜  ~ nerdctl images
    2. REPOSITORY    TAG                  IMAGE ID        CREATED           SIZE
    3. busybox       latest               0f354ec1728d    6 minutes ago     1.3 MiB
    4. nginx         alpine               bead42240255    41 minutes ago    16.0 KiB
    5. ➜  ~ nerdctl tag nginx:alpine harbor.k8s.local/course/nginx:alpine
    6. ➜  ~ nerdctl images
    7. REPOSITORY                       TAG                  IMAGE ID        CREATED           SIZE
    8. busybox                          latest               0f354ec1728d    7 minutes ago     1.3 MiB
    9. nginx                            alpine               bead42240255    41 minutes ago    16.0 KiB
    10. harbor.k8s.local/course/nginx    alpine               bead42240255    2 seconds ago     16.0 KiB

    注意:用tag打的镜像,其Image ID都是相同的:

    image-20211025101448781

    🐳nerdctl save:导出镜像

    使用 save 命令可以导出镜像为一个 tar 压缩包。

    1. ➜  ~ nerdctl save -o busybox.tar.gz busybox:latest
    2. ➜  ~ ls -lh busybox.tar.gz
    3. -rw-r--r-- 1 root root 761K Aug 19 15:19 busybox.tar.gz

    🐳nerdctl rmi:删除镜像

    1. ➜  ~ nerdctl rmi busybox
    2. Untagged: docker.io/library/busybox:latest@sha256:0f354ec1728d9ff32edcd7d1b8bbdfc798277ad36120dc3dc683be44524c8b60
    3. Deleted: sha256:5b8c72934dfc08c7d2bd707e93197550f06c0751023dabb3a045b723c5e7b373

    🐳nerdctl load:导入镜像

    使用 load 命令可以将上面导出的镜像再次导入:

    1. ➜  ~ nerdctl load -i busybox.tar.gz
    2. unpacking docker.io/library/busybox:latest (sha256:0f354ec1728d9ff32edcd7d1b8bbdfc798277ad36120dc3dc683be44524c8b60)...done

    使用 -i 或 --input 选项指定需要导入的压缩包。

    4、镜像构建

    镜像构建是平时我们非常重要的一个需求,我们知道 ctr 并没有构建镜像的命令,而现在我们又不使用 Docker 了,那么如何进行镜像构建了,幸运的是 nerdctl 就提供了 nerdctl build 这样的镜像构建命令。

    🐳nerdctl build:从 Dockerfile 构建镜像

    比如现在我们定制一个 nginx 镜像,新建一个如下所示的 Dockerfile 文件:

    1. [root@containerd ~]#mkdir -p /root/nerctl_demo
    2. [root@containerd ~]#cd /root/nerctl_demo/
    3. [root@containerd nerctl_demo]#cat > Dockerfile <
    4. > FROM nginx:alpine
    5. > RUN echo 'Hello Nerdctl From Containerd' > /usr/share/nginx/html/index.html
    6. > EOF
    7. [root@containerd nerctl_demo]#cat Dockerfile
    8. FROM nginx:alpine
    9. RUN echo 'Hello Nerdctl From Containerd' > /usr/share/nginx/html/index.html

    然后在文件所在目录执行镜像构建命令:

    1. [root@containerd nerctl_demo]#nerdctl build -t nginx:nerctl -f Dockefile .
    2. FATA[0000`buildctl` needs to be installed and `buildkitd` needs to be running, see https://github.com/moby/buildkit: exec"buildctl": executable file not found in $PATH
    3. [root@containerd nerctl_demo]#

    注意:也可以加上这个--no-cache选项

    1. #--no-cache选项
    2. --no-cache                Do not use cache when building the image (defaultfalse)

    可以看到有一个错误提示,需要我们安装 buildctl 并运行 buildkitd,这是因为 nerdctl build 需要依赖 buildkit 工具。

    buildkit 项目也是 Docker 公司开源的一个构建工具包,支持 OCI 标准的镜像构建。它主要包含以下部分:

    • 服务端 buildkitd:当前支持 runc 和 containerd 作为 worker,默认是 runc,我们这里使用 containerd

    • 客户端 buildctl:负责解析 Dockerfile,并向服务端 buildkitd 发出构建请求

    buildkit 是典型的 C/S 架构,客户端和服务端是可以不在一台服务器上,而 nerdctl 在构建镜像的时候也作为 buildkitd 的客户端,所以需要我们安装并运行 buildkitd

    https://github.com/moby/buildkit

    所以接下来我们先来安装 buildkit

    1. ➜  ~ wget https://github.com/moby/buildkit/releases/download/v0.9.1/buildkit-v0.9.1.linux-amd64.tar.gz
    2. # 如果有限制,也可以替换成下面的 URL 加速下载
    3. # wget https://download.fastgit.org/moby/buildkit/releases/download/v0.9.1/buildkit-v0.9.1.linux-amd64.tar.gz
    4. [root@containerd ~]#ll -h buildkit-v0.9.1.linux-amd64.tar.gz
    5. -rw-r--r-- 1 root root 46M Oct  5 03:51 buildkit-v0.9.1.linux-amd64.tar.gz
    6. [root@containerd ~]#tar tf buildkit-v0.9.1.linux-amd64.tar.gz
    7. bin/
    8. bin/buildctl
    9. bin/buildkit-qemu-aarch64
    10. bin/buildkit-qemu-arm
    11. bin/buildkit-qemu-i386
    12. bin/buildkit-qemu-mips64
    13. bin/buildkit-qemu-mips64el
    14. bin/buildkit-qemu-ppc64le
    15. bin/buildkit-qemu-riscv64
    16. bin/buildkit-qemu-s390x
    17. bin/buildkit-runc
    18. bin/buildkitd
    19. [root@containerd ~]#
    20. ➜  ~ tar -zxvf buildkit-v0.9.1.linux-amd64.tar.gz -C /usr/local/containerd/
    21. bin/
    22. bin/buildctl
    23. bin/buildkit-qemu-aarch64
    24. bin/buildkit-qemu-arm
    25. bin/buildkit-qemu-i386
    26. bin/buildkit-qemu-mips64
    27. bin/buildkit-qemu-mips64el
    28. bin/buildkit-qemu-ppc64le
    29. bin/buildkit-qemu-riscv64
    30. bin/buildkit-qemu-s390x
    31. bin/buildkit-runc
    32. bin/buildkitd
    33. ➜  ~ ln -s /usr/local/containerd/bin/buildkitd /usr/local/bin/buildkitd
    34. ➜  ~ ln -s /usr/local/containerd/bin/buildctl /usr/local/bin/buildctl

    这里我们使用 Systemd 来管理 buildkitd,创建如下所示的 systemd unit 文件:

    1. cat > /etc/systemd/system/buildkit.service <<EOF
    2. [Unit]
    3. Description=BuildKit
    4. Documentation=https://github.com/moby/buildkit
    5. [Service]
    6. ExecStart=/usr/local/bin/buildkitd --oci-worker=false --containerd-worker=true
    7. [Install]
    8. WantedBy=multi-user.target
    9. EOF

    然后启动 buildkitd

    1. [root@containerd ~]#systemctl deamon-reload
    2. Unknown operation 'deamon-reload'.
    3. [root@containerd ~]#systemctl daemon-reload
    4. [root@containerd ~]#systemctl enable buildkit --now
    5. Created symlink from /etc/systemd/system/multi-user.target.wants/buildkit.service to /etc/systemd/system/buildkit.service.
    6. [root@containerd ~]#systemctl status buildkit
    7. ● buildkit.service - BuildKit
    8.    Loaded: loaded (/etc/systemd/system/buildkit.service; enabled; vendor preset: disabled)
    9.    Active: active (running) since Mon 2021-10-25 16:11:47 CST; 13s ago
    10.      Docs: https://github.com/moby/buildkit
    11.  Main PID: 26680 (buildkitd)
    12.     Tasks: 7
    13.    Memory: 13.5M
    14.    CGroup: /system.slice/buildkit.service
    15.            └─26680 /usr/local/bin/buildkitd --oci-worker=false --containerd-worker=true
    16. Oct 25 16:11:47 containerd systemd[1]: Started BuildKit.
    17. Oct 25 16:11:47 containerd buildkitd[26680]: time="2021-10-25T16:11:47+08:00" level=warning msg="using host network as the default"
    18. Oct 25 16:11:47 containerd buildkitd[26680]: time="2021-10-25T16:11:47+08:00" level=info msg="found worker \"72ur53vv5olwy9wv0oc46...
    19. Oct 25 16:11:47 containerd buildkitd[26680]: time="2021-10-25T16:11:47+08:00" level=info msg="found 1 workers, default=\"72u...cc6\""
    20. Oct 25 16:11:47 containerd buildkitd[26680]: time="2021-10-25T16:11:47+08:00" level=warning msg="currently, only the default...used."
    21. Oct 25 16:11:47 containerd buildkitd[26680]: time="2021-10-25T16:11:47+08:00" level=info msg="running server on /run/buildki....sock"
    22. Hint: Some lines were ellipsized, use -to show in full.
    23. [root@containerd ~]#
    24. #可以看下日志
    25. [root@containerd ~]#journalctl -u buildkit
    26. -- Logs begin at Sat 2021-10-23 13:52:41 CST, end at Mon 2021-10-25 16:11:47 CST. --
    27. Oct 25 16:11:47 containerd systemd[1]: Started BuildKit.
    28. Oct 25 16:11:47 containerd buildkitd[26680]: time="2021-10-25T16:11:47+08:00" level=warning msg="using host network as the default"
    29. Oct 25 16:11:47 containerd buildkitd[26680]: time="2021-10-25T16:11:47+08:00" level=info msg="found worker \"72ur53vv5olwy9wv0oc46bcc
    30. Oct 25 16:11:47 containerd buildkitd[26680]: time="2021-10-25T16:11:47+08:00" level=info msg="found 1 workers, default=\"72ur53vv5olw
    31. Oct 25 16:11:47 containerd buildkitd[26680]: time="2021-10-25T16:11:47+08:00" level=warning msg="currently, only the default worker c
    32. Oct 25 16:11:47 containerd buildkitd[26680]: time="2021-10-25T16:11:47+08:00" level=info msg="running server on /run/buildkit/buildki
    33. lines 1-7/7 (END)

    现在我们再来重新构建镜像:

    1. [root@containerd ~]#cd nerctl_demo/
    2. [root@containerd nerctl_demo]#ls
    3. Dockerfile
    4. [root@containerd nerctl_demo]#nerdctl build  -t nginx:nerctl -f Dockerfile .
    5. [+] Building 7.2s (6/6) FINISHED
    6.  => [internal] load build definition from Dockerfile                                                                            0.0s
    7.  => => transferring dockerfile: 131B                                                                                            0.0s
    8.  => [internal] load .dockerignore                                                                                               0.0s
    9.  => => transferring context: 2B                                                                                                 0.0s
    10.  => [internal] load metadata for docker.io/library/nginx:alpine                                                                 4.1s
    11.  => [1/2] FROM docker.io/library/nginx:alpine@sha256:686aac2769fd6e7bab67663fd38750c135b72d993d0bb0a942ab02ef647fc9c3           1.1s
    12.  => => resolve docker.io/library/nginx:alpine@sha256:686aac2769fd6e7bab67663fd38750c135b72d993d0bb0a942ab02ef647fc9c3           0.0s
    13.  => => extracting sha256:a0d0a0d46f8b52473982a3c466318f479767577551a53ffc9074c9fa7035982e                                       0.2s
    14.  => => extracting sha256:4dd4efe90939ab5711aaf5fcd9fd8feb34307bab48ba93030e8b845f8312ed8e                                       0.8s
    15.  => => extracting sha256:c1368e94e1ec563b31c3fb1fea02c9fbdc4c79a95e9ad0cac6df29c228ee2df3                                       0.0s
    16.  => => extracting sha256:3e72c40d0ff43c52c5cc37713b75053e8cb5baea8e137a784d480123814982a2                                       0.0s
    17.  => => extracting sha256:969825a5ca61c8320c63ff9ce0e8b24b83442503d79c5940ba4e2f0bd9e34df8                                       0.0s
    18.  => => extracting sha256:61074acc7dd227cfbeaf719f9b5cdfb64711bc6b60b3865c7b886b7099c15d15                                       0.0s
    19.  => [2/2] RUN echo 'Hello Nerdctl From Containerd' > /usr/share/nginx/html/index.html                                           0.5s
    20.  => exporting to oci image format                                                                                               1.3s
    21.  => => exporting layers                                                                                                         0.3s
    22.  => => exporting manifest sha256:c5ab5ef3d410c1e7e8140eaf48f92c7b2a70d6f8d75a4bd26636db0e886101aa                               0.0s
    23.  => => exporting config sha256:faa17ba50c10a48d128f1369bca7640083c48249239d9dd95ea30f88a4e387b5                                 0.0s
    24.  => => sending tarball                                                                                                          0.9s
    25. unpacking docker.io/library/nginx:nerctl (sha256:c5ab5ef3d410c1e7e8140eaf48f92c7b2a70d6f8d75a4bd26636db0e886101aa)...done
    26. [root@containerd nerctl_demo]#nerdctl images
    27. REPOSITORY    TAG       IMAGE ID        CREATED          SIZE
    28. nginx         alpine    686aac2769fd    47 hours ago     24.9 MiB
    29. nginx         nerctl    c5ab5ef3d410    9 seconds ago    24.9 MiB
    30. [root@containerd nerctl_demo]#

    构建完成后查看镜像是否构建成功:

    1. [root@containerd nerctl_demo]#nerdctl images
    2. REPOSITORY    TAG       IMAGE ID        CREATED          SIZE
    3. nginx         alpine    686aac2769fd    47 hours ago     24.9 MiB
    4. nginx         nerctl    c5ab5ef3d410    9 seconds ago    24.9 MiB
    5. [root@containerd nerctl_demo]#

    我们可以看到已经有我们构建的 nginx:nerdctl 镜像了。接下来使用上面我们构建的镜像来启动一个容器进行测试:

    1. [root@containerd ~]#nerdctl ps -a
    2. CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES
    3. [root@containerd ~]#nerdctl images
    4. REPOSITORY    TAG       IMAGE ID        CREATED          SIZE
    5. nginx         alpine    686aac2769fd    47 hours ago     24.9 MiB
    6. nginx         nerctl    c5ab5ef3d410    4 minutes ago    24.9 MiB
    7. [root@containerd ~]#nerdctl run -d -p 80:80 --name=nginx88  nginx:nerctl
    8. 1a5ae8262e78b3c0bf9e9da56789b9b6529e11ab7b53934841ada4e712210001
    9. [root@containerd ~]#nerdctl ps -a
    10. CONTAINER ID    IMAGE                             COMMAND                   CREATED          STATUS    PORTS                 NAMES
    11. 1a5ae8262e78    docker.io/library/nginx:nerctl    "/docker-entrypoint.…"    6 seconds ago    Up        0.0.0.0:80->80/tcp    nginx88
    12. [root@containerd ~]#curl localhost
    13. Hello Nerdctl From Containerd
    14. [root@containerd ~]#

    这样我们就使用 nerdctl + buildkitd 轻松完成了容器镜像的构建。

    完美。

    当然如果你还想在单机环境下使用 Docker Compose,在 containerd 模式下,我们也可以使用 nerdctl 来兼容该功能。同样我们可以使用 nerdctl composenerdctl compose upnerdctl compose logsnerdctl compose buildnerdctl compose down 等命令来管理 Compose 服务。这样使用 containerd、nerdctl 结合 buildkit 等工具就完全可以替代 docker 在镜像构建、镜像容器方面的管理功能了。

    1. [root@containerd ~]#nerdctl volume ls
    2. VOLUME NAME    DIRECTORY
    3. [root@containerd ~]#nerdctl network ls
    4. NETWORK ID    NAME              FILE
    5. 0             bridge
    6.               containerd-net    /etc/cni/net.d/10-containerd-net.conflist
    7.               host
    8.               none
    9. [root@containerd ~]#nerdctl namespace ls
    10. NAME        CONTAINERS    IMAGES    VOLUMES
    11. buildkit    0             0         0
    12. default     1             2         0
    13. test        0             1         0
    14. [root@containerd ~]#

    四、需要注意的问题 

    :question:(待解决)nerdctl run命令创建出的容器在宿主机上看不到端口号,奇怪

    • 很奇怪,这个现象:

    创建的容器映射到宿主机上的端口,在宿主机上没有查看的到。-->是个遗留问题,老师说正常情况是可以看到的才对。可能是底层走的是iptables。老师也没排查出来,当做遗留问题。

    测试过程如下:

    查看环境:

    1. [root@containerd ~]#ctr i ls -q
    2. docker.io/library/nginx:alpine
    3. [root@containerd ~]#ctr t ls
    4. TASK    PID    STATUS
    5. [root@containerd ~]#netstat -ntlp #没有80端口被占用
    6. Active Internet connections (only servers)
    7. Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    8. tcp        0      0 127.0.0.1:42797         0.0.0.0:*               LISTEN      8116/containerd
    9. tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      6587/sshd
    10. tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      6858/master
    11. tcp6       0      0 :::22                   :::*                    LISTEN      6587/sshd
    12. tcp6       0      0 ::1:25                  :::*                    LISTEN      6858/master
    13. [root@containerd ~]#

    创建容器:

    1. [root@containerd ~]#nerdctl run -d -p 80:80 --name=nginx_bak docker.io/library/nginx:alpine
    2. daf6ed8901335002c2edde96a3639da4a201f44a1ed74cb2b6a29221bf2603cb
    3. [root@containerd ~]#

    验证:

    发现容器是创建成功了,但是宿主机上是没有出现这个80端口,很奇怪:

    1. [root@containerd ~]#ctr t ls
    2. TASK                                                                PID      STATUS
    3. daf6ed8901335002c2edde96a3639da4a201f44a1ed74cb2b6a29221bf2603cb    28327    RUNNING
    4. [root@containerd ~]#ctr c ls
    5. CONTAINER                                                           IMAGE                             RUNTIME
    6. daf6ed8901335002c2edde96a3639da4a201f44a1ed74cb2b6a29221bf2603cb    docker.io/library/nginx:alpine    io.containerd.runc.v2
    7. [root@containerd ~]#ps -ef|grep nginx
    8. root      28327  28296  0 07:17 ?        00:00:00 nginx: master process nginx -g daemon off;
    9. 101       28441  28327  0 07:17 ?        00:00:00 nginx: worker process
    10. 101       28442  28327  0 07:17 ?        00:00:00 nginx: worker process
    11. root      28503  28223  0 07:41 pts/0    00:00:00 grep --color=auto nginx
    12. [root@containerd ~]#
    13. [root@containerd ~]#curl localhost
    14. html>
    15. <html>
    16. <head>
    17. <title>Welcome to nginx!title>
    18. <style>
    19. html { color-scheme: light dark; }
    20. body { width35emmargin0 auto;
    21. font-family: Tahoma, Verdana, Arial, sans-serif; }
    22. style>
    23. head>
    24. <body>
    25. <h1>Welcome to nginx!h1>
    26. <p>If you see this page, the nginx web server is successfully installed and
    27. working. Further configuration is required.p>
    28. <p>For online documentation and support please refer to
    29. <a href="http://nginx.org/">nginx.orga>.<br/>
    30. Commercial support is available at
    31. <a href="http://nginx.com/">nginx.coma>.p>
    32. <p><em>Thank you for using nginx.em>p>
    33. body>
    34. html>
    35. [root@containerd ~]#
    36. [root@containerd ~]#netstat -ntlp
    37. Active Internet connections (only servers)
    38. Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    39. tcp        0      0 127.0.0.1:42797         0.0.0.0:*               LISTEN      8116/containerd
    40. tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      6587/sshd
    41. tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      6858/master
    42. tcp6       0      0 :::22                   :::*                    LISTEN      6587/sshd
    43. tcp6       0      0 ::1:25                  :::*                    LISTEN      6858/master
    44. [root@containerd ~]#ctr c info daf6ed8901335002c2edde96a3639da4a201f44a1ed74cb2b6a29221bf2603cb|l

    :question:(待解决)还有个奇怪的问题就是:容器名被占用问题。。。

    这个我就想不通,原来创建的容器已经被删除了,怎么创建同名的容器还报错呢。。。

    :heavy_check_mark:(已解决)nerdctl为啥没有自动补全呢?

    已解决!

    和这个kubectl的一样,按这个方法配置下就可以自动补全命令了,666.

    1. [root@containerd ~]#yum install -y epel-release bash-completion
    2. [root@containerd ~]#source /usr/share/bash-completion/bash_completion
    3. [root@containerd ~]#source <(nerdctl completion bash)
    4. [root@containerd ~]#echo "source <(nerdctl completion bash)" >> ~/.bashrc
    5. [root@containerd ~]#source ~/.bashrc
    6. [root@containerd ~]#nerdctl r
    7. rm rmi run
    8. [root@containerd ~]#nerdctl r

    :heavy_check_mark:注意:不推荐使用commit去构建对象,而是要用build去构建对象

    不推荐使用commit去构建对象,而是要用build去构建对象。--->不知道为啥。。。。

    1. build       Build an image from a Dockerfile. Needs buildkitd to be running.
    2. commit      [flags] CONTAINER REPOSITORY[:TAG]

    :heavy_check_mark:注意:用build构建镜像时,下面这个.问题。

    docker的架构是cs架构:all请求,包括构建镜像

    很多同学认为这里的点代表dockerfile的地址,其实这里的.和dockerfile的地址是有区别的:

    dockerfile的地址你可以任意去指定;

    其实这个点表示:构建上下文,就是你所要构建文件上下文是在哪些地方。就是你dockerfile里面的东西都是相对于你上下文的,因为你构建上下文all的事情都是上传到dockerd后台的,你不要考虑在本地。

    因此,有个不好的情况就是,假如说你的dockerfile文件在/目录下:

    可想而知,它会把你/目录下all文件全部上传到dockerd上面去,就会特别特别慢,会出问题的。

    所以,这里的点构建上下文并不是随便指定的。

    :heavy_check_mark:注意:containerd网络,它对接的是cni

    1. [root@containerd ~]#nerdctl network ls
    2. NETWORK ID    NAME              FILE
    3. 0             bridge
    4.               containerd-net    /etc/cni/net.d/10-containerd-net.conflist
    5.               host
    6.               none
    7. [root@containerd ~]#

    /etc/cni/net.d/,这个其实是我们标准CNI的一个配置方式:

    就是我们后面要讲的flannel都是放在这个下面的。

    但是这种情况下,我们直接用这个配置文件去创建我们的k8s集群,即使你是创建的一个flannel网络插件,但是启动起来pod后,它还是不会使用这个flannel插件的。就是这个目录下的all conflist cni插件,好像是按这个字母顺序来加载的,所以会优先加载这个10-containerd-net.conflist的,也就是containerd本地的一个网络配置:

    1. [root@containerd net.d]#cat 10-containerd-net.conflist
    2. {
    3.   "cniVersion""0.4.0",
    4.   "name""containerd-net",
    5.   "plugins": [
    6.     {
    7.       "type""bridge",
    8.       "bridge""cni0",
    9.       "isGateway"true,
    10.       "ipMasq"true,
    11.       "promiscMode"true,
    12.       "ipam": {
    13.         "type""host-local",
    14.         "ranges": [
    15.           [{
    16.             "subnet""10.88.0.0/16"
    17.           }],
    18.           [{
    19.             "subnet""2001:4860:4860::/64"
    20.           }]
    21.         ],
    22.         "routes": [
    23.           { "dst""0.0.0.0/0" },
    24.           { "dst""::/0" }
    25.         ]
    26.       }
    27.     },
    28.     {
    29.       "type""portmap",
    30.       "capabilities": {"portMappings"true}
    31.     }
    32.   ]
    33. }
    34. [root@containerd net.d]#

    就是一个bridge模式。

    如果你自己要去创建网络也是可以的啊,和docker一样,其实都是对接的我们cni,你可以认为它是可以直接去对接的:

    1. [root@containerd ~]#nerdctl network ls
    2. NETWORK ID    NAME              FILE
    3. 0             bridge
    4.               containerd-net    /etc/cni/net.d/10-containerd-net.conflist
    5.               host
    6.               none
    7. [root@containerd ~]#

    就是你可以把这个/etc/cni/net.d/10-containerd-net.conflist给删除掉,然后你自己在下面创建一个cni的配置,也是可以的。

    所以,你后面在k8s里如果使用containerd来搭建集群的话,你需要把/etc/cni/net.d/10-containerd-net.conflist这个给移除掉,否则可能你创建出的pod它所使用的网段都是/etc/cni/net.d/10-containerd-net.conflist里面的"subnet": "2001:4860:4860::/64",没有使用你的flannel插件配置或者你的其他网络插件。

    :heavy_check_mark:注意:nerdctl在构建镜像时可以配置.dockerignore文件的。

    也就是说在构建镜像时,可以配置下要忽略的文件,否则这个文件也一起会被提交到buildkitd后台的。

  • 相关阅读:
    maven 进阶
    spring boot 自定义配置文件并提示及NestedConfigurationProperty注解作用
    【毕业设计】基于javaEE+原生Servlet+MySql的Web停车场管理系统设计与实现(毕业论文+程序源码)——停车场管理系统
    排查线上问题的9种方式
    【机器学习】如何判断函数凸或非凸?(面试回答)
    数据库计算机三级等级考试--数据库技术相关知识点和笔记
    【物联网安全知多少?】
    JSP SSH毕业论文管理统myeclipse开发mysql数据库MVC模式java编程网页设计
    金仓数据库 KingbaseES 插件参考手册(22. dbms_sql)
    Python将字符串转换成dataframe
  • 原文地址:https://blog.csdn.net/zfw_666666/article/details/126174036