一.为何docker会被广泛使用?
其实docker就是虚拟化技术的应用。那说到虚拟化技术,大家是不是会想起大名鼎鼎的vmware?但是,vmware也没现在docker这么火吧。虚拟化技术,本质上还是使用了linux内核提供的控制分组(controll group)能力和命名空间(namespace)能力。cgroup用来对网络资源,文件系统,进程环境进行分配隔离;namesapce用来对cpu,内存这些资源做分配隔离。所以,每台宿主机可以搞多台虚拟机。
那docker和之前的虚拟化手段又有何区别呢?之前的虚拟化,是在操作系统上增加了两层软件的,分别是模拟层和管理层,这样势必会导致资源占用。而在linux平台,docker是直接调用os的api的,这样资源占用也就更少。
docker是否仅仅因为是因为上述那个区别而火的呢?其实也不是。一个技术是否受欢迎,其实关键点在于其是否解决了实际需求,实际痛点。docker做的最重要的事情是把一系列已经出现的技术手段给组成了一套解决方案,让使用成本极大降低,带来了极大的效率提升。docker做的事情,其实和java所做事情有一个相同点,他们都做到了一次xx,可移植到任何平台运行。它改变了整个交付流程,交付的内容变成了一个镜像,避免了工作中常遇到的一个问题:代码在测试机上跑的没问题啊,但是在生产环境就扑街了。
二.docker组成
docker从其解决方案角度来说,由四个核心部分组成:docker服务,镜像,registry(镜像仓库存储服务),docker容器。和其图标进行映照,docker服务就是鲸船,docker容器就是一个个集装箱,镜像就像是集装箱内的货物,而registry则是码头,镜像仓库则是码头的仓储地。
三.docker使用
docker的安装
docker对安装环境是有一定要求的,比如linux内核版本最好3.8及以上(官方支持,低版本可能有兼容性问题),存储驱动系统需要满足要求,需要是x64架构,cgroup和namespace没有被主动关闭。这些需要同学们在安装前自行检查。
一个成熟的产品,正常会提供3中安装方式:1.二进制的压缩包。2.不同系统的包管理仓库下载安装,如用rmp/deb。3. 到官网拉安装脚本执行。推荐使用软件仓促上的包直接安装,具体的安装教程一大把,同学们自行去查吧。
这里列举一些docker服务常用命令吧。systemctl start docker(启动docker服务); systemctl start docker(启动docker服务);service docker status或者docker info(用来查询docker服务的状态);docker ps -a(查看所有容器的状态,去掉-a则是查看启动容器的状态);docker rm(用来删除容器);docker rmi(用来删除镜像);docker start(启动容器);docker stop(关闭容器);docker images(查看镜像);
一个成熟的产品/中间件,一般会提供3中使用方式:1.命令行方式使用;2.api方式使用;3.sdk方式使用。docker服务,大家可能会接触到命令行或者api方式使用。之后的介绍都按命令行进行。
构建镜像
构建镜像有两种方式,一种是命令行commit;另一种方式就是通过撰写Dockerfile然后执行docker build。一般情况下,第二种方式应用的多(灵活)。
第二种方式,核心其实就是用docker的DSL(作用于特定领域的语言)写一个Dockerfile。Dockerfile所在的目录称为"构建上下文"或者“上下文”。 在执行docker build的过程中,构建上下文内的内容都会被上传到docker服务的守护进程中,当然,不想被守护进程触达的目录可以在.dockerignore文件内记录(类似.gitignore) 。
Dockerfile的DSL的语法,命令均需要大写,每一行之间不需要分隔符。这里介绍一些常用的命令:FROM(从基础镜像当中构建新镜像);RUN (执行具体的命令,有两种方式,一种是直接写命令行(默认命令前会加上/bin/sh -c),另外一种是exec格式,即[“命令”,"选项","参数"...]格式,推荐使用第二种);ENV(设置环境变量); COPY(直接从构建上下文复制特定内容到容器内指定目录); ADD(从构建上下文复制特定内容到容器内指定目录,如果是压缩文件,该命令还会解压提取);MAINTAINER(声明作者信息,是一个广告的好地方);EXPOSE(指定容器对外暴露的端口号,如果没指定宿主机器的端口号,则会在宿主机的49152~65535内的端口随机选一个进行绑定);ENTRYPOINT(容器启动后要执行的命令,也建议使用exec格式,多个ENTRYPOINT会进行覆盖,只执行最后一个);CMD(容器启动后默认要执行的命令,会被命令行替代,也建议使用exec格式,多个ENTRYPOINT会进行覆盖,只执行最后一个);WORKDIR(设置工作目录,后面的命令都在该目录下执行);VOLUMN(设置容器挂载卷[其实就是宿主机的某个目录],也建议用exec格式,该模式避过了docker的联合文件系统,可以直接操作宿主机卷目录);USER(指定之后的命令由哪个用户执行);
在写完Dockerfile后执行docker build。需要特殊说明的是,docker采用的是联合文件系统,其采用了写时复制技术。没执行一行Dockerfile的命令行,都会生成一个镜像,之后的镜像都是在之前的基础上进行叠加。如果在其中某一个步骤出错了,那可执行的镜像就是在出错前的哪一步。修改Dockerfile之后,重新build,默认会直接使用之前的缓存,然后继续build。要关闭可以添加--no-cache参数。
在执行完build指令后,在aufs目录下,可以看见有一些记录变化的文件和一些文件夹(如果新增了内容),这些文件夹就是镜像的实体了。
上传镜像
上传镜像到reigstry即可以实现共享。如果是想要镜像在小范围内分享,则需要使用dockerhub的私有registry功能(付费)或者搭建一套私有的registry。harbor是目前比较流行的开源方案。要分享镜像的话,其实还可以通过Dockerfile分享。
启动容器
有了镜像,就可以启动容器了。命令格式如下:
docker run --name 别名 -d(后台运行) 镜像名称 要执行的命令
注意,容器需要有进程是前台进程,一般情况下,服务进程都是后台进程(也就是守护进程),这种情况下,容器会自动退出的。所以,该模式(-d)下需要命令行让主线成在前台挂着,这样容器才能一直跑着。或者也可以让服务进程挂在前台(如nginix的daemon off打开)。
docker容器内,可以跑多个服务的进程的。但是docker建议一个容器跑一个服务就够了。容器内也可以套容器,但是这种玩法比较少人用。在容器启动的时候,如果是有控制台输出日志,可以用docker log命令查看。
结合CI/CD工具使用
目前比较流行的持续集成(CI)/持续部署(CD)服务平台是Jekins。可以利用jekins和代码仓库一起使用,当有代码提交的时候,就通过web hook触发代码拉取,代码扫描,镜像构建,容器启动,单元测试,镜像上传镜像部署这些工作。(其实就是写脚本)
三.容器编排
docker仅仅解决了生产当中的一部分问题。服务间的协作,容器的管理这部分能力是需要其他服务进行支持的,也就是需要容器编排能力。目前比较流行的容器编排平台是k8s。
网友评论