本文最后编辑于   前,其中的内容可能需要更新。
                
                
                    
                
                 
                在生产中有时候会遇上一个比较恶心的问题,因为经常性需要去各个甲方部署,公司的平台基于docker-compose部署,另外还有大大小小各种乱七八糟几百个镜像的业务依赖,每部署一次都需要重新挑出所需的镜像对其进行导出,再将其部署。
原有方案 将docker镜像通过docker save 的方式导出为tar包,然后再到需要部署的机器上导入:
1 2 # 导出操作 docker images|grep -v "REPOSITORY"|awk '{print "docker save -o "NR".tar " $1":"$2}' |awk '{system($0)}' 
 
1 2 #  导入操作 ls *.tar|awk '{print $NF}'|sed -r 's#(.*)#sudo docker load -i \1#' |bash 
 
问题 这个方案存在两个问题,一来是docker容器通过docker save 导出后会占用大量的磁盘空间,而且费时费力,另外需要在某台机器先部署好镜像才能进行导出,
为了提高效率,拟采用新的方式进行镜像的搬运。
使用私有镜像仓库来进行搬运 docker 官方镜像中存在docker registry的镜像,该镜像可比较方便的进行导入导出,并且镜像分层,可以较好的解决磁盘占用和导入时间长的问题。这个方式类似上一章中提到的harbor做镜像存储操作,
1 2 3 4 5 6 #  运行容器 docker pull registry docker run -d -p 80:5000 -v /root/registry:/var/lib/registry registry # 推送镜像 docker images|grep -v "REPOSITORY"|awk '{print "docker tag " $1":"$2 "localhost:5000/"  $1":"$2}' |awk '{system($0)}' docker images|grep "localhost"|awk '{print "docker push " $1":"$2}' |awk '{system($0)}' 
 
此时registry文件夹即保存的镜像,
部署:
1 2 3 #  导入registry镜像 docker  load -i registry.tar docker run -d -p 5000:5000 -v /root/registry:/var/lib/registry registry 
 
通过python脚本简单下载:
1 2 3 4 5 6 7 8 import  requestsimport  jsonimport  osres = requests.get("http://127.0.0.1:5000/v2/_catalog" ) imagelist = res.json()["repositories" ] for  i in  imagelist:    os.system(f"docker pull localhost:5000/{i} " )     os.system(f"docker tag localhost:5000/{i}  {i} " ) 
 
问题 这个方案虽然解决磁盘占用问题,但仍需要通过本地的docker 导出镜像。同样会带来大量的镜像。
最终方案(?) 最近听说了skopeo之后发现它可以比较方便的解决这个问题,但执行起来还是有一些阻碍:
各种依赖镜像原本都是使用Dockerfile进行构建的,此时使用skopeo去获取镜像并不容易 
skopeo保存的镜像仍然存在分层重复的问题,重复占用磁盘的问题仍旧存在。 
 
解决问题:
搭建私有的harbor仓库 不多做赘述,可以参考此处 
在本地构建镜像后推送到私有harbor 先构建全部的可能用到的镜像,构建过程略,在harbor建立一个image仓库,然后推送:
1 2 docker images|grep -v "REPOSITORY"|awk '{print "docker tag " $1":"$2 "harbor.local/images/"  $1":"$2}' |awk '{system($0)}' docker images|grep "harbor.local"|awk '{print "docker push " $1":"$2}' |awk '{system($0)}' 
 
使用skopeo拉取镜像 skopeo镜像拉取方式:
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 skopeo  sync --src docker harbor.local/image/nginx:latest  --dest  dir image --insecure-policy --tls-verify=false WARN[0000] '--tls-verify' is deprecated, please set this on the specific subcommand  INFO[0000] Tag presence check                            imagename="harbor.local/image/nginx:latest" tagged=true INFO[0000] Copying image ref 1/1                         from="docker://harbor.local/image/nginx:latest" to="dir:image/nginx:latest" Getting image source signatures Copying blob 7dbe7f8c80d3 done   Copying blob 89a5e550c323 done   Copying blob 2ef7f86534fd done   Copying blob b2109f84b5d3 done   Copying blob f88e263879e1 done   Copying blob e445148a2a87 done   Copying config 4f380adfc1 done   Writing manifest to image destination Storing signatures INFO[0006] Synced 1 images from 1 sources       
 
