Docker 镜像拉取与导出脚本

Docker 镜像拉取与导出脚本

功能概述

该脚本用于批量拉取 Docker 镜像并导出为 tar 文件,导出成功后自动删除本地镜像以释放磁盘空间。

主要特性

  • ✅ 批量拉取 Docker 镜像
  • ✅ 自动导出为 tar 文件
  • ✅ 导出成功后自动删除本地镜像(释放磁盘空间)
  • ✅ 彩色日志输出,清晰易读
  • ✅ 详细的成功/失败统计
  • ✅ 显示磁盘空间使用情况

前置要求

  • 已安装 Docker
  • 具有 Docker 操作权限
  • 确保有足够的磁盘空间存储导出的 tar 文件

使用方法

1. 基本使用(使用默认配置)

./pull_and_save_images.sh

默认配置:
– 镜像列表文件:images.txt
– 保存目录:./images

2. 指定镜像列表文件

./pull_and_save_images.sh -f my_images.txt

3. 指定保存目录

./pull_and_save_images.sh -d /backup/docker_images

4. 同时指定文件和目录

./pull_and_save_images.sh -f my_images.txt -d /backup/docker_images

5. 查看帮助信息

./pull_and_save_images.sh -h

镜像列表文件格式

创建一个文本文件(如 images.txt),每行一个镜像地址:

# 这是注释行,会被忽略
reg-hub.gzeport.com/jsb/gzeport-sso/gzeport-sso-web:202603181336-23
reg-hub.gzeport.com/jsb/managemodule/gzeport-manage-web:202603181152-66
reg-hub.gzeport.com/jsb/managemodule/gzeport-manage-server:202603181152-66

# 空行会被忽略
reg-hub.gzeport.com/jsb/datamanage/gzeport-datamanage-web:202603181045-34

注意事项:
– 每行一个完整的镜像地址(包含仓库地址和标签)
– 以 # 开头的行为注释,会被忽略
– 空行会被自动跳过

命令行参数说明

参数 简写 说明 默认值
–file -f 指定镜像列表文件 images.txt
–dir -d 指定保存目录 ./images
–help -h 显示帮助信息

工作流程

1. 读取镜像列表文件
   ↓
2. 拉取 Docker 镜像
   ↓
3. 导出为 tar 文件
   ↓
4. 自动删除本地镜像(释放磁盘空间)
   ↓
5. 显示统计信息和磁盘使用情况

输出文件命名规则

导出的 tar 文件命名格式:<镜像名>-<标签>.tar

示例:
– 镜像:reg-hub.gzeport.com/jsb/gzeport-sso/gzeport-sso-web:202603181336-23
– 文件名:gzeport-sso-web-202603181336-23.tar

日志输出示例

