name: cnb-docker-transfer

description: 利用CNB云端终端免密登录特性,先在CNB上下载Docker镜像,保存为tar.gz文件,然后通过SCP传输到本地,最后用docker load加载。适用于直接拉取失败或网络超时的场景。

CNB Docker 镜像传输方案

目标

通过”CNB下载 → 打包传输 → 本地加载”的方式,绕过本地网络限制获取Docker镜像。

获取CNB连接信息

方式 A:连接cnb终端,从环境变量获取(推荐)

env | grep -i cnb_vscode_remote_ssh_schema

输出示例:vscode://vscode-remote/ssh-remote+cnb-user@cnb.space/workspace/

快速提取:grep -oP '(?<=ssh-remote\+)[^@]+' <<< "$CNB_VSCODE_REMOTE_SSH_SCHEMA"

方式 B:如果cnb终端没有,让用户手动输入连接地址

如果没有CNB终端或环境变量,用户可以手动提供: 例如完整SSH命令ssh cnb-ebj-1jmkvgl01-001.1852baf2-119e-4636-a5fa-bf1b922c1b55-2i3@cnb.space

完整工作流程

步骤 1:从目标机器连接CNB终端

# 连接CNB(首次连接需输入yes)
ssh <USERNAME>@cnb.space

步骤 2:在CNB上下载目标镜像

# 拉取目标镜像
docker pull <镜像名>:<标签>

# 验证下载成功
docker images | grep <镜像名>

步骤 3:将镜像保存为tar.gz文件

# 压缩保存(推荐)
docker save <镜像名>:<标签> | gzip > <镜像名>_<标签>.tar.gz

# 验证文件创建成功
ls -lh *.tar.gz

exit
# 退出CNB终端

步骤 4:将镜像文件传输到目标机器

目标机器终端执行:

# 从CNB下载文件到本地
scp <USERNAME>@cnb.space:/workspace/<文件名>.tar.gz ./

# 如果文件不在workspace,先移动到用户目录(在CNB终端执行)
mv <文件名>.tar.gz ~/
then: scp <USERNAME>@cnb.space:~/<文件名>.tar.gz ./

步骤 5:在目标机器加载镜像

# 加载压缩的tar.gz文件
gunzip -c <文件名>.tar.gz | docker load

# 或直接加载
docker load < <文件名>.tar.gz

# 验证加载成功
docker images | grep <镜像名>

步骤 6:验证测试

docker run --rm <镜像名>:<标签> <测试命令>
# 例如:docker run --rm busybox:latest echo "OK"

步骤 7:清理临时文件

# 清理CNB文件(在CNB终端)
rm -f *.tar.gz

# 清理目标机器文件(可选)
rm -f *.tar.gz

快速参考

步骤 位置 命令 说明
1. 获取用户名 任意终端 env \| grep -i cnb_vscode_remote_ssh_schema 🚀 快速获取
手动解析用户名 本地 echo "cnb-user@cnb.space" \| cut -d@ -f1 从地址提取
2. 连接CNB 本地终端 ssh <USERNAME>@cnb.space 首次需输入yes
3. 下载镜像 CNB终端 docker pull <镜像名> 在CNB上下载
4. 打包镜像 CNB终端 docker save <镜像名> \| gzip > <文件>.tar.gz 压缩保存
5. 传输文件 本地终端 scp <USERNAME>@cnb.space:<文件> ./ SCP下载
6. 加载镜像 本地终端 gunzip -c <文件>.tar.gz \| docker load 本地加载
7. 验证测试 本地终端 docker run --rm <镜像名> echo "OK" 功能验证

实际应用示例

示例1:拯救busybox镜像拉取

# 手动提供连接地址的情况
USERNAME=$(echo "cnb-ebj-1jmkvgl01-001.1852baf2-119e-4636-a5fa-bf1b922c1b55-2i3@cnb.space" | cut -d@ -f1)

echo "使用用户名: $USERNAME"

