离线获取 Docker 镜像

在内网中使用 docker 源,标准的方式是使用 harbor。如果是小量的只需要几个镜像,我们可以使用 docker save 和 docker load 的命令,将外部的容器镜像导入内部。下面介绍一下用法,最后还附带一个一键保存、还原所有镜像的脚本。

保存单个镜像

  1. 环境准备

    • 服务器node01、node02
    • node01可以访问外网,node02不能访问外网,但node01与node02之间是互通的
    • node01和node02均已成功安装并启动Docker
  2. 在node01上,从远程仓库获取镜像

    docker pull nginx
    	
    Using default tag: latest
    latest: Pulling from library/nginx
    8176e34d5d92: Pull complete
    5b19c1bdd74b: Pull complete
    4e9f6296fa34: Pull complete
    Digest: sha256:4771d09578c7c6a65299e110b3ee1c0a2592f5ea2618d23e4ffe7a4cab1ce5de
    Status: Downloaded newer image for nginx:latest
    
  3. 归档

    docker save -o nginx.tar library/nginx
    

    docker save : 将指定镜像保存成 tar 归档文件。 -o :输出到的文件。

  4. 将保存好的nginx.tar上传至服务器node02上

    scp nginx.tar root@node02:/tmp
    
  5. 登录node02,加载nginx.tar

    docker load -i /tmp/nginx.tar
    
    014cf8bfcb2d: Loading layer [==================================================>]  58.46MB/58.46MB
    832a3ae4ac84: Loading layer [==================================================>]  53.91MB/53.91MB
    e89b70d28795: Loading layer [==================================================>]  3.584kB/3.584kB
    Loaded image: nginx:latest
    

    docker load : 加载指定的tar归档文件格式的镜像。-i :指定要读取的tar归档文件格式的镜像。

批量保存镜像

如果需要保存比较多的镜像,这种笨重的方式显然不合适,我找到了这个脚本,一键打包/加载所有镜像,非常好用。

下载链接:hydra1983/docker_images.sh

源码备份如下:

#!/bin/bash

readonly DB_FILE="$(pwd)/images.db"
readonly IMG_DIR="$(pwd)/images"

save-images() {
  echo "Create ${DB_FILE}"
  echo "$(docker images|grep -v 'IMAGE ID'|awk '{printf("%s %s %s\n", $1, $2, $3)}'|column -t)" > "${DB_FILE}"
  
  echo "Read ${DB_FILE}"
  local images
  while read -r image; do
     images+=("$image"); 
  done <<< "$(cat ${DB_FILE})"

  echo "Create ${IMG_DIR}"
  if [[ ! -d "${IMG_DIR}" ]]; then
    mkdir "${IMG_DIR}"
  fi
  
  local name tag id
  for image in "${images[@]}"; do
    name=$(echo $image|awk '{print $1}')
    tag=$(echo $image|awk '{print $2}')
    id=$(echo $image|awk '{print $3}')
        
    if [[ "${id}" != "" ]]; then
      local imgPath="${IMG_DIR}/${id}.dim"

      if [[ ! -f "${imgPath}" ]] ; then
        echo "[DEBUG] save ${id} ${name}:${tag} to ${imgPath}"
        (time  docker save -o "${imgPath}" ${name}:${tag}) 2>&1 | grep real
      else
        echo "[DEBUG] ${id} ${name}:${tag} already saved"
      fi
    fi    
  done
}

load-images() {
  if [[ ! -f "${DB_FILE}" ]]; then
    echo "No ${DB_FILE} to read"
    exit 0
  fi

  if [[ ! -d "${IMG_DIR}" ]]; then
    echo "No ${IMG_DIR} to load images"
    exit 0
  fi

  echo "Read ${DB_FILE}"
  local images
  while read -r image; do
     images+=("$image"); 
  done <<< "$(cat ${DB_FILE})"

  local name tag id
  for image in "${images[@]}"; do
    name=$(echo $image|awk '{print $1}')
    tag=$(echo $image|awk '{print $2}')
    id=$(echo $image|awk '{print $3}')
        
    if [[ "${id}" != "" ]]; then
      local imgPath="${IMG_DIR}/${id}.dim"

      if [[ "$(docker images|grep ${id} | grep ${name} | grep ${tag})" == "" ]]; then        
        if [[ "$(docker images|grep ${id})" == "" ]]; then
          echo "[DEBUG] load ${id} ${name}:${tag} from ${imgPath}"
          docker load -i "${imgPath}"
        else
          echo "[DEBUG] tag ${id} as ${name}:${tag}"
          docker tag ${id} ${name}:${tag}
        fi
      else
        echo "[DEBUG] ${id} ${name}:${tag} already loaded"
      fi
    fi
  done
}

$@

参考资料


王岐山为何推荐《旧制度与大革命》? - 人民日报海外版 使用脚本备份还原 postgresql