惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
S
Secure Thoughts
月光博客
月光博客
美团技术团队
雷峰网
雷峰网
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
News and Events Feed by Topic
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Forbes - Security
Forbes - Security
W
WeLiveSecurity
P
Proofpoint News Feed
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿
G
GRAHAM CLULEY
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AI
AI
Last Week in AI
Last Week in AI
Google Online Security Blog
Google Online Security Blog
Schneier on Security
Schneier on Security
云风的 BLOG
云风的 BLOG
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Recent Announcements
Recent Announcements
Webroot Blog
Webroot Blog
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
N
News and Events Feed by Topic
罗磊的独立博客
The Register - Security
The Register - Security
Blog — PlanetScale
Blog — PlanetScale
T
Threat Research - Cisco Blogs
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
T
The Exploit Database - CXSecurity.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
B
Blog
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Engineering at Meta
Engineering at Meta
Latest news
Latest news
IT之家
IT之家
D
DataBreaches.Net
博客园 - 司徒正美
N
Netflix TechBlog - Medium
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

博客园 - 仙守

用audit审计去记录谁用了docker docker容器大小使用限制 docker容器的磁盘使用进行限额 sentry私有化部署: 在8c16g上降低资源使用 私有化部署sentry: 获取dsn 私有化部署sentry:卷备份及恢复 私有化部署sentry:镜像构建 docker拉取代理脚本 vscode密钥从windows连接远程linux 基于docker构建es集群 在es中进行update+upsert milvus遍历查询全部数据 简单剖析qwen-agent回答是怎么获取tool的 一个中转代码,底层调用openai,上层模拟openai 一个小工具识别哪个docker占用gpu NLP之预训练语言模型BERT NLP之预训练语言模型GPT NLP之引言 [推荐系统]粗排之FSCD
docker 保存所有镜像
仙守 · 2026-02-06 · via 博客园 - 仙守
  1. 最简单的方法:使用 docker save 和 xargs
# 方法一:直接打包所有镜像
docker save $(docker images -q) -o all_images.tar