[INFO] 2026-03-18 13:45:20 - Docker已安装,版本: Docker version 24.0.7
[INFO] 2026-03-18 13:45:20 - 从文件读取镜像列表: images.txt
[INFO] 2026-03-18 13:45:20 - 开始处理 5 个镜像
================================
[INFO] 2026-03-18 13:45:21 - 开始拉取镜像: reg-hub.gzeport.com/jsb/gzeport-sso/gzeport-sso-web:202603181336-23
[INFO] 2026-03-18 13:45:35 - 镜像拉取成功: reg-hub.gzeport.com/jsb/gzeport-sso/gzeport-sso-web:202603181336-23
[INFO] 2026-03-18 13:45:35 - 开始保存镜像到: ./images/gzeport-sso-web-202603181336-23.tar
[INFO] 2026-03-18 13:45:50 - 镜像保存成功: ./images/gzeport-sso-web-202603181336-23.tar
[INFO] 2026-03-18 13:45:50 - 文件大小: 812M
[INFO] 2026-03-18 13:45:50 - 删除本地镜像以释放磁盘空间: reg-hub.gzeport.com/jsb/gzeport-sso/gzeport-sso-web:202603181336-23
[INFO] 2026-03-18 13:45:51 - 镜像删除成功: reg-hub.gzeport.com/jsb/gzeport-sso/gzeport-sso-web:202603181336-23
--------------------------------
================================
[INFO] 2026-03-18 14:09:03 - 镜像拉取成功: reg-hub.gzeport.com/jsb/gzeport-gzsw-server/gzeport-openapi-wechat:202603181401-78
[INFO] 2026-03-18 14:09:03 - 开始保存镜像到: ./images/gzeport-openapi-wechat-202603181401-78.tar
[INFO] 2026-03-18 14:09:08 - 镜像保存成功: ./images/gzeport-openapi-wechat-202603181401-78.tar
[INFO] 2026-03-18 14:09:08 - 文件大小: 567M
[INFO] 2026-03-18 14:09:08 - 删除本地镜像以释放磁盘空间: reg-hub.gzeport.com/jsb/gzeport-gzsw-server/gzeport-openapi-wechat:202603181401-78
[INFO] 2026-03-18 14:09:08 - 镜像删除成功: reg-hub.gzeport.com/jsb/gzeport-gzsw-server/gzeport-openapi-wechat:202603181401-78
--------------------------------
================================
[INFO] 2026-03-18 14:09:08 - 处理完成!
[INFO] 2026-03-18 14:09:08 - 总计: 5, 成功: 5, 失败: 0
[INFO] 2026-03-18 14:09:08 - 当前磁盘空间使用情况:
/dev/mapper/klas-root        91G   44G   47G   49% /
[INFO] 2026-03-18 14:09:08 - 已保存的镜像文件:

常见问题

1. 镜像删除失败怎么办?

如果镜像正在被容器使用,删除会失败并显示警告,但不影响整体流程。可以手动停止相关容器后再删除:

# 查看使用该镜像的容器
docker ps -a --filter ancestor=<镜像名>

# 停止并删除容器
docker stop <容器ID>
docker rm <容器ID>

# 删除镜像
docker rmi <镜像名>

2. 如何恢复导出的镜像?

使用 docker load 命令:

docker load -i ./images/gzeport-sso-web-202603181336-23.tar

3. 磁盘空间不足怎么办?

  • 确保保存目录所在分区有足够空间
  • 脚本会在导出后自动删除本地镜像,释放空间
  • 可以分批处理镜像,避免同时处理过多

4. 如何验证导出的 tar 文件是否完整?

# 查看 tar 文件内容
tar -tvf ./images/gzeport-sso-web-202603181336-23.tar

# 或者尝试加载镜像
docker load -i ./images/gzeport-sso-web-202603181336-23.tar

示例场景

场景 1:备份生产环境镜像

# 1. 创建镜像列表
cat > prod_images.txt <<EOF
reg-hub.gzeport.com/jsb/gzeport-sso/gzeport-sso-web:202603181336-23
reg-hub.gzeport.com/jsb/managemodule/gzeport-manage-web:202603181152-66
EOF

# 2. 执行备份到指定目录
./pull_and_save_images.sh -f prod_images.txt -d /backup/prod_images

# 3. 查看备份结果
ls -lh /backup/prod_images/

场景 2:定时自动备份(Crontab)

# 编辑 crontab
crontab -e

# 添加定时任务(每天凌晨 2 点执行)
0 2 * * * cd /path/to/script && ./pull_and_save_images.sh > /var/log/docker_backup_$(date +\%Y\%m\%d).log 2>&1

下面是脚本

#!/bin/bash

# 镜像拉取并保存脚本
# 功能:批量拉取Docker镜像并保存为tar文件

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # 无颜色

# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

# 检查Docker是否安装
check_docker() {
    if ! command -v docker &> /dev/null; then
        log_error "Docker未安装,请先安装Docker"
        exit 1
    fi
    log_info "Docker已安装,版本: $(docker --version)"
}