通过脚本获取需要的镜像列表,然后对其分别拉取到image目录。
此时image的目录结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 tree images/ images/ └── nginx:latest     ├── 2ef7f86534fdfcd45609e1f26fae69dff48828665da24023b86ce80a4efdea06     ├── 4f380adfc10f4cd34f775ae57a17d2835385efd5251d6dfe0f246b0018fb0399     ├── 7dbe7f8c80d3a2e99a0d1e07e4314dc18fecaf591563e596c1080698173d3724     ├── 89a5e550c32388274bd4ced3c636fa8a3f21b1fd01e0f3b91bad4769ead317c6     ├── b2109f84b5d3876f7fe664c298f91e4de086ce6d892cf6b885820e168fe6d10b     ├── e445148a2a87d1e55db8d9e3f0f554481cb2ff8bf70383ad3f34d5379c5ad984     ├── f88e263879e1903b1cdf9fe53ace2241fc3995aaa77b6524a1dcf3f9447bfd06     ├── manifest.json     └── version 
 
转换拉取的镜像文件 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 import  osimport  jsonimport  hashlibos.mkdir("registry" ) os.makedirs(f"registry/docker/registry/v2/blobs/sha256" ) imagelist=["nginx:latest" ] for  i in  imagelist:    os.system(f"skopeo  sync --src docker harbor.local/test/{i}   --dest  dir image --insecure-policy --tls-verify=false" )     imagename=i.split(':' )[0 ]     imagetag=i.split(':' )[1 ]     os.makedirs(f"registry/docker/registry/v2/repositories/{imagename} " )     with  open (f"image/{i} /manifest.json" ) as  f:         manifestdata = f.read()              with  open (f"image/{i} /manifest.json" ,'r' ,encoding="utf-8" ) as  f:         man_sha=f.read()         data = json.loads(man_sha)     m = hashlib.sha256()     m.update(bytes (man_sha,encoding='utf-8' ))     manifest_sha = m.hexdigest()     os.makedirs(f"registry/docker/registry/v2/repositories/{imagename} /_manifests/revisions/sha256/{manifest_sha} " )     with  open (f"registry/docker/registry/v2/repositories/{imagename} /_manifests/revisions/sha256/{manifest_sha} /link" ,"w" ) as  f:         f.write(f"sha256:{manifest_sha} " )              os.makedirs(f"registry/docker/registry/v2/repositories/{imagename} /_manifests/tags/{imagetag} /index/sha256/{manifest_sha} " )     with  open (f"registry/docker/registry/v2/repositories/{imagename} /_manifests/tags/{imagetag} /index/sha256/{manifest_sha} /link" ,"w" ) as  f:         f.write(f"sha256:{manifest_sha} " )         os.makedirs(f"registry/docker/registry/v2/repositories/{imagename} /_manifests/tags/{imagetag} /current" )     with  open (f"registry/docker/registry/v2/repositories/{imagename} /_manifests/tags/{imagetag} /current/link" ,"w" ) as  f:         f.write(f"sha256:{manifest_sha} " )                  sim_man_sha = manifest_sha[:2 ]         os.makedirs(f"registry/docker/registry/v2/blobs/sha256/{sim_man_sha} /{manifest_sha} " )         with  open (f"registry/docker/registry/v2/blobs/sha256/{sim_man_sha} /{manifest_sha} /data" ,"w" ) as  f:             f.write(man_sha)         man_digest=data['config' ]["digest" ].split(":" )[1 ]         os.makedirs(f"registry/docker/registry/v2/blobs/sha256/{man_digest[:2 ]} /{man_digest} " )         os.system(f"ln -f  image/{i} /{man_digest}  registry/docker/registry/v2/blobs/sha256/{man_digest[:2 ]} /{man_digest} /data" )         os.makedirs(f"registry/docker/registry/v2/repositories/{imagename} /_layers/sha256/{man_digest} " )         with  open (f"registry/docker/registry/v2/repositories/{imagename} /_layers/sha256/{man_digest} /link" ,"w" ) as  f:             f.write(f"sha256:{man_digest} " )         for  layer in  data['layers' ]:             print (layer)                      layerhash = layer["digest" ].split(":" )[2 ]             layerpath = f"registry/docker/registry/v2/repositories/{imagename} /_layers/sha256/{layerhash} "              sim_layerhash = layerhash[:2 ]             os.makedirs(layerpath)             with  open (f"{layerpath} /link" ,'w' ,encoding="utf-8" ) as  f:                 f.write(layer["digest" ])             os.makedirs(f"registry/docker/registry/v2/blobs/sha256/{sim_layerhash} /{layerhash} " )             os.system(f"ln -f  image/{i} /{layerhash}  registry/docker/registry/v2/blobs/sha256/{sim_layerhash} /{layerhash} /data" ) 
 
