尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Docker镜像离线批量导入实战:5分钟部署48个常用镜像

Docker镜像离线批量导入实战:5分钟部署48个常用镜像 之前在公司内网环境部署 Docker 服务时最头疼的就是基础镜像拉取问题。网络隔离导致docker pull命令直接失效而项目依赖的几十个常用镜像如 Nginx、MySQL、Redis 等又必须提前准备好。手动一个个下载、导出、再导入效率极低且容易出错。本文将分享一套高效的 Docker 镜像离线批量导入方案手把手教你如何从有网环境“打包”常用镜像再到无网环境“一键式”恢复。整个过程最快只需 5 分钟即可完成 48 个甚至更多常用镜像的离线部署非常适合企业内网、开发测试隔离环境及离线服务器场景。1. 背景与核心概念为什么需要离线镜像包在深入操作之前我们先明确两个核心概念和需求场景。1.1 Docker 镜像与仓库Docker 镜像是包含应用及其运行环境的只读模板它基于分层存储结构。通常我们通过docker pull命令从公共仓库如 Docker Hub或私有仓库拉取镜像。这个过程需要服务器能够访问外网或指定的镜像仓库地址。1.2 离线环境的挑战在许多企业生产环境、保密研发环境或网络受限的场景中服务器出于安全考虑无法直接连接互联网。这就导致了服务无法启动所有依赖FROM基础镜像的 Dockerfile 构建都会失败。部署流程中断基于容器编排工具如 Kubernetes、Docker Compose的自动化部署流程会卡在镜像拉取环节。效率低下如果只能通过移动硬盘拷贝单个镜像的.tar文件面对成百上千个镜像时管理将是一场噩梦。因此一个能够批量导出、传输和导入Docker 镜像的标准化流程是保障离线环境下容器化应用顺利交付的关键。本文介绍的“懒人包”正是为解决此痛点而生它本质上是一个包含了多个镜像及其依赖层的归档文件集合。2. 环境准备与版本说明为了模拟完整的流程我们需要准备两台机器一台有外网权限的打包机和一台离线的目标服务器。以下操作均基于 Linux 系统Windows 或 macOS 上的 Docker Desktop 在命令行操作上基本一致。环境要求操作系统Ubuntu 20.04/CentOS 7.9 或更高版本本文以 CentOS 7.9 为例。Docker 版本Docker Engine 20.10.0 及以上。新旧版本在镜像导出/导入格式上可能存在兼容性问题建议保持一致。# 在打包机和目标服务器上均检查版本 docker --version # 输出示例Docker version 24.0.7, build afdd53b磁盘空间确保打包机和目标服务器有足够的磁盘空间存放镜像文件。48个常用镜像的压缩包大约需要 3-5 GB 空间。网络打包机需能访问 Docker Hub 或你的私有镜像仓库。本文示例镜像列表我们将准备一个包含基础运行环境、数据库、中间件和工具的常用镜像列表images.txt你可以根据实际需求增删。# images.txt 内容示例 nginx:alpine mysql:8.0 redis:alpine postgres:13-alpine mongo:6 node:18-alpine python:3.11-slim openjdk:11-jre-slim busybox:latest ubuntu:22.04 centos:7 alpine:latest # ... 此处可继续添加你的常用镜像总计48个3. 核心原理与工具拆解离线批量导入的核心在于两个 Docker 命令docker save和docker load以及配套的脚本化批量处理。3.1docker save将镜像导出为归档文件此命令将一个或多个镜像保存到一个 tar 归档文件中。# 保存单个镜像 docker save -o nginx_alpine.tar nginx:alpine # 保存多个镜像到同一个文件 docker save -o my_images.tar nginx:alpine redis:alpine mysql:8.0-o指定输出文件的路径和名称。关键特性docker save会保存镜像的完整历史记录和元数据非常适合用于镜像的备份和迁移。导出的文件可能会比较大。3.2docker load从归档文件载入镜像此命令从 tar 归档文件或标准输入流中载入镜像。docker load -i my_images.tar-i指定输入的 tar 文件。注意load载入的镜像会保留其原有的REPOSITORY和TAG信息。如果本地已存在同名同标签的镜像它会被覆盖。3.3 批量处理的 Shell 脚本单纯手动执行命令对于大量镜像是不现实的。我们需要编写 Shell 脚本实现从列表文件循环拉取或导出镜像。将多个镜像打包并压缩便于传输。在目标服务器上循环解压和导入。4. 完整实战案例5分钟实现48个镜像离线导入下面我们分步骤演示从“打包”到“导入”的全流程。4.1 步骤一在有网环境打包镜像在打包机上操作。1. 创建镜像列表文件mkdir -p ~/docker-offline cd ~/docker-offline vim images.txt将上述示例的镜像列表48个粘贴进去并保存。2. 编写批量拉取与导出脚本创建脚本pack_images.sh#!/bin/bash # pack_images.sh - 批量拉取并导出Docker镜像 IMAGE_LIST_FILEimages.txt OUTPUT_DIR./images_tar PACKAGE_NAMEdocker_images_offline_package # 创建输出目录 mkdir -p ${OUTPUT_DIR} echo “开始拉取镜像...” # 循环拉取镜像列表中的所有镜像 while IFS read -r image_name || [[ -n “$image_name” ]]; do # 跳过空行和注释行以#开头 [[ “$image_name” ~ ^#.* ]] || [[ -z “$image_name” ]] continue echo “正在拉取: ${image_name}” docker pull ${image_name} if [ $? -eq 0 ]; then echo “拉取成功: ${image_name}” else echo “[警告] 拉取失败: ${image_name}请检查镜像名或网络” fi done “${IMAGE_LIST_FILE}” echo “镜像拉取完成开始导出...” # 导出所有已拉取的镜像到一个tar文件 # 使用 docker images --format 获取所有镜像的 repository:tag 格式 ALL_IMAGES$(docker images --format “{{.Repository}}:{{.Tag}}” | grep -v “none“ | tr ‘\n’ ’ ‘) if [ -z “$ALL_IMAGES” ]; then echo “未找到可导出的镜像请检查拉取过程。” exit 1 fi echo “正在打包镜像: ${ALL_IMAGES}” docker save -o ${OUTPUT_DIR}/${PACKAGE_NAME}.tar ${ALL_IMAGES} if [ $? -eq 0 ]; then echo “镜像已成功导出到: ${OUTPUT_DIR}/${PACKAGE_NAME}.tar” # 可选压缩以减小传输体积 cd ${OUTPUT_DIR} tar -czvf ${PACKAGE_NAME}.tar.gz ${PACKAGE_NAME}.tar echo “压缩包已创建: ${PACKAGE_NAME}.tar.gz” ls -lh ${PACKAGE_NAME}.tar.gz else echo “镜像导出失败” exit 1 fi给脚本添加执行权限并运行chmod x pack_images.sh ./pack_images.sh脚本会依次拉取images.txt中的所有镜像然后将它们全部打包成一个docker_images_offline_package.tar文件并自动压缩为.tar.gz格式以节省空间。4.2 步骤二传输归档文件到离线环境将打包机~/docker-offline/images_tar/docker_images_offline_package.tar.gz文件通过安全的内部方式如内部文件服务器、堡垒机传输、U盘等拷贝到目标离线服务器的某个目录下例如/opt/docker-images/。# 在目标服务器上创建目录 mkdir -p /opt/docker-images # 假设文件已拷贝至此 cd /opt/docker-images ls -l # 应能看到 docker_images_offline_package.tar.gz 文件4.3 步骤三在离线环境批量导入镜像在目标服务器上操作。1. 编写批量导入脚本创建脚本load_images.sh#!/bin/bash # load_images.sh - 批量导入Docker镜像 PACKAGE_GZ“docker_images_offline_package.tar.gz” PACKAGE_TAR“docker_images_offline_package.tar” IMPORT_DIR“/opt/docker-images” cd ${IMPORT_DIR} || { echo “目录 ${IMPORT_DIR} 不存在”; exit 1; } if [ ! -f “${PACKAGE_GZ}” ]; then echo “压缩包 ${PACKAGE_GZ} 未找到” exit 1 fi echo “解压镜像包...” tar -xzvf ${PACKAGE_GZ} if [ ! -f “${PACKAGE_TAR}” ]; then echo “镜像tar文件 ${PACKAGE_TAR} 未找到” exit 1 fi echo “开始导入Docker镜像这可能需要几分钟取决于镜像大小和数量...” docker load -i ${PACKAGE_TAR} if [ $? -eq 0 ]; then echo “镜像批量导入成功” echo “验证已导入的镜像” docker images --format “table {{.Repository}}\t{{.Tag}}\t{{.Size}}“ | head -20 # 查看前20个 else echo “镜像导入失败” exit 1 fi # 清理中间解压的tar文件可选 # rm -f ${PACKAGE_TAR} echo “操作完成。”给脚本添加执行权限并运行chmod x load_images.sh ./load_images.sh脚本会自动解压并执行docker load。当终端出现类似Loaded image: nginx:alpine的滚动输出时表示正在导入。导入完成后使用docker images命令即可看到所有镜像。4.4 步骤四验证与使用导入完成后进行快速验证# 1. 检查镜像总数是否匹配预期 docker images | wc -l # 注意第一行是标题行镜像数结果-1 # 2. 运行一个测试容器 docker run --rm -d --name test-nginx nginx:alpine docker ps | grep test-nginx # 如果能看到容器在运行说明镜像导入成功且可用 # 3. 停止测试容器 docker stop test-nginx至此48个常用 Docker 镜像的离线批量导入全部完成。从执行导入脚本到验证完毕整个过程通常在5分钟以内具体时间取决于服务器性能和镜像包大小。5. 常见问题与排查思路在实际操作中你可能会遇到以下问题问题现象可能原因排查思路与解决方案docker save导出的.tar文件异常大1. 镜像本身层数多、体积大。2. 包含了多个镜像的重复层。1. 这是正常现象docker save保存的是完整镜像。2. 使用tar -czvf压缩后体积会显著减小。3. 考虑按需导出只导出必要的镜像。docker load时报错open /var/lib/docker/tmp/...: no space left on device目标服务器 Docker 存储目录磁盘空间不足。1. 使用df -h和docker system df检查磁盘和Docker存储使用情况。2. 清理无用镜像、容器和卷docker system prune -a谨慎操作。3. 扩展磁盘或更改Docker数据目录。docker load后镜像的REPOSITORY和TAG显示为none1. 源镜像本身标签就是none如中间层镜像。2. 使用docker save时指定的是镜像ID而非name:tag。1. 这是正常现象部分中间层镜像无标签。2.确保使用docker save时用镜像名:标签格式不要用镜像ID。脚本中docker images --format已正确指定格式。导入后运行容器失败提示No such image1. 镜像导入不完整或损坏。2. 容器运行时指定的镜像名或标签与导入的不符。1. 重新传输并导入镜像包检查传输过程中文件是否损坏使用md5sum校验。2. 使用docker images精确核对镜像名称和标签。脚本执行权限不足脚本没有执行权限或当前用户无权操作 Docker。1.chmod x *.sh赋予执行权。2. 将当前用户加入docker用户组sudo usermod -aG docker $USER然后退出终端重新登录生效。在离线环境docker load后镜像的依赖基础镜像缺失导出的镜像列表中可能漏掉了某些作为基础的公共镜像如scratch,alpine。1. 确保在打包机上docker images能看到所有层对应的镜像。2. 在images.txt中显式加入最基础的操作系统镜像如alpine,busybox。6. 最佳实践与工程建议将离线镜像分发流程化、规范化能极大提升团队效率。1. 镜像列表的维护版本固化在images.txt中为所有镜像指定明确的版本标签如nginx:1.24.0-alpine避免使用latest确保环境一致性。分类管理可以创建多个列表文件如base_images.txt基础OS、db_images.txt数据库、app_images.txt应用镜像便于按需打包。定期更新建立流程定期在有网环境更新镜像列表并生成新的离线包同步给离线环境。2. 打包过程的优化使用私有仓库中转更专业的做法是在有网环境搭建私有镜像仓库如 Harbor将所有需要的镜像推送到私有仓库。然后从私有仓库导出为离线包。这样便于版本管理和权限控制。增量更新如果只是更新少数几个镜像可以单独导出这几个镜像的 tar 包而不是每次都全量打包。在目标服务器上单独load即可新镜像会自动覆盖旧标签。完整性校验在打包机和目标服务器上对生成的tar.gz文件计算 MD5 或 SHA256 校验和确保文件在传输过程中未损坏。# 打包机生成校验文件 md5sum docker_images_offline_package.tar.gz package.md5 # 目标服务器校验 md5sum -c package.md53. 安全与权限镜像来源可信只从官方或可信的渠道拉取镜像避免引入带有安全漏洞或恶意软件的镜像。最小权限原则运行 Docker 守护进程和脚本的用户应遵循最小权限原则。扫描镜像漏洞在有网环境可以使用docker scan需登录 Docker Hub或 Trivy、Clair 等工具对镜像进行安全扫描再将安全的镜像打包离线。4. 与 CI/CD 流程集成在持续集成CI阶段可以增加一个生成离线镜像包的步骤作为制品的一部分发布。在持续部署CD到离线环境时将加载离线镜像包作为前置步骤写入部署脚本中。通过这套方案你不仅能解决“懒人包拉不到镜像”的燃眉之急更能构建起一套健壮的、适用于离线或隔离环境的容器化应用交付体系。从手动折腾到脚本化自动化效率的提升是显而易见的。下次面对新的离线服务器你只需要拷贝一个文件并运行一个脚本基础环境瞬间就绪。
返回列表