Docker Commit 小技巧
问题
公司需要给外部客户提供私有化的布署包,我们使用Registry来存放我们使用的docker镜像。我们的方案是先把Registry以容器的形式起来,然后将需要的docker镜像push到Registry中,然后使用docker commit将这个容器打包成新的docker镜像,然后压缩起来等待部署的时候使用。但是实际情况是,Registry容器起来后,没有任何docker镜像,重复执行docker commit仍然失败。
分析
首先是一顿谷歌,大概得到的原因就是:当容器出现挂载(Mount)时,docker commit是只会保留容器的数据,不会保留任何挂载在宿主机的数据。
然后是检查Registry容器的情况,主要就是查看是否有挂载的数据(找到Mounts关键词)
"Mounts": [
{
"Type": "volume",
"Name": "0c11b0bd97ae2d67b5a28b4e0e98a325b4ef731f913278b468c7ca044a995ebb",
"Source": "/var/lib/docker/volumes/0c11b0bd97ae2d67b5a28b4e0e98a325b4ef731f913278b468c7ca044a995ebb/_data",
"Destination": "/var/lib/registry",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
看到这个就说明你找到原因了,Registery是把docker镜像是存在/var/lib/registry路径下,所以当你把docker镜像push到Registry后,数据就会存储到/var/lib/registry路径下,但这个路径是挂载到宿主机,所以这个数据实际上就是存储到宿主机。那么你commit的时候,这部分数据就不会保存到新的镜像中。
但是问题还没有结束,我在启动Registery的时候并没有挂载,但是怎么会出现挂载的情况,有点想不明白,首先能想到的方法是检查Registery的Dockerfile。
#Build a minimal distribution container
FROMalpine:3.11
RUNset -ex \
&& apk add --no-cache ca-certificates
COPY./registry /bin/registry
COPY./config-example.yml /etc/docker/registry/config.yml
VOLUME["/var/lib/registry"]
EXPOSE5000
COPYdocker-entrypoint.sh /entrypoint.sh
ENTRYPOINT["/entrypoint.sh"]
CMD["/etc/docker/registry/config.yml"]
Dockerfile如上,检查一圈下来,VOLUME["/var/lib/registry"] 这个是个问题 详细可以查看 VOLUME 也就是说使用这个VOLUME后,容器起来后会自动挂载到宿主机,这也就是本次问题的根本原因。
解决方案
删除 VOLUME["/var/lib/registry"] 即可。使用这个VOLUME其实是为了保护数据,如果你启动容器后,容器出现问题需要删除容器的话,如果你的数据是挂载在宿主机上,那你这部分数据是有保障的,即使容器出问题,数据还在可以恢复。