导出后文件夹格式:
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 registry/ └── docker     └── registry         └── v2             ├── blobs             │   └── sha256             │       ├── 2e             │       │   └── 2ef7f86534fdfcd45609e1f26fae69dff48828665da24023b86ce80a4efdea06             │       │       └── data             │       ├── 4f             │       │   └── 4f380adfc10f4cd34f775ae57a17d2835385efd5251d6dfe0f246b0018fb0399             │       │       └── data             │       ├── 7d             │       │   └── 7dbe7f8c80d3a2e99a0d1e07e4314dc18fecaf591563e596c1080698173d3724             │       │       └── data             │       ├── 89             │       │   └── 89a5e550c32388274bd4ced3c636fa8a3f21b1fd01e0f3b91bad4769ead317c6             │       │       └── data             │       ├── b2             │       │   └── b2109f84b5d3876f7fe664c298f91e4de086ce6d892cf6b885820e168fe6d10b             │       │       └── data             │       ├── d1             │       │   └── d1ad002da32d49eed600f7fcff543396a57a7e2c913063ac9bb68ca78219bfd1             │       │       └── data             │       ├── e4             │       │   └── e445148a2a87d1e55db8d9e3f0f554481cb2ff8bf70383ad3f34d5379c5ad984             │       │       └── data             │       └── f8             │           └── f88e263879e1903b1cdf9fe53ace2241fc3995aaa77b6524a1dcf3f9447bfd06             │               └── data             └── repositories                 └── nginx                     ├── _layers                     │   └── sha256                     │       ├── 2ef7f86534fdfcd45609e1f26fae69dff48828665da24023b86ce80a4efdea06                     │       │   └── link                     │       ├── 4f380adfc10f4cd34f775ae57a17d2835385efd5251d6dfe0f246b0018fb0399                     │       │   └── link                     │       ├── 7dbe7f8c80d3a2e99a0d1e07e4314dc18fecaf591563e596c1080698173d3724                     │       │   └── link                     │       ├── 89a5e550c32388274bd4ced3c636fa8a3f21b1fd01e0f3b91bad4769ead317c6                     │       │   └── link                     │       ├── b2109f84b5d3876f7fe664c298f91e4de086ce6d892cf6b885820e168fe6d10b                     │       │   └── link                     │       ├── e445148a2a87d1e55db8d9e3f0f554481cb2ff8bf70383ad3f34d5379c5ad984                     │       │   └── link                     │       └── f88e263879e1903b1cdf9fe53ace2241fc3995aaa77b6524a1dcf3f9447bfd06                     │           └── link                     └── _manifests                         ├── revisions                         │   └── sha256                         │       └── d1ad002da32d49eed600f7fcff543396a57a7e2c913063ac9bb68ca78219bfd1                         │           └── link                         └── tags                             └── latest                                 ├── current                                 │   └── link                                 └── index                                     └── sha256                                         └── d1ad002da32d49eed600f7fcff543396a57a7e2c913063ac9bb68ca78219bfd1                                             └── link 42 directories, 18 files 
 
拉取镜像测试 1 2 3 4 5 6 7 8 9 10 11 12 docker pull localhost:5000/nginx Using default tag: latest latest: Pulling from nginx 7dbe7f8c80d3: Pull complete  89a5e550c323: Pull complete  2ef7f86534fd: Pull complete  b2109f84b5d3: Pull complete  f88e263879e1: Pull complete  e445148a2a87: Pull complete  Digest: sha256:d1ad002da32d49eed600f7fcff543396a57a7e2c913063ac9bb68ca78219bfd1 Status: Downloaded newer image for localhost:5000/nginx:latest localhost:5000/nginx:latest