利用 Katacoda 免费同步 Docker 镜像到 Docker Hub

Posted by Mike on 2020-05-24

为什么要同步

安装 kubernetes 的时候,我们需要用到 gcr.io/google_containers 下面的一些镜像,在国内是不能直接下载的。如果用 Self Host 方式安装,Master 上的组件除开 Kubelet 之外都用容器运行,甚至 CNI 插件也是容器运行。比如 Flannel,在 quay.io/coreos 下面,在国内下载非常慢。但是我们可以把这些镜像同步到我们的 Docker Hub 仓库里,再配个 Docker Hub 加速器,这样下载镜像就很快了。

原理

Katacoda 是一个在线学习平台,在 Web 上提供学习需要的服务器终端,里面包含学习所需的环境,我们可以利用 Docker 课程的终端来同步,因为里面有 Docker 环境,可以执行 docker login、docker pull、docker tag、docker push 等命令来实现同步镜像。

但是手工去执行命令很麻烦,如果要同步的镜像和 Tag 比较多,手工操作那就是浪费生命。我们可以利用程序代替手工操作,不过 Katacoda 为了安全起见,不允许执行外来的二进制程序,但是可以 Shell 脚本,我写好了脚本,大家只需要粘贴进去根据自己需要稍稍修改下,然后运行就可以了。

Let’s Do It

点击 这里 进入 Docker 课程。

点击 START SCENARIO 或 终端右上角全屏按钮将终端放大。

安装脚本依赖的 jq 命令

1
$ apt install jq

登录 Docker Hub

1
$ docker login

创建脚本并赋予执行权限

1
2
$ touch sync
$ chmod +x sync

编辑脚本,可以使用自带的 vim 编辑器

1
$ vim sync

将脚本粘贴进去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#! /bin/bash

docker_repo="k8smirror" # your docker hub username or organization name
registry="gcr.io" # the registry of original image, e.g. gcr.io, quay.io
repo="google_containers" # the repository name of original image


sync_one(){
docker pull ${registry}/${repo}/${1}:${2}
docker tag ${registry}/${repo}/${1}:${2} docker.io/${docker_repo}/${1}:${2}
docker push docker.io/${docker_repo}/${1}:${2}
docker rmi -f ${registry}/${repo}/${1}:${2} docker.io/${docker_repo}/${1}:${2}
}

sync_all_tags() {
for image in $*; do
tags_str=`curl https://${registry}/v2/${repo}/$image/tags/list | jq '.tags' -c | sed 's/\[/\(/g' | sed 's/\]/\)/g' | sed 's/,/ /g'`
echo "$image $tags_str"
src="
sync_one(){
docker pull ${registry}/${repo}/\${1}:\${2}
docker tag ${registry}/${repo}/\${1}:\${2} docker.io/${docker_repo}/\${1}:\${2}
docker push docker.io/${docker_repo}/\${1}:\${2}
docker rmi -f ${registry}/${repo}/\${1}:\${2} docker.io/${docker_repo}/\${1}:\${2}
}
tags=${tags_str}
echo \"$image ${tags_str}\"
for tag in \${tags[@]}
do
sync_one $image \${tag}
done;"
bash -c "$src"
done
}

sync_with_tags(){
image=$1
skip=1
for tag in $*; do
if [ $skip -eq 1 ]; then
skip=0
else
sync_one $image $tag
fi
done
}

sync_after_tag(){
image=$1
start_tag=$2
tags_str=`curl https://${registry}/v2/${repo}/$image/tags/list | jq '.tags' -c | sed 's/\[/\(/g' | sed 's/\]/\)/g' | sed 's/,/ /g'`
echo "$image $tags_str"
src="
sync_one(){
docker pull ${registry}/${repo}/\${1}:\${2}
docker tag ${registry}/${repo}/\${1}:\${2} docker.io/${docker_repo}/\${1}:\${2}
docker push docker.io/${docker_repo}/\${1}:\${2}
docker rmi -f ${registry}/${repo}/\${1}:\${2} docker.io/${docker_repo}/\${1}:\${2}
}
tags=${tags_str}
start=0
for tag in \${tags[@]}; do
if [ \$start -eq 1 ]; then
sync_one $image \$tag
elif [ \$tag == '$start_tag' ]; then
start=1
fi
done"
bash -c "$src"
}

get_tags(){
image=$1
curl https://${registry}/v2/${repo}/$image/tags/list | jq '.tags' -c
}

#sync_with_tags etcd 2.0.12 2.0.13 # sync etcd:2.0.12 and etcd:2.0.13
#sync_after_tag etcd 2.0.8 # sync tag after etcd:2.0.8
#sync_all_tags etcd hyperkube # sync all tags of etcd and hyperkube

脚本中有一些参数需要根据你自己情况修改,可以使用它自带的 vim 在线修改,也可以在你本地改好在粘贴上去。

  • docker_repo 改为你的 Docker Hub 账号组织名
  • registry 改为被同步镜像所在仓库的域名
  • repo 改为被同步镜像所在仓库的账号或组织名

在脚本最后,可以调用写好的函数来实现镜像同步,举例:

  • 同步一个镜像中指定的一个或多个 tag
1
sync_with_tags etcd 2.0.12 2.0.13
  • 从某个 Tag 后面的 Tag 开始一直同步到最后(Tag 顺序按照字母数字来的,不是上传日期;Katacoda 终端用久了会断连,可能处于安全原因考虑,断开之后可以看 Tag 同步到哪一个了,然后执行类似下面的命令从断连的 Tag 开始同步)
1
sync_after_tag etcd 2.0.8

同步一个或多个镜像的所有 Tag

1
sync_all_tags etcd hyperkube

最后执行脚本

1
$ ./sync

这就开始同步了,Katacoda 服务器在国外,下载 gcr.ioquay.io 上那些镜像都很快,上传 Docker Hub 也很快。如果断连了,可以在 Docker Hub 上查最新上传的 Tag 是哪个(如:https://hub.docker.com/r/k8smirror/hyperkube/tags/ 把 k8smirror 改为你的 Docker 用户名或组织名,hyperkube 改为镜像名),然后改脚本,用 sync_after_tag 这个函数继续上传。

本文转载自:「I’m roc Blog」,原文:http://t.cn/AiW3Jpot,版权归原作者所有。欢迎投稿,投稿邮箱: editor@hi-linux.com