浅谈 Docker 容器与镜像

社区编辑2018-05-18 15:12


Docker 是一种开源的容器虚拟化技术,近来越来越多的互联网企业将其应用在产品链的开发过程中,以此轻松地为应用创建轻量级的、可移植的、自给自足的容器。
 
开发者编译测试通过的容器可以批量地在生产环境中进行部署,包括 VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。
 

Docker 的应用场景

 
Docker 通常用于如下场景:
 
web 应用的自动化打包和发布;
 
自动化测试和持续集成、发布;
 
在服务型环境中部署和调整数据库或其他的后台应用;
 
Docker 的优势主要体现在持续集成、版本控制、可移植性、隔离性和安全性等方面。而 docker 能够实现持续集成和版本控制以及可移植性等功能是依赖于其文件组织方式。
 
Docker 通过镜像文件来进行分发,并通过镜像仓库解决了分发问题,只要下载这个镜像,在任何装有 docker 环境的机器上,通过 docker run 就能运行起来。而每一个镜像文件都可以打上不同的 tag 从而实现了对 docker 镜像文件的版本控制。
 

镜像构建

 
如何构建 docker 镜像是所有开发者都比较关心的问题,也是使用 docker 必须掌握的能力。如下:
 
FROM centos
ADD yt.txt /root/
RUN echo “Hello World!” > /root/yt.txt
EXPOSE 80
CMD [“cat”, “/root/yt.txt”]
 

指令解释:
 
FROM 指定要 build 的镜像是基于哪个镜像 build 的
ADD 添加本地的文件到镜像中
RUN 运行的 shell 命令所做的修改都会体现在新 build 的镜像中
EXPOSE 用于声明镜像对外暴露的端口
CMD 指定启动镜像时的默认命令
 

镜像存储

 
用户对镜像构建完成后,往往需要对镜像进行保存,从而得以分发到其他机器去运行。一个镜像往往包括多层的文件系统,同时也包括镜像的原信息。
 
镜像分发有两种方式,一种通过 save 的方式保存为压缩包,然后通过 scp 等命令传输到其他机器去执行,但这种方式复杂又麻烦,往往会在传输的过程中受限于权限和网络隔离等问题导致下发复杂。另一种是通过镜像仓库这个中间存储中心来处理镜像的下发,用户可以把镜像存储在镜像仓库,然后通过相应指令下载,只要网络畅通即可。
 
镜像仓库相关指令 docker login/pull/push:
 
docker login 用于登陆授权,如登陆网易云基础服务的镜像仓库:docker login -u username -p password hub.c.163.com,其中 -u 是代表用户名,-p 代表密码,hub.c.163.com 则代表镜像仓库的地址。
 
docker push 用于镜像的推送,docker push url 即可把镜像推送到指定的镜像仓库,其中 url 中需要自定镜像仓库的地址。
 
docker pull 用于拉取镜像,通过获取镜像的 url,直接通过 docker pull url 即可拉取到镜像。
 

镜像仓库

 
1、镜像仓库默认镜像是存储在硬盘的,但是直接存储在本机会有几个问题,如限制了镜像仓库的部署方式,同时本机的磁盘空间也会有很大的压力,因为一个镜像往往就是几百 M。
 
镜像仓库为了解决这个问题,提供了 Aws,阿里 nss 等面向对象存储驱动接口,用户只需要购买相关服务即可把镜像仓库做成一个存储高可用的服务。
 
简单来说面向对象 object-file system 文件系统主要是通过分离文件的元数据和具体的文件内容,通过一个 key 来快速获取文件的系统(该系统比较复杂,后续相应的文章进行深入说明)。网易云基础服务基于自身打造的分布式存储系统提供了相应的存储接口接入镜像仓库,随着硬盘数据量越来越多,磁盘坏道带来的影响也会越来越大,为了保证用户的镜像不会损坏,网易云基础服务采用了基于三副本的方式来保证用户镜像的高可用,当然其带来的问题就是存储成倍的增加,但是硬盘价格相对低廉使得这个问题基本可以忽略掉。
 
2、在 dockerhub 上使用镜像仓库类似于 github,要想实现私有的镜像仓库必须购买,否则就是公共的镜像仓库。网易云基础服务基于用户的安全考虑提供了私有和公有两种镜像仓库,同时用户也可以把自己制作的镜像共享以便其他用户下载。同时新版的镜像仓库 V2 已经开始支持镜像仓库多级目录。
 
老的 V1 repo 规则是 hub.c.163.com/username/reponame:tag 这种方式,这种方式下不能很好地描述很多业务场景,一个用户往往来自于一个组织,同时一个项目下可能有多个服务,而每个服务又可能有多套环境。而 V2 版本的镜像仓库支持多级目录,以满足用户的个性化需求,如 hub.c.163.com/username/company/product/module/env:tag, 从而可以实现镜像仓库更好地划分,解决了老版本下只能两级目录的缺陷。

镜像构建中常遇到的问题以及解决方法

 

1、基础镜像的处理

 
如何快速地构建一个镜像出来是开发者很关心的一件事,但是构建一个镜像往往需要几个基础镜像,如上例的 centos,这个基础镜像存储在 dockerhub 的官方文件系统中,受限被墙的缘故,而且基础镜像文件较大(上百 M),往往会导致用户下载基础镜像失败。
 
网易云基础服务在 docker 实践的过程中也遇到了和用户同样的问题,为了解决上述问题,网易云基础服务采用专线的方式定期同步 dockerhub 的官方镜像,从而为用户提供快速的基础镜像下载地址,用户可以把其 From 官方的基础镜像改为网易云基础服务的镜像从而实现快速构建。
 
其中同步镜像的过程中需要定期获取官方镜像仓库的更新和变化,而官方的基础镜像仓库信息都托管在 github,通过定期获取 github 上的更新信息,然后通过代理拉取镜像和相应的描述信息,从而实现镜像仓库的同步。
 

2、用户自己构建镜像需要提供构建机器以及保证机器处于良好的网络中

 
一个业务部门的构建数量往往跟开发的构建次数有关,随着开发的大量构建往往会导致构建机器速度较慢,开发往往需要通过对某个 tag 或者某一个分支 branch 上的 commit 进行构建实现持续集成和测试。
 
这种情况下可以使用 github 或者 gitbuck 的版本控制服务,通过 hook 到代码仓库的更新从而实现实时的镜像构建。当然,如果用户的构建操作较多,则需要考虑提供多台构建机器,以任务下发的模式,下发给不同机器进行相应的镜像构建。
 
考虑到这种需求,网易云基础服务提供了持续集成的服务,用户可以将其仓库部署在 github 或者 gitbucket 等仓库,通过提供一个 dockerfile 文件,实现对用户仓库的持续构建,减少用户构建的复杂性,提高效率。