要在没有网络连接的环境中使用Docker安装镜像,你需要提前下载镜像文件,并通过某种方式将其传输到目标机器上。以下是步骤和示例代码:
在有网络连接的机器上,下载Docker镜像:
docker pull [IMAGE_NAME]:[TAG]
保存镜像为tar文件:
docker save -o [PATH_TO_SAVE]/[IMAGE_NAME].[TAG].tar [IMAGE_NAME]:[TAG]
将tar文件复制到离线的Docker主机上。
在离线的Docker主机上,加载镜像tar文件:
docker load -i [PATH_TO_SAVE]/[IMAGE_NAME].[TAG].tar
现在可以运行镜像:
docker run -d --name [CONTAINER_NAME] [IMAGE_NAME]:[TAG]
请确保替换[IMAGE_NAME]
, [TAG]
, [PATH_TO_SAVE]
和 [CONTAINER_NAME]
为实际的镜像名、标签、保存路径和容器名。
我这里写了一个脚本来导出docker
#!/bin/bash
GREEN="\033[0;32m"
YELLOW="\033[1;33m"
BLUE="\033[0;34m"
NC="\033[0m"
EXPORT_DIR="docker_images_export_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$EXPORT_DIR"
echo -e "${BLUE}创建导出目录: $EXPORT_DIR${NC}"
images=($(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>"))
total_images=${#images[@]}
echo -e "${YELLOW}发现 $total_images 个镜像需要导出${NC}"
echo -e "${YELLOW}开始导出过程...${NC}\n"
current=0
for image in "${images[@]}"; do
current=$((current + 1))
echo -e "${BLUE}[$current/$total_images] 正在导出: $image${NC}"
filename=$(echo "$image" | tr "/" "_" | tr ":" "_").tar
docker save -o "$EXPORT_DIR/$filename" "$image"
if [ $? -eq 0 ]; then
size=$(du -h "$EXPORT_DIR/$filename" | cut -f1)
echo -e "${GREEN}✓ 成功导出: $filename (大小: $size)${NC}\n"
else
echo -e "\033[0;31m✗ 导出失败: $image\033[0m\n"
fi
done
total_size=$(du -sh "$EXPORT_DIR" | cut -f1)
echo -e "${GREEN}导出完成!${NC}"
echo -e "${BLUE}总共导出 $total_images 个镜像${NC}"
echo -e "${BLUE}导出文件位置: $(pwd)/$EXPORT_DIR${NC}"
echo -e "${BLUE}总占用空间: $total_size${NC}"
又写了一个脚本,用于导入docker
#!/bin/bash
GREEN="\033[0;32m"
YELLOW="\033[1;33m"
BLUE="\033[0;34m"
RED="\033[0;31m"
NC="\033[0m"
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}请使用 sudo 运行此脚本${NC}"
exit 1
fi
check_docker() {
if ! command -v docker &> /dev/null; then
echo -e "${RED}Docker 未安装。是否要安装 Docker? (y/n)${NC}"
read -r install_docker
if [ "$install_docker" = "y" ]; then
echo -e "${YELLOW}正在安装 Docker...${NC}"
apt-get update
apt-get install -y docker.io
systemctl start docker
systemctl enable docker
else
echo -e "${RED}Docker 是必需的。退出安装。${NC}"
exit 1
fi
fi
}
check_docker_service() {
if ! systemctl is-active --quiet docker; then
echo -e "${YELLOW}Docker 服务未运行,正在启动...${NC}"
systemctl start docker
fi
}
LOG_DIR="docker_import_logs"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/import_$(date +%Y%m%d_%H%M%S).log"
log_message() {
echo -e "$1" | tee -a "$LOG_FILE"
}
main() {
check_docker
check_docker_service
tar_files=(*.tar)
if [ ! -e "${tar_files[0]}" ]; then
log_message "${RED}错误:当前目录下没有找到 .tar 文件${NC}"
exit 1
fi
total_files=${#tar_files[@]}
total_size=$(du -ch "${tar_files[@]}" | tail -n1 | cut -f1)
log_message "${BLUE}找到 $total_files 个镜像文件需要导入${NC}"
log_message "${BLUE}总大小: $total_size${NC}"
log_message "${YELLOW}开始导入过程...${NC}\n"
current=0
success_count=0
failed_count=0
start_time=$(date +%s)
for tar_file in "${tar_files[@]}"; do
current=$((current + 1))
log_message "${BLUE}[$current/$total_files] 正在导入: $tar_file${NC}"
file_size=$(du -h "$tar_file" | cut -f1)
log_message "${YELLOW}文件大小: $file_size${NC}"
if docker load -i "$tar_file" 2>> "$LOG_FILE"; then
log_message "${GREEN}✓ 成功导入: $tar_file${NC}"
success_count=$((success_count + 1))
else
log_message "${RED}✗ 导入失败: $tar_file${NC}"
failed_count=$((failed_count + 1))
fi
log_message ""
done
end_time=$(date +%s)
duration=$((end_time - start_time))
minutes=$((duration / 60))
seconds=$((duration % 60))
log_message "${GREEN}导入完成!${NC}"
log_message "${BLUE}总耗时: ${minutes}分${seconds}秒${NC}"
log_message "${BLUE}成功导入: $success_count 个镜像${NC}"
if [ $failed_count -gt 0 ]; then
log_message "${RED}导入失败: $failed_count 个镜像${NC}"
log_message "${YELLOW}请查看日志文件了解详细信息: $LOG_FILE${NC}"
fi
log_message "\n${BLUE}当前系统中的 Docker 镜像列表:${NC}"
docker images | tee -a "$LOG_FILE"
}
main
docker 不同设备的镜像是否是通用的?
Docker 镜像的 tar 包是跨平台通用的,这是因为:
-
Docker 镜像的特性:
- Docker 镜像是平台无关的,采用 OCI(Open Container Initiative)标准
- 镜像内部的文件系统和配置是独立的,与宿主机操作系统无关
docker save
和docker load
命令产生和使用的格式是标准化的
-
但是需要注意:
- 虽然镜像格式是通用的,但镜像本身可能会包含特定架构的二进制文件
- 需要确保镜像支持目标机器的 CPU 架构(比如 AMD64/x86_64 或 ARM64)
让我们验证一下您的镜像架构:
docker images --format "{{.Repository}}:{{.Tag}} - {{.Architecture}}" | cat
让我们用另一个命令来查看:
docker inspect $(docker images -q) | grep Architecture
我看到您当前的镜像都是 ARM64 架构的,这可能会带来一些注意事项:
-
架构兼容性:
- 如果目标 Ubuntu 服务器是 x86_64(AMD64)架构,这些 ARM64 镜像可能无法直接运行
- 如果目标服务器也是 ARM64 架构(比如 AWS Graviton 或其他 ARM 服务器),则可以直接使用
-
解决方案:
a. 如果目标服务器是 x86_64 架构:- 建议在相同架构的机器上重新拉取和打包这些镜像
- 或者使用支持多架构的镜像(multi-arch images)
b. 如果目标服务器也是 ARM64 架构:
- 可以直接使用当前的镜像包
-
检查目标服务器架构的命令:
uname -m # 或 arch
- 如果显示
x86_64
,则是 Intel/AMD 架构 - 如果显示
aarch64
或arm64
,则是 ARM 架构
- 如果显示
-
建议:
- 在迁移之前,先确认目标 Ubuntu 服务器的 CPU 架构
- 如果架构不同,建议:
- 在目标架构的机器上重新拉取这些镜像
- 使用
docker save
重新打包 - 然后再进行迁移
-
使用多架构镜像:
- 如果可能,建议使用支持多架构的官方镜像
- 这样的镜像可以在不同架构的机器上自动选择正确的版本