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
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