目录:
1、Dockerfile基础语法
2、Dockerfile编写思路
3、参考文档
相比于谈及Docker架构,那么Docker镜像就显得没有那么高大上了,但作为Docker实践的一部分,Docker镜像制作的重要性,一点不比Docker架构低。因为一个业务的最终发布形式就是一个个Docker镜像,镜像中的业务稳定性,直接影响到业务的可用性。架构冗余,高可用,弹性,等等这些,对于业务可用性,连续性来说只是锦上添花而已,如果服务本身不稳定,或者因为Docker镜像做的不好导致业务不稳定,那么架构再好可用性也是得不到保证的。
所以从这个方面看,Docker镜像的重要性,也就不言而喻了。本系列针对Docker镜像,准备了至少四篇文章。
Docker本身提供了一种非常方便的工具Dockerfile,让用户能自行创建业务镜像。做运维的同学,应该都听过自动化运维工具Ansible,Dockerfile就类似于Ansible中的Playbook,它们都是编排工具,将一个任务拆分成一步步具体的操作,再将其连在一起,最终达到一致的效果。如果有用过Ansible的话,用Dockerfile会好理解很多。
通过Dockerfile,我们将运行环境、程序、配置,都封装到镜像中,不论开发,测试,或者上线,都可以保证完全一样。本篇将从Dockerfile的基础语法开始介绍,进而再介绍一些Dockerfile的编写思路。
Dockerfile用于自动构建Docker镜像,将构建镜像的过程,以命令的形式存放在一个文本文件中,文件名通常就叫Dockerfile,编写完Dockerfile文件之后,可以使用以下命令开始构建Docker镜像。
FROM指令,格式为FROM
每个Dockerfile的第一行,必须以FROM开头,指定创建镜像使用源镜像名称,例如:
注意 Dockerfile中,关键字指令是不区分大小写的,但是习惯上还是全部大写
MAINTAINER指令,格式为 MAINTAINER
注意 MAINTAINER不是必填指令,如果只是测试的话,可以忽略
RUN指令,格式为 RUN
ADD和COPY两个命令功能上都是往镜像内传文件,但是区别在于ADD的文件源可以是URL或者一个tar文件。
ADD指令,格式为ADD
COPY指令,格式为COPY
EXPOSE指令,格式为 EXPOSE
VOLUME指令,格式为 VOLUME ["/data"],创建一个可以从本地主机或其他容器挂载的挂载点,凡是需要本地永久化保存数据的容器镜像都需要用这个指令。如果需要设置多个挂载点的话,在[]中以“,”分隔多个,例如:
创建镜像之后,启动容器
ENV指令,格式为 ENV
与下面这种方式指定环境变量,效果是完全一样的,但相比之下,上面这种定义的方式更加直观一些。
WORKDIR指令,格式为 WORKDIR /path/to/workdir,这个命令很简单,就是切换目录,为后续的 RUN 、 CMD 、 ENTRYPOINT 指令配置工作目录。举例:
ONBUILD指令,格式为 ONBUILD [INSTRUCTION],[INSTRUCTION]指的是一个基本的指令,使用ONBUILD之后,其后跟的实际指令,并不会在当前镜像创建过程中被执行,而是其被当做源镜像被使用时才会被执行。举例:
再创建一个Dockerfile,并以images:0.1为源镜像
CMD和ENTRYPOINT都用于指定在容器启动时,执行的命令,但两个命令并非完全相同,以下罗列它们的异同。
ENTRYPOINT指令,格式为ENTRYPOINT["executable", "param1", "param2"],此格式使用exec 形式执行命令, 优选,或者ENTRYPOINT command param1param2,此格式使用 shell形式执行命令
CMD指令,格式为CMD ["executable","param1", "param2"],此格式使用exec 形式执行命令, 优选,或者CMD command param1 param2,此格式使用 shell形式执行命令,或者CMD ["param1","param2"],此处定义将作为ENTRYPOINT的参数。
以下再介绍一下,如果在Dockerfile中既有CMD指令又有ENTRYPOINT指令时,具体的执行情况。
以上这个表格来自Docker 官网,简单总结一下:
A:用数组形式定义命令和参数的情况下,都是以/bin/sh -c 形式执行
B:直接命令形式定义的情况下,都是以exec形式执行
C:Dockerfile中同时用了CMD和ENTRYPOINT两个指令,最终CMD中定义的命令会成为ENTRYPOINT定义命令的参数
Dockerfile内容尽可能精简,比如run命令,一条命令就是生产一个新的层。对于复用性很低的配置,可以通过上传脚本的方式,在启动的时候,由脚本来完成。
Docker安装完成之后,默认就可以下载docker hub中提供的镜像,访问https://hub.docker.com网站,注册一个账号,然后登陆。查找你需要的镜像,比如: centos。如下图,官方提供了相应CentOS版本的镜像
接着我们可以直接 docker pullcentos:centos5.11,下载centos5.11的官方镜像。使用官方镜像的原因主要两个,第一是安全,第二是体积比较小。
Base镜像作为之后其他镜像的基础,仅做一些最基本的配置,比如
添加公司自有的yum源
安装一些基础的包,如:gcc、wget、gcc、git等等
安装统一程序包,比如监控的客户端程序。
拷贝一些基础的脚本
通常这部分安装的内容都是能被高度复用的,避免之后重复的安装工作,同时也要注意Base镜像的大小。在应用大批量部署的时候,Docker镜像的大小,将决定业务上线的速度。
业务的运行,依赖于两个东西,第一是运行环境,第二是业务程序。
在使用Dockerfile创建镜像的时候,主要应对的是运行环境,在这个基础之上,进一步将业务整合进来,最终是将两者打包成一个完整的业务镜像,直接在Docker宿主机上批量部署,上线业务。
业务拆解,包括应用分拆和应用通信。比如Wordpress应用,这是一个比较典型的网站类业务,其中主要包含LAMP环境,mysql可以作为一个独立的容器运行,也可以在同一个容器中。同一个容器这种情况,要简单许多,但是无法应对高负载的情况。数据库负载高的情况下,其中一个手段就是拆表,但这需要业务代码支持。究竟如何拆,还是需要结合实际的业务,因为并不是所有业务都是满足微服务架构的,特别是早期的一些业务,相互之间耦合非常厉害,那么面对这些业务,AllInOne也是一个办法,虽然这不是Docker的强项。最好的方式是,一个业务就在一个容器中,它的发布,销毁都只和这个容器有关系。
这种场景,本身Docker是不推崇的,但是在实际的应用中,却是存在的,所以对此呢,介绍一下简单的思路。还是举WordPress这个业务,如果是AllInOne的方式部署,那么这个容器里面就必须运行apache和mysql两个服务,这两个服务用什么管理呢?
常用的有Supervisor和Monit,两者都提供了WebUI,可以在里面看到有它接管的应用的状态。具体使用和注意事项,会在以后的文章中介绍。
博客: http://www.tuicool.com/articles/e2YrE3j
KVM云技术社区微信群加入,联系北极熊:
KVM云技术社区QQ群,99.99%纯技术交流气氛
QQ 1群:434720759(已满)
QQ 2群:131961942,加入密码大写KVM
1000人VMWare技术交流群:494084329,加入密码小写vm
OpenNebula QQ群:495571573 加入密码Nebula
2000人OpenStack开发纯技术群: 334605713 加入密码nova
Cloudstack纯技术交流群:515249455密码cs
2000人桌面云行业讨论: 484979056 加入密码大写VDI
2000人超融合行业讨论群:65779632 加入密码大写HC
2000人云技术招聘求职群: 279875515 加入密码hr