Containerd 入门教程:离线安装与 Hello World
·
Containerd 入门教程:离线安装与 Hello World
前置说明
目标读者
- 熟悉 Linux 基本命令
- 了解容器基本概念
- 需要在无网络环境部署容器
你将学到
- containerd 是什么,为什么选择它
- 离线安装 containerd 的完整流程
- 使用 ctr 命令管理镜像和容器
- 启动第一个 Hello World 容器
环境要求
- Linux 服务器(CentOS 7+ / Ubuntu 18.04+ / Debian 10+)
- root 权限
- 一台有网络的机器用于下载安装包
一、什么是 Containerd?
1.1 定义
Containerd 是一个工业级的容器运行时,负责管理容器的完整生命周期:
┌─────────────────────────────────────────────────────────────┐
│ Containerd 功能 │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 镜像传输 │ │ 容器创建 │ │ 容器启动 │ │
│ │ (pull/push) │ │ (create) │ │ (start) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 容器停止 │ │ 容器删除 │ │ 快照管理 │ │
│ │ (stop) │ │ (delete) │ │ (snapshot) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
1.2 与 Docker 的关系
┌─────────────────────────────────────────────────────────────┐
│ Docker 架构 │
│ │
│ docker CLI → Docker Daemon → containerd → runc → 容器 │
│ │
│ Containerd 架构 │
│ │
│ ctr CLI → containerd → runc → 容器 │
│ │
│ 区别:Containerd 少了 Docker Daemon 层,更轻量 │
└─────────────────────────────────────────────────────────────┘
1.3 为什么选择 Containerd?
| 优势 | 说明 |
|---|---|
| 轻量级 | 只关注容器运行,不包含镜像构建等功能 |
| 行业标准 | CNCF 毕业项目,Kubernetes 默认运行时 |
| 资源占用低 | 比 Docker 少一层守护进程 |
| 安全性好 | 攻击面更小 |
| 离线友好 | 镜像可以导出导入,无需联网 |
二、离线安装准备
2.1 在有网络的机器上下载安装包
需要下载以下内容:
┌─────────────────────────────────────────────────────────────┐
│ 需要下载的文件 │
│ │
│ 1. containerd - 容器运行时主体 │
│ 2. runc - 底层运行时(创建容器) │
│ 3. CNI 插件 - 容器网络(可选,高级网络配置需要) │
│ 4. 配置文件 - containerd 配置 │
│ 5. 镜像包 - 后续需要运行的容器镜像 │
└─────────────────────────────────────────────────────────────┘
2.2 下载 Containerd
访问 GitHub Release 页面:
# 创建下载目录
mkdir -p ~/containerd-offline
cd ~/containerd-offline
# 下载 containerd(以 1.7.11 为例)
# 地址:https://github.com/containerd/containerd/releases
wget https://github.com/containerd/containerd/releases/download/v1.7.11/containerd-1.7.11-linux-amd64.tar.gz
# 文件说明:
# containerd-1.7.11-linux-amd64.tar.gz
# └── 包含 containerd 二进制文件和相关工具
2.3 下载 Runc
# 下载 runc(以 1.1.10 为例)
# 地址:https://github.com/opencontainers/runc/releases
wget https://github.com/opencontainers/runc/releases/download/v1.1.10/runc.amd64
# 文件说明:
# runc.amd64
# └── runc 二进制文件,需要重命名并赋予执行权限
2.4 下载 CNI 插件(可选)
# 下载 CNI 插件(以 1.4.0 为例)
# 地址:https://github.com/containernetworking/plugins/releases
wget https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz
# 文件说明:
# cni-plugins-linux-amd64-v1.4.0.tgz
# └── 包含各种网络插件(bridge、loopback、host-local 等)
2.5 下载 Hello World 镜像
在有网络的机器上拉取并导出镜像:
# 方法一:使用 Docker 导出(如果已安装 Docker)
docker pull busybox:latest
docker save -o busybox.tar busybox:latest
# 方法二:使用 ctr 导出(如果已有 containerd)
ctr images pull docker.io/library/busybox:latest
ctr images export busybox.tar docker.io/library/busybox:latest
# 方法三:使用 skopeo 工具
skopeo copy docker://busybox:latest docker-archive:busybox.tar:busybox:latest
2.6 查看下载的文件
ls -lh ~/containerd-offline/
# 预期输出:
# -rw-r--r-- 1 root root 50M containerd-1.7.11-linux-amd64.tar.gz
# -rw-r--r-- 1 root root 10M runc.amd64
# -rw-r--r-- 1 root root 40M cni-plugins-linux-amd64-v1.4.0.tgz
# -rw-r--r-- 1 root root 2.0M busybox.tar
2.7 打包所有文件
# 打包,便于传输
cd ~
tar -czvf containerd-offline-bundle.tar.gz containerd-offline/
# 传输到目标服务器
# scp containerd-offline-bundle.tar.gz root@目标服务器IP:/root/
三、离线安装详细步骤
3.1 解压安装包
在目标服务器上执行:
# 解压传输过来的包
cd /root
tar -xzvf containerd-offline-bundle.tar.gz
cd containerd-offline
# 查看文件
ls -lh
3.2 安装 Containerd
3.2.1 解压 containerd
# 解压到 /usr/local 目录
tar -xzvf containerd-1.7.11-linux-amd64.tar.gz -C /usr/local/
# 解压后的目录结构:
# /usr/local/
# └── bin/
# ├── containerd ← 主程序
# ├── containerd-shim ← shim 进程
# ├── containerd-shim-runc-v1
# ├── containerd-shim-runc-v2
# ├── ctr ← 命令行工具
# └── ...
3.2.2 验证安装
# 查看版本
/usr/local/bin/containerd --version
# 预期输出:
# containerd github.com/containerd/containerd v1.7.11
# 查看 ctr 版本
/usr/local/bin/ctr --version
# 预期输出:
# ctr github.com/containerd/containerd v1.7.11
3.3 安装 Runc
# 复制到系统 PATH 目录
install -m 755 runc.amd64 /usr/local/sbin/runc
# 验证安装
runc --version
# 预期输出:
# runc version 1.1.10
# spec: 1.0.2-dev
# go: go1.20.13
3.4 创建配置文件
3.4.1 生成默认配置
# 创建配置目录
mkdir -p /etc/containerd
# 生成默认配置
containerd config default > /etc/containerd/config.toml
3.4.2 配置文件详解
查看并理解配置文件:
cat /etc/containerd/config.toml
关键配置项说明:
# /etc/containerd/config.toml
# ========================================
# 根目录配置
# ========================================
root = "/var/lib/containerd" # 容器数据存储目录
state = "/run/containerd" # 运行时状态目录
# ========================================
# 插件配置
# ========================================
[plugins]
# ---- CRI 插件(Kubernetes 使用)----
[plugins."io.containerd.grpc.v1.cri"]
# sandbox 镜像(K8s 的 pause 容器)
sandbox_image = "registry.k8s.io/pause:3.8"
# 容器运行时类型
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
# ---- 镜像拉取配置 ----
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
# Docker Hub 镜像源
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://registry-1.docker.io"]
# ========================================
# 调试配置
# ========================================
[debug]
level = "info" # 日志级别:trace, debug, info, warn, error
# ========================================
# 远程 API 配置
# ========================================
[grpc]
address = "/run/containerd/containerd.sock" # Unix Socket 地址
tcp_address = "" # TCP 地址(空表示不监听)
3.4.3 重要:配置 Systemd Cgroup
推荐使用 systemd cgroup 驱动,这是 Kubernetes 的要求:
# 编辑配置文件
vim /etc/containerd/config.toml
找到并修改以下部分:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true # 添加这一行,设为 true
或者使用 sed 直接修改:
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
3.5 创建 Systemd 服务文件
3.5.1 创建服务文件
vim /etc/systemd/system/containerd.service
3.5.2 服务文件内容
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target
[Service]
# 前置执行命令
ExecStartPre=-/sbin/modprobe overlay
# 启动命令
ExecStart=/usr/local/bin/containerd
# 重启策略
Restart=always
RestartSec=5
# 限制
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
LimitMEMLOCK=infinity
# 安全相关
TasksMax=infinity
OOMScoreAdjust=-999
# Cgroup 设置
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
配置项详解:
┌─────────────────────────────────────────────────────────────┐
│ [Unit] 部分 - 单元描述 │
│ │
│ Description - 服务描述 │
│ Documentation - 文档地址 │
│ After - 在这些服务之后启动 │
│ │
├─────────────────────────────────────────────────────────────┤
│ [Service] 部分 - 服务配置 │
│ │
│ ExecStartPre - 启动前执行(加载 overlay 模块) │
│ ExecStart - 启动命令 │
│ Restart - 重启策略:always 总是重启 │
│ RestartSec - 重启间隔 5 秒 │
│ │
│ LimitNOFILE - 最大打开文件数 │
│ LimitNPROC - 最大进程数 │
│ Delegate - 允许 containerd 管理 cgroup │
│ KillMode - 杀进程的方式(只杀主进程) │
│ │
├─────────────────────────────────────────────────────────────┤
│ [Install] 部分 - 安装配置 │
│ │
│ WantedBy - 被哪个 target 需要 │
└─────────────────────────────────────────────────────────────┘
3.6 启动 Containerd 服务
3.6.1 重载 Systemd
# 重载 systemd 配置
systemctl daemon-reload
3.6.2 启动服务
# 启动 containerd
systemctl start containerd
# 检查状态
systemctl status containerd
预期输出:
● containerd.service - containerd container runtime
Loaded: loaded (/etc/systemd/system/containerd.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2024-01-01 10:00:00 CST; 5s ago
Main PID: 12345 (containerd)
Tasks: 8
Memory: 15.0M
CGroup: /system.slice/containerd.service
└─12345 /usr/local/bin/containerd
3.6.3 设置开机自启
systemctl enable containerd
3.6.4 查看日志
# 查看实时日志
journalctl -u containerd -f
# 查看最近 100 行日志
journalctl -u containerd -n 100
3.7 安装 CNI 插件(可选但推荐)
# 创建 CNI 目录
mkdir -p /opt/cni/bin
# 解压 CNI 插件
tar -xzvf cni-plugins-linux-amd64-v1.4.0.tgz -C /opt/cni/bin/
# 查看安装的插件
ls -lh /opt/cni/bin/
# 预期输出:
# -rwxr-xr-x bridge
# -rwxr-xr-x dhcp
# -rwxr-xr-x firewall
# -rwxr-xr-x host-device
# -rwxr-xr-x host-local
# -rwxr-xr-x ipvlan
# -rwxr-xr-x loopback
# -rwxr-xr-x macvlan
# -rwxr-xr-x portmap
# -rwxr-xr-x ptp
# -rwxr-xr-x sbr
# -rwxr-xr-x static
# -rwxr-xr-x tap
# -rwxr-xr-x tuning
# -rwxr-xr-x vlan
# -rwxr-xr-x vrf
3.8 验证安装完成
# 1. 检查服务状态
systemctl status containerd
# 2. 检查 Socket 文件
ls -lh /run/containerd/containerd.sock
# 3. 检查 ctr 命令
ctr version
# 4. 检查 runc 命令
runc --version
四、启动 Hello World 容器
4.1 导入镜像
将下载的镜像导入到 containerd:
# 导入镜像
ctr -n k8s.io images import busybox.tar
# 参数说明:
# -n k8s.io 指定命名空间为 k8s.io(Kubernetes 默认命名空间)
# 如果不指定,默认是 default 命名空间
关于命名空间:
┌─────────────────────────────────────────────────────────────┐
│ Containerd 命名空间 │
│ │
│ 作用:隔离不同用户的容器和镜像 │
│ │
│ 默认命名空间: │
│ ├── default - ctr 默认使用的命名空间 │
│ ├── k8s.io - Kubernetes 使用的命名空间 │
│ └── moby - Docker 使用的命名空间 │
│ │
│ 不同命名空间的容器互不可见 │
└─────────────────────────────────────────────────────────────┘
4.2 查看镜像列表
# 查看镜像
ctr -n k8s.io images list
# 预期输出:
# REF TYPE SIZE DIGEST
# docker.io/library/busybox:latest application/vnd.docker.distribution.manifest.v2+json 2.0 MiB sha256:xxx
# 简写形式
ctr -n k8s.io images ls
4.3 运行容器(Hello World)
4.3.1 方法一:使用 ctr run(不推荐生产)
# 运行容器
ctr -n k8s.io run --rm docker.io/library/busybox:latest hello-world echo "Hello World"
# 参数说明:
# -n k8s.io 命名空间
# run 运行容器
# --rm 容器退出后自动删除
# docker.io/... 镜像名称
# hello-world 容器名称(必须唯一)
# echo "Hello..." 容器内执行的命令
# 预期输出:
# Hello World
4.3.2 方法二:创建后启动(推荐学习)
步骤分解:
# 1. 创建容器(只创建,不启动)
ctr -n k8s.io containers create docker.io/library/busybox:latest my-container
# 2. 查看容器列表(状态为 CREATED)
ctr -n k8s.io containers list
# 预期输出:
# CONTAINER IMAGE RUNTIME
# my-container docker.io/library/busybox:latest io.containerd.runc.v2
# 3. 启动容器并执行任务
ctr -n k8s.io task start --attach my-container
# 注意:这会失败,因为容器没有前台进程
# busybox 默认没有启动命令,需要指定
正确的做法:
# 删除之前创建的容器
ctr -n k8s.io containers delete my-container
# 使用 run 命令并指定交互式
ctr -n k8s.io run -t --rm docker.io/library/busybox:latest my-hello sh -c "echo 'Hello World'; sleep 3"
# 参数:
# -t 分配终端
# --rm 退出后删除
4.4 容器生命周期管理
4.4.1 生命周期图
┌─────────────────────────────────────────────────────────────┐
│ 容器生命周期 │
│ │
│ ┌─────────┐ │
│ │ 创建 │ ctr containers create │
│ │ CREATED │ │
│ └────┬────┘ │
│ ↓ │
│ ┌─────────┐ │
│ │ 启动 │ ctr task start │
│ │ RUNNING │ │
│ └────┬────┘ │
│ │ │
│ ├─── 暂停 ctr task pause ────┐ │
│ │ ↓ │
│ │ ┌─────────┐ │
│ │ │ 暂停 │ │
│ │ │ PAUSED │ │
│ │ └─────────┘ │
│ │ │ │
│ │ ctr task resume ──┘ │
│ │ │
│ ↓ │
│ ┌─────────┐ │
│ │ 停止 │ ctr task kill / 任务进程退出 │
│ │ STOPPED │ │
│ └────┬────┘ │
│ ↓ │
│ ┌─────────┐ │
│ │ 删除 │ ctr containers delete │
│ │ DELETED │ │
│ └─────────┘ │
└─────────────────────────────────────────────────────────────┘
4.4.2 完整操作示例
# 1. 创建容器
ctr -n k8s.io containers create docker.io/library/busybox:latest demo-container
# 2. 查看容器列表
ctr -n k8s.io containers ls
# 3. 查看任务列表(此时为空)
ctr -n k8s.io tasks ls
# 4. 在容器内启动一个任务(进程)
ctr -n k8s.io task start --attach demo-container
# 注意:这会卡住,因为没有指定命令
# 按 Ctrl+C 退出
# 5. 正确的方式:创建时指定命令
# 先删除旧容器
ctr -n k8s.io containers delete demo-container
# 创建并运行(后台模式)
ctr -n k8s.io run -d docker.io/library/busybox:latest demo-container sleep infinity
# 6. 查看运行中的任务
ctr -n k8s.io tasks ls
# 预期输出:
# TASK PID STATUS
# demo-container 12345 RUNNING
# 7. 进入容器执行命令
ctr -n k8s.io task exec --exec-id demo-exec demo-container echo "Hello World"
# 参数:
# --exec-id demo-exec 执行任务的 ID(必须唯一)
# demo-container 容器名称
# echo "Hello World" 要执行的命令
# 预期输出:
# Hello World
# 8. 进入容器交互式 shell
ctr -n k8s.io task exec --exec-id demo-shell -t demo-container sh
# 现在你在容器内了
# 执行命令:
ls
hostname
exit
# 9. 停止容器(发送 SIGTERM 信号)
ctr -n k8s.io task kill demo-container
# 10. 查看任务状态(已停止)
ctr -n k8s.io tasks ls
# 11. 删除任务
ctr -n k8s.io task delete demo-container
# 12. 删除容器
ctr -n k8s.io containers delete demo-container
五、ctr 命令详解
5.1 命令结构
ctr [全局选项] <命令> [命令选项] [参数...]
# 结构说明:
# ctr - 主命令
# -n k8s.io - 命名空间(全局选项)
# images - 子命令(管理镜像)
# list - 二级子命令(列出镜像)
5.2 镜像管理
# ─────────────────────────────────────────
# 列出镜像
# ─────────────────────────────────────────
ctr -n k8s.io images list
ctr -n k8s.io images ls # 简写
# ─────────────────────────────────────────
# 拉取镜像(需要网络)
# ─────────────────────────────────────────
ctr -n k8s.io images pull docker.io/library/nginx:latest
# ─────────────────────────────────────────
# 导入镜像
# ─────────────────────────────────────────
ctr -n k8s.io images import busybox.tar
# ─────────────────────────────────────────
# 导出镜像
# ─────────────────────────────────────────
ctr -n k8s.io images export nginx.tar docker.io/library/nginx:latest
# ─────────────────────────────────────────
# 删除镜像
# ─────────────────────────────────────────
ctr -n k8s.io images rm docker.io/library/nginx:latest
# ─────────────────────────────────────────
# 查看镜像详情
# ─────────────────────────────────────────
ctr -n k8s.io images inspect docker.io/library/nginx:latest
5.3 容器管理
# ─────────────────────────────────────────
# 创建容器
# ─────────────────────────────────────────
ctr -n k8s.io containers create <镜像> <容器名>
# ─────────────────────────────────────────
# 列出容器
# ─────────────────────────────────────────
ctr -n k8s.io containers list
ctr -n k8s.io containers ls
# ─────────────────────────────────────────
# 查看容器详情
# ─────────────────────────────────────────
ctr -n k8s.io containers inspect <容器名>
# ─────────────────────────────────────────
# 删除容器
# ─────────────────────────────────────────
ctr -n k8s.io containers delete <容器名>
ctr -n k8s.io containers rm <容器名>
5.4 任务管理
# ─────────────────────────────────────────
# 启动任务
# ─────────────────────────────────────────
ctr -n k8s.io task start <容器名> # 前台运行
ctr -n k8s.io task start -d <容器名> # 后台运行
# ─────────────────────────────────────────
# 查看任务
# ─────────────────────────────────────────
ctr -n k8s.io tasks list
ctr -n k8s.io tasks ls
# ─────────────────────────────────────────
# 在容器内执行命令
# ─────────────────────────────────────────
ctr -n k8s.io task exec --exec-id <任务ID> <容器名> <命令>
ctr -n k8s.io task exec --exec-id shell1 -t <容器名> sh # 交互式
# ─────────────────────────────────────────
# 暂停/恢复任务
# ─────────────────────────────────────────
ctr -n k8s.io task pause <容器名>
ctr -n k8s.io task resume <容器名>
# ─────────────────────────────────────────
# 停止任务
# ─────────────────────────────────────────
ctr -n k8s.io task kill <容器名>
ctr -n k8s.io task kill --signal SIGKILL <容器名> # 强制杀死
# ─────────────────────────────────────────
# 删除任务
# ─────────────────────────────────────────
ctr -n k8s.io task delete <容器名>
5.5 命名空间管理
# ─────────────────────────────────────────
# 列出命名空间
# ─────────────────────────────────────────
ctr namespaces list
ctr ns ls # 简写
# 预期输出:
# NAME LABELS
# default
# k8s.io
# ─────────────────────────────────────────
# 创建命名空间
# ─────────────────────────────────────────
ctr namespaces create my-namespace
# ─────────────────────────────────────────
# 删除命名空间
# ─────────────────────────────────────────
ctr namespaces delete my-namespace
5.6 快照管理
# ─────────────────────────────────────────
# 列出快照
# ─────────────────────────────────────────
ctr -n k8s.io snapshots list
# ─────────────────────────────────────────
# 查看快照信息
# ─────────────────────────────────────────
ctr -n k8s.io snapshots info <快照名>
# ─────────────────────────────────────────
# 删除快照
# ─────────────────────────────────────────
ctr -n k8s.io snapshots delete <快照名>
六、常见问题排查
6.1 容器无法启动
问题: ctr task start 报错 no such file or directory
原因: 容器没有前台进程或命令不存在
解决:
# 使用正确的命令启动
ctr -n k8s.io run --rm docker.io/library/busybox:latest test sh -c "echo hello"
# 或后台运行一个持续进程
ctr -n k8s.io run -d docker.io/library/busybox:latest test sleep infinity
6.2 无法删除容器
问题: cannot delete container: task is running
原因: 容器内有任务在运行
解决:
# 1. 先停止任务
ctr -n k8s.io task kill <容器名>
# 2. 删除任务
ctr -n k8s.io task delete <容器名>
# 3. 删除容器
ctr -n k8s.io containers delete <容器名>
6.3 权限不足
问题: permission denied
原因: 需要 root 权限
解决:
# 使用 root 用户或 sudo
sudo ctr -n k8s.io images list
# 或将当前用户加入 containerd 组
sudo usermod -aG containerd $USER
# 重新登录生效
6.4 Socket 文件不存在
问题: connect: no such file or directory
原因: containerd 服务未运行
解决:
# 检查服务状态
systemctl status containerd
# 启动服务
systemctl start containerd
# 检查 Socket 文件
ls -l /run/containerd/containerd.sock
6.5 镜像导入失败
问题: unpacking failed
原因: 镜像格式不兼容或存储空间不足
解决:
# 检查磁盘空间
df -h /var/lib/containerd
# 清理无用数据
ctr -n k8s.io content prune
# 使用 --no-unpack 选项导入后再解包
ctr -n k8s.io images import --no-unpack busybox.tar
6.6 网络不通
问题: 容器内无法访问网络
原因: CNI 未配置或配置错误
解决:
# 检查 CNI 配置
ls -l /etc/cni/net.d/
# 创建默认网络配置
mkdir -p /etc/cni/net.d
cat > /etc/cni/net.d/10-bridge.conf << EOF
{
"cniVersion": "1.0.0",
"name": "bridge",
"type": "bridge",
"bridge": "cni0",
"isGateway": true,
"ipMasq": true,
"ipam": {
"type": "host-local",
"subnet": "10.88.0.0/16",
"routes": [{"dst": "0.0.0.0/0"}]
}
}
EOF
七、进阶:运行 Nginx 容器
7.1 准备 Nginx 镜像
在有网络的机器上:
# 拉取 Nginx 镜像
docker pull nginx:alpine
# 导出镜像
docker save -o nginx-alpine.tar nginx:alpine
# 传输到目标服务器
scp nginx-alpine.tar root@目标服务器:/root/
7.2 导入并运行
# 导入镜像
ctr -n k8s.io images import nginx-alpine.tar
# 运行 Nginx 容器
ctr -n k8s.io run -d \
--net-host \
docker.io/library/nginx:alpine \
nginx-server
# 参数说明:
# -d 后台运行
# --net-host 使用主机网络(容器直接使用宿主机端口)
# 验证
curl http://localhost
# 预期输出:Welcome to nginx!
7.3 管理容器
# 查看容器状态
ctr -n k8s.io tasks ls
# 进入容器
ctr -n k8s.io task exec --exec-id nginx-shell -t nginx-server sh
# 在容器内
ls /etc/nginx/
cat /etc/nginx/nginx.conf
exit
# 停止容器
ctr -n k8s.io task kill nginx-server
# 删除容器
ctr -n k8s.io task delete nginx-server
ctr -n k8s.io containers delete nginx-server
八、总结
8.1 安装流程回顾
┌─────────────────────────────────────────────────────────────┐
│ 离线安装 Containerd 流程 │
│ │
│ 1. 下载安装包 │
│ ├── containerd-xxx.tar.gz │
│ ├── runc.amd64 │
│ ├── cni-plugins-xxx.tgz │
│ └── 镜像.tar │
│ │
│ 2. 安装 containerd │
│ tar -xzvf containerd-xxx.tar.gz -C /usr/local/ │
│ │
│ 3. 安装 runc │
│ install -m 755 runc.amd64 /usr/local/sbin/runc │
│ │
│ 4. 创建配置 │
│ containerd config default > /etc/containerd/config.toml │
│ (修改 SystemdCgroup = true) │
│ │
│ 5. 创建服务文件 │
│ vim /etc/systemd/system/containerd.service │
│ │
│ 6. 启动服务 │
│ systemctl daemon-reload │
│ systemctl start containerd │
│ systemctl enable containerd │
│ │
│ 7. 验证安装 │
│ ctr version │
│ runc --version │
└─────────────────────────────────────────────────────────────┘
8.2 核心命令速查
| 操作 | 命令 |
|---|---|
| 查看版本 | ctr version |
| 列出镜像 | ctr -n k8s.io images ls |
| 导入镜像 | ctr -n k8s.io images import xxx.tar |
| 列出容器 | ctr -n k8s.io containers ls |
| 运行容器 | ctr -n k8s.io run -d <镜像> <名称> <命令> |
| 查看任务 | ctr -n k8s.io tasks ls |
| 执行命令 | ctr -n k8s.io task exec --exec-id <id> <容器> <命令> |
| 停止容器 | ctr -n k8s.io task kill <容器> |
8.3 与 Docker 命令对比
| Docker | Containerd (ctr) | 说明 |
|---|---|---|
docker run |
ctr run |
运行容器 |
docker ps |
ctr containers ls |
列出容器 |
docker images |
ctr images ls |
列出镜像 |
docker pull |
ctr images pull |
拉取镜像 |
docker exec |
ctr task exec |
进入容器 |
docker stop |
ctr task kill |
停止容器 |
docker rm |
ctr containers rm |
删除容器 |
docker rmi |
ctr images rm |
删除镜像 |
九、附录
9.1 目录结构
/var/lib/containerd/ # 数据目录
├── io.containerd.content.v1.content/
│ └── blobs/ # 镜像层
├── io.containerd.metadata.v1.bolt/
│ └── meta.db # 元数据
├── io.containerd.runtime.v2.task/
│ └── k8s.io/ # 运行中的容器
│ └── <container-id>/
│ ├── config.json # 容器配置
│ ├── log.json # 日志
│ └── rootfs/ # 根文件系统
└── io.containerd.snapshotter.v1.overlayfs/
└── snapshots/ # 快照
/run/containerd/ # 运行时目录
├── containerd.sock # Socket 文件
└── io.containerd.runtime.v2.task/
└── k8s.io/
└── <container-id>/
└── init.pid # 进程 ID
9.2 下载地址汇总
| 组件 | 下载地址 |
|---|---|
| Containerd | https://github.com/containerd/containerd/releases |
| Runc | https://github.com/opencontainers/runc/releases |
| CNI Plugins | https://github.com/containernetworking/plugins/releases |
| Nerctl(可选,更好的 CLI) | https://github.com/containerd/nerdctl/releases |
9.3 推荐阅读
- Containerd 官方文档:https://containerd.io/docs/
- Kubernetes 容器运行时:https://kubernetes.io/docs/setup/production-environment/container-runtimes/
- OCI 运行时规范:https://github.com/opencontainers/runtime-spec
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)