# 拉取并保存单个镜像
pull_and_save_image() {
    local image=$1
    local save_dir=$2

    # 提取镜像名称(去除仓库地址和标签)
    local image_name=$(echo "$image" | awk -F'/' '{print $NF}' | sed 's/:/-/g')
    local tar_file="${save_dir}/${image_name}.tar"

    log_info "开始拉取镜像: $image"

    # 拉取镜像
    if docker pull "$image"; then
        log_info "镜像拉取成功: $image"
    else
        log_error "镜像拉取失败: $image"
        return 1
    fi

    # 保存镜像为tar文件
    log_info "开始保存镜像到: $tar_file"
    if docker save -o "$tar_file" "$image"; then
        log_info "镜像保存成功: $tar_file"
        # 显示文件大小
        local file_size=$(du -h "$tar_file" | awk '{print $1}')
        log_info "文件大小: $file_size"

        # 导出成功后删除本地镜像以释放磁盘空间
        log_info "删除本地镜像以释放磁盘空间: $image"
        if docker rmi "$image" > /dev/null 2>&1; then
            log_info "镜像删除成功: $image"
        else
            log_warn "镜像删除失败(可能被其他容器使用): $image"
        fi
    else
        log_error "镜像保存失败: $image"
        return 1
    fi

    return 0
}

# 从文件读取镜像列表
read_images_from_file() {
    local file=$1
    local images=()

    # 检查文件是否存在
    if [ ! -f "$file" ]; then
        log_error "镜像列表文件不存在: $file"
        exit 1
    fi

    # 读取文件,过滤空行和注释行
    while IFS= read -r line || [ -n "$line" ]; do
        # 去除首尾空格
        line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
        # 跳过空行和以#开头的注释行
        if [ -n "$line" ] && [[ ! "$line" =~ ^# ]]; then
            images+=("$line")
        fi
    done < "$file"

    # 返回镜像数组
    printf '%s\n' "${images[@]}"
}

# 主函数
main() {
    # 检查Docker
    check_docker

    # 默认镜像列表文件
    local image_list_file="images.txt"
    # 保存目录(默认为当前目录下的images文件夹)
    local save_dir="./images"

    # 解析命令行参数
    while [[ $# -gt 0 ]]; do
        case $1 in
            -f|--file)
                image_list_file="$2"
                shift 2
                ;;
            -d|--dir)
                save_dir="$2"
                shift 2
                ;;
            -h|--help)
                echo "使用方法: $0 [选项]"
                echo "选项:"
                echo "  -f, --file <文件>    指定镜像列表文件 (默认: images.txt)"
                echo "  -d, --dir <目录>     指定保存目录 (默认: ./images)"
                echo "  -h, --help           显示帮助信息"
                exit 0
                ;;
            *)
                log_error "未知参数: $1"
                echo "使用 -h 或 --help 查看帮助信息"
                exit 1
                ;;
        esac
    done

    # 从文件读取镜像列表
    log_info "从文件读取镜像列表: $image_list_file"
    mapfile -t images < <(read_images_from_file "$image_list_file")

    # 检查是否读取到镜像
    if [ ${#images[@]} -eq 0 ]; then
        log_error "镜像列表为空,请检查文件: $image_list_file"
        exit 1
    fi

    # 创建保存目录
    if [ ! -d "$save_dir" ]; then
        mkdir -p "$save_dir"
        log_info "创建保存目录: $save_dir"
    fi

    # 统计信息
    local total=${#images[@]}
    local success=0
    local failed=0

    log_info "开始处理 $total 个镜像"
    echo "================================"

    # 遍历镜像列表
    for image in "${images[@]}"; do
        if pull_and_save_image "$image" "$save_dir"; then
            ((success++))
        else
            ((failed++))
        fi
        echo "--------------------------------"
    done

    # 输出统计结果
    echo "================================"
    log_info "处理完成!"
    log_info "总计: $total, 成功: $success, 失败: $failed"

    # 显示磁盘空间使用情况
    log_info "当前磁盘空间使用情况:"
    df -h | grep -E "Filesystem|/$"

    # 列出保存的文件
    if [ $success -gt 0 ]; then
        log_info "已保存的镜像文件:"
        ls -lh "$save_dir"/*.tar 2>/dev/null
    fi
}

# 执行主函数
main "$@"

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