# 连接CNB并下载busybox
ssh $USERNAME@cnb.space
docker pull busybox:latest
docker save busybox:latest | gzip > busybox_latest.tar.gz
exit

# 传输到本地
scp $USERNAME@cnb.space:~/busybox_latest.tar.gz ./

# 本地加载
gunzip -c busybox_latest.tar.gz | docker load

# 验证
docker run --rm busybox:latest echo "busybox传输成功!"

示例2:从SSH命令解析用户名

# 如果用户直接提供SSH命令
SSH_CMD="ssh cnb-ebj-1jmkvgl01-001.1852baf2-119e-4636-a5fa-bf1b922c1b55-2i3@cnb.space"
USERNAME=$(echo "$SSH_CMD" | sed 's/^ssh //' | awk '{print $1}')

# 或者更简单的方法
USERNAME=$(echo "$SSH_CMD" | grep -o '^ssh [^@]*' | sed 's/^ssh //')

# 或者直接用cut(如果格式固定)
USERNAME=$(echo "$SSH_CMD" | awk '{print $2}' | cut -d@ -f1)

echo "解析到的用户名: $USERNAME"

示例3:批量传输脚本

#!/bin/bash
# 准备多个镜像用于离线环境
USERNAME="cnb-user"  # 手动设置或从其他方式获取
IMAGES=("nginx:alpine" "redis:alpine" "openjdk:8-jdk-slim")

for image in "${IMAGES[@]}"; do
    name=$(echo $image | sed 's/:/-/g')
    
    # 在CNB操作    ssh $USERNAME@cnb.space "
        docker pull $image
        docker save $image | gzip > ${name}.tar.gz
    "
    
    # 下载到本地    scp $USERNAME@cnb.space:~/${name}.tar.gz ./
    
    # 本地加载    gunzip -c ${name}.tar.gz | docker load
    
    echo "✅ $image 准备完成"
done

用户名解析技巧

常见输入格式及处理方法

  1. 完整SSH命令ssh cnb-user@cnb.space

    USERNAME=$(echo "$INPUT" | awk '{print $2}' | cut -d@ -f1)
    
    1. 仅地址cnb-user@cnb.space bash USERNAME=$(echo "$INPUT" | cut -d@ -f1)
  2. 带端口cnb-user@cnb.space:22

    USERNAME=$(echo "$INPUT" | cut -d@ -f1)
    
    1. 复杂SSH命令ssh -p 22 cnb-user@cnb.space bash USERNAME=$(echo "$INPUT" | grep -o '[^@]*@cnb\.space' | cut -d@ -f1)

通用解析函数

parse_cnb_username() {
    local input="$1"
    
    # 移除ssh前缀
    input=$(echo "$input" | sed 's/^ssh //')
    
    # 提取@cnb.space前的部分
    if echo "$input" | grep -q '@cnb\.space'; then
        echo "$input" | grep -o '^[^@]*'
    else
        echo "$input" | cut -d@ -f1
    fi
}

# 使用示例
USERNAME=$(parse_cnb_username "ssh cnb-user@cnb.space")
echo $USERNAME  # 输出: cnb-user

USERNAME=$(parse_cnb_username "cnb-user@cnb.space")
echo $USERNAME  # 输出: cnb-user

故障排除

❌ SCP连接失败

  • 检查文件路径是否正确
  • 在CNB上使用绝对路径:~/filename.tar.gz
  • 尝试移动文件到用户主目录再传输

❌ 镜像加载失败

  • 检查文件完整性:gunzip -t filename.tar.gz
  • 重新传输文件
  • 检查磁盘空间:df -h

❌ CNB存储空间不足

  • 清理不需要的文件:docker system prune -a
  • 使用更小的镜像标签
  • 分批处理,及时清理临时文件

总结

CNB Docker镜像传输方案是代理方案的完美补充

  • 代理方案:适合大多数常规镜像的快速获取
  • 传输方案:适合疑难镜像、大镜像和批量部署场景

结合使用,几乎可以应对任何网络环境下的Docker镜像获取需求!