# 方法二:包含标签信息
docker save $(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>") -o all_images.tar

# 方法三:包含所有,包括没有标签的镜像
docker images --format "{{.Repository}}:{{.Tag}}" | xargs docker save -o all_images.tar
  1. 更安全的脚本:处理镜像名称中的特殊字符
#!/bin/bash
# save-all-images.sh

# 设置输出文件名
OUTPUT_FILE="all_docker_images_$(date +%Y%m%d_%H%M%S).tar"

echo "开始收集所有镜像..."

# 获取所有镜像列表,处理特殊字符
IMAGE_LIST=()
while IFS= read -r line; do
    # 跳过空行和表头
    if [[ -n "$line" && ! "$line" =~ ^REPOSITORY ]]; then
        # 提取镜像名和标签
        repo_tag=$(echo "$line" | awk '{print $1":"$2}')
        # 跳过 <none>:<none>
        if [[ "$repo_tag" != "<none>:<none>" ]]; then
            IMAGE_LIST+=("$repo_tag")
        fi
    fi
done < <(docker images)

# 如果镜像列表为空
if [ ${#IMAGE_LIST[@]} -eq 0 ]; then
    echo "没有找到任何镜像"
    exit 1
fi

echo "找到 ${#IMAGE_LIST[@]} 个镜像:"
printf '%s\n' "${IMAGE_LIST[@]}"

echo "正在打包到 $OUTPUT_FILE ..."

# 方法A:逐个打包再合并(适用于大量镜像)
if false; then
    # 创建临时目录
    TEMP_DIR=$(mktemp -d)
    echo "使用临时目录: $TEMP_DIR"
    
    # 逐个保存镜像
    for image in "${IMAGE_LIST[@]}"; do
        echo "保存: $image"
        # 替换特殊字符作为文件名
        safe_name=$(echo "$image" | tr '/:' '_-')
        docker save "$image" -o "$TEMP_DIR/${safe_name}.tar"
    done
    
    # 合并所有tar文件
    tar -cf "$OUTPUT_FILE" -C "$TEMP_DIR" .
    
    # 清理临时文件
    rm -rf "$TEMP_DIR"
else
    # 方法B:一次性保存(推荐,但可能命令行过长)
    docker save "${IMAGE_LIST[@]}" -o "$OUTPUT_FILE"
fi

# 验证文件
echo "打包完成!"
echo "文件大小: $(du -h "$OUTPUT_FILE" | cut -f1)"
echo "文件信息:"
file "$OUTPUT_FILE"
  1. 高级脚本:包含分层保存和验证
#!/bin/bash
# docker-save-all.sh

set -e

# 配置
BACKUP_DIR="${BACKUP_DIR:-/tmp/docker-backup}"
OUTPUT_FILE="${BACKUP_DIR}/docker-images-$(date +%Y%m%d-%H%M%S).tar"
LOG_FILE="${BACKUP_DIR}/backup-$(date +%Y%m%d-%H%M%S).log"

# 创建备份目录
mkdir -p "$BACKUP_DIR"

echo "========================================" | tee -a "$LOG_FILE"
echo "Docker 镜像备份开始: $(date)" | tee -a "$LOG_FILE"
echo "========================================" | tee -a "$LOG_FILE"

# 1. 获取镜像列表
echo "1. 获取镜像列表..." | tee -a "$LOG_FILE"
IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>")
IMAGE_COUNT=$(echo "$IMAGES" | wc -l)

echo "找到 $IMAGE_COUNT 个镜像" | tee -a "$LOG_FILE"
echo "$IMAGES" | tee -a "$LOG_FILE"

if [ "$IMAGE_COUNT" -eq 0 ]; then
    echo "没有镜像需要备份" | tee -a "$LOG_FILE"
    exit 0
fi

# 2. 保存镜像列表到文件(用于恢复时参考)
echo "$IMAGES" > "${BACKUP_DIR}/image-list.txt"

# 3. 获取镜像详细信息
echo "2. 获取镜像详细信息..." | tee -a "$LOG_FILE"
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}" > "${BACKUP_DIR}/image-details.txt"

# 4. 打包所有镜像
echo "3. 开始打包镜像..." | tee -a "$LOG_FILE"
echo "输出文件: $OUTPUT_FILE" | tee -a "$LOG_FILE"

start_time=$(date +%s)

# 使用 tee 命令同时输出到文件和屏幕
{
    echo "开始保存镜像..."
    docker save $(echo "$IMAGES") -o "$OUTPUT_FILE"
} 2>&1 | tee -a "$LOG_FILE"

end_time=$(date +%s)
duration=$((end_time - start_time))

# 5. 验证打包结果
echo "4. 验证打包文件..." | tee -a "$LOG_FILE"
if [ -f "$OUTPUT_FILE" ]; then
    file_size=$(du -h "$OUTPUT_FILE" | cut -f1)
    echo "文件大小: $file_size" | tee -a "$LOG_FILE"
    
    # 检查tar文件是否有效
    if tar -tf "$OUTPUT_FILE" &>/dev/null; then
        echo "✓ Tar 文件格式正确" | tee -a "$LOG_FILE"
        tar_count=$(tar -tf "$OUTPUT_FILE" | grep "manifest.json" | wc -l)
        echo "包含 $tar_count 个镜像" | tee -a "$LOG_FILE"
    else
        echo "✗ Tar 文件损坏" | tee -a "$LOG_FILE"
        exit 1
    fi
else
    echo "✗ 输出文件不存在" | tee -a "$LOG_FILE"
    exit 1
fi

echo "========================================" | tee -a "$LOG_FILE"
echo "备份完成!" | tee -a "$LOG_FILE"
echo "总耗时: ${duration}秒" | tee -a "$LOG_FILE"
echo "输出文件: $OUTPUT_FILE" | tee -a "$LOG_FILE"
echo "日志文件: $LOG_FILE" | tee -a "$LOG_FILE"
echo "镜像列表: ${BACKUP_DIR}/image-list.txt" | tee -a "$LOG_FILE"
echo "镜像详情: ${BACKUP_DIR}/image-details.txt" | tee -a "$LOG_FILE"
echo "========================================" | tee -a "$LOG_FILE"
  1. 批量处理大量镜像的优化版本
#!/bin/bash
# save-docker-images-batch.sh

# 配置
MAX_ARGS=20  # 每次传递的最大镜像数,避免参数过长
OUTPUT_BASE="docker-images-backup"

# 创建备份目录
BACKUP_DIR="${OUTPUT_BASE}-$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"

echo "备份目录: $BACKUP_DIR"

# 获取所有镜像
mapfile -t IMAGES < <(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>")
TOTAL=${#IMAGES[@]}

echo "总共 $TOTAL 个镜像需要备份"

# 分批处理
BATCH=0
for ((i=0; i<TOTAL; i+=MAX_ARGS)); do
    BATCH=$((BATCH+1))
    END_INDEX=$((i+MAX_ARGS))
    if [ $END_INDEX -gt $TOTAL ]; then
        END_INDEX=$TOTAL
    fi
    
    # 获取当前批次的镜像
    BATCH_IMAGES=("${IMAGES[@]:i:MAX_ARGS}")
    
    echo "处理第 $BATCH 批: ${#BATCH_IMAGES[@]} 个镜像"
    echo "镜像列表: ${BATCH_IMAGES[*]}"
    
    # 保存当前批次
    OUTPUT_FILE="$BACKUP_DIR/batch-${BATCH}.tar"
    docker save "${BATCH_IMAGES[@]}" -o "$OUTPUT_FILE"
    
    # 验证
    if [ -s "$OUTPUT_FILE" ]; then
        size=$(du -h "$OUTPUT_FILE" | cut -f1)
        echo "✓ 批次 $BATCH 完成: $size"
    else
        echo "✗ 批次 $BATCH 失败"
    fi
done

# 创建合并脚本
cat > "$BACKUP_DIR/load-all.sh" << 'EOF'
#!/bin/bash
echo "加载所有Docker镜像..."
for tar_file in batch-*.tar; do
    echo "加载: $tar_file"
    docker load -i "$tar_file"
done
echo "完成!"
EOF

chmod +x "$BACKUP_DIR/load-all.sh"

# 创建恢复说明
cat > "$BACKUP_DIR/README.txt" << EOF
Docker 镜像备份
备份时间: $(date)
镜像总数: $TOTAL
批次数量: $BATCH

恢复方法:
1. 将所有 batch-*.tar 文件复制到目标机器
2. 运行: ./load-all.sh
3. 或者逐个加载: docker load -i batch-*.tar

镜像列表:
$(printf '%s\n' "${IMAGES[@]}")
EOF

echo "备份完成! 目录: $BACKUP_DIR"
echo "恢复时请运行: cd '$BACKUP_DIR' && ./load-all.sh"
  1. 压缩版本(节省空间)
# 直接打包并压缩
docker save $(docker images -q) | gzip > all_images.tar.gz

# 或者使用并行压缩(更快)
docker save $(docker images -q) | pigz -9 > all_images.tar.gz

# 完整脚本
#!/bin/bash
OUTPUT="docker-images-$(date +%Y%m%d).tar.gz"
echo "打包并压缩所有镜像到 $OUTPUT ..."
docker save $(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>") | gzip -c > "$OUTPUT"
echo "完成! 文件大小: $(du -h $OUTPUT | cut -f1)"
  1. 恢复所有镜像
# 从tar文件恢复所有镜像
docker load -i all_images.tar

# 如果使用gzip压缩
gunzip -c all_images.tar.gz | docker load

# 或者
docker load < all_images.tar.gz

# 从分批次备份恢复
for tar_file in batch-*.tar; do
    echo "Loading $tar_file..."
    docker load -i "$tar_file"
done
  1. 一键备份和恢复脚本
#!/bin/bash
# docker-backup-manager.sh

ACTION="$1"
BACKUP_FILE="${2:-docker-images-backup.tar}"

case "$ACTION" in
    "save"|"backup"|"export")
        echo "备份所有Docker镜像到 $BACKUP_FILE ..."
        IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>")
        if [ -z "$IMAGES" ]; then
            echo "没有找到任何镜像"
            exit 1
        fi
        
        echo "备份以下镜像:"
        echo "$IMAGES"
        
        docker save $IMAGES -o "$BACKUP_FILE"
        
        echo "备份完成!"
        echo "文件大小: $(du -h $BACKUP_FILE | cut -f1)"
        ;;
        
    "load"|"restore"|"import")
        if [ ! -f "$BACKUP_FILE" ]; then
            echo "错误: 备份文件 $BACKUP_FILE 不存在"
            exit 1
        fi
        
        echo "从 $BACKUP_FILE 恢复Docker镜像..."
        docker load -i "$BACKUP_FILE"
        echo "恢复完成!"
        ;;
        
    "list")
        echo "当前Docker镜像:"
        docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedAt}}\t{{.Size}}"
        ;;
        
    "info")
        if [ -f "$BACKUP_FILE" ]; then
            echo "备份文件信息:"
            echo "大小: $(du -h $BACKUP_FILE | cut -f1)"
            echo "修改时间: $(stat -c %y $BACKUP_FILE)"
            
            # 列出tar中的镜像
            echo "包含的镜像:"
            tar -xf "$BACKUP_FILE" -O manifest.json 2>/dev/null | jq -r '.[].RepoTags[]' 2>/dev/null || \
            echo "无法读取镜像列表,可能格式不支持"
        else
            echo "备份文件不存在"
        fi
        ;;
        
    *)
        echo "用法: $0 {save|load|list|info} [备份文件]"
        echo "示例:"
        echo "  $0 save                         # 备份到 docker-images-backup.tar"
        echo "  $0 save my-backup.tar           # 备份到指定文件"
        echo "  $0 load                         # 从默认文件恢复"
        echo "  $0 load my-backup.tar          # 从指定文件恢复"
        echo "  $0 list                         # 列出当前镜像"
        echo "  $0 info                         # 查看备份文件信息"
        exit 1
        ;;
esac
  1. 使用 Docker 镜像来备份 Docker 镜像(元!)
# Dockerfile.backup
FROM alpine:latest
RUN apk add --no-cache docker-cli
COPY backup.sh /backup.sh
RUN chmod +x /backup.sh
ENTRYPOINT ["/backup.sh"]
# backup.sh
#!/bin/sh
# 挂载Docker socket,备份所有镜像
docker save $(docker images -q) -o /backup/images.tar
echo "备份完成!"

最简单的单行命令

# 备份所有镜像
docker save $(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>") -o all-images.tar

# 恢复所有镜像
docker load -i all-images.tar

注意事项
权限问题:确保有足够的磁盘空间

镜像数量:如果有大量镜像,考虑分批处理

特殊字符:镜像名中的特殊字符可能需要处理

版本兼容性:备份的镜像在不同Docker版本间可能有限制

推荐使用第3个脚本(高级脚本),它包含验证和日志记录,更安全可靠。