Docker系列文章---定制Docker镜像基础

来源:互联网 发布:真正的面向对象编程 编辑:程序博客网 时间:2024/06/01 20:24
                                                                                                     

本文转载自G云定制云订阅号“G云定制云”

目录:


1、Dockerfile基础语法


2、Dockerfile编写思路


3、参考文档


相比于谈及Docker架构,那么Docker镜像就显得没有那么高大上了,但作为Docker实践的一部分,Docker镜像制作的重要性,一点不比Docker架构低。因为一个业务的最终发布形式就是一个个Docker镜像,镜像中的业务稳定性,直接影响到业务的可用性。架构冗余,高可用,弹性,等等这些,对于业务可用性,连续性来说只是锦上添花而已,如果服务本身不稳定,或者因为Docker镜像做的不好导致业务不稳定,那么架构再好可用性也是得不到保证的。


所以从这个方面看,Docker镜像的重要性,也就不言而喻了。本系列针对Docker镜像,准备了至少四篇文章。


Docker本身提供了一种非常方便的工具Dockerfile,让用户能自行创建业务镜像。做运维的同学,应该都听过自动化运维工具AnsibleDockerfile就类似于Ansible中的Playbook,它们都是编排工具,将一个任务拆分成一步步具体的操作,再将其连在一起,最终达到一致的效果。如果有用过Ansible的话,用Dockerfile会好理解很多。


通过Dockerfile,我们将运行环境、程序、配置,都封装到镜像中,不论开发,测试,或者上线,都可以保证完全一样。本篇将从Dockerfile的基础语法开始介绍,进而再介绍一些Dockerfile的编写思路。


1.1  Dockerfile基础语法


   Dockerfile用于自动构建Docker镜像,将构建镜像的过程,以命令的形式存放在一个文本文件中,文件名通常就叫Dockerfile,编写完Dockerfile文件之后,可以使用以下命令开始构建Docker镜像。


Docker系列文章---定制Docker镜像基础


1.1.1   FROM

FROM指令,格式为FROM<image> FROM<image>:<tag>


每个Dockerfile的第一行,必须以FROM开头,指定创建镜像使用源镜像名称,例如:


Docker系列文章---定制Docker镜像基础


注意  Dockerfile中,关键字指令是不区分大小写的,但是习惯上还是全部大写

 

1.1.2   MAINTAINER


   MAINTAINER指令,格式为 MAINTAINER <name> ,指定维护者信息,通常可以是Dockerfile文件的创建者姓名,邮箱等信息,例如:


Docker系列文章---定制Docker镜像基础


注意  MAINTAINER不是必填指令,如果只是测试的话,可以忽略

 

1.1.3   RUN


   RUN指令,格式为 RUN <command> 或 RUN ["executable", "param1","param2"],RUN提供了两种格式,通常大多使用第一种,例如安装httpd软件包:


Docker系列文章---定制Docker镜像基础


1.1.4   ADD和COPY


ADD和COPY两个命令功能上都是往镜像内传文件,但是区别在于ADD的文件源可以是URL或者一个tar文件。


ADD指令,格式为ADD <src> <dest>

  COPY指令,格式为COPY <src> <dest>


Docker系列文章---定制Docker镜像基础


1.1.5   EXPOSE


EXPOSE指令,格式为 EXPOSE <port>[<port>...],表示在Docker容器中暴露哪些端口,可以是多个,相互之间用空格分开,例如:


Docker系列文章---定制Docker镜像基础


1.1.6   VOLUME


VOLUME指令,格式为 VOLUME ["/data"],创建一个可以从本地主机或其他容器挂载的挂载点,凡是需要本地永久化保存数据的容器镜像都需要用这个指令。如果需要设置多个挂载点的话,在[]中以“,”分隔多个,例如:         Docker系列文章---定制Docker镜像基础


创建镜像之后,启动容器

Docker系列文章---定制Docker镜像基础


1.1.7   ENV


ENV指令,格式为 ENV<key> <value> 或ENV  <key>=<value>。 指定一个环境变量,该变量可以被后续 RUN 指令使用,并在容器运行时保持。例如:  


与下面这种方式指定环境变量,效果是完全一样的,但相比之下,上面这种定义的方式更加直观一些。



1.1.8   WORKDIR


WORKDIR指令,格式为 WORKDIR /path/to/workdir,这个命令很简单,就是切换目录,为后续的 RUN 、 CMD 、 ENTRYPOINT 指令配置工作目录。举例:     Docker系列文章---定制Docker镜像基础


1.1.9   ONBUILD


ONBUILD指令,格式为 ONBUILD [INSTRUCTION],[INSTRUCTION]指的是一个基本的指令,使用ONBUILD之后,其后跟的实际指令,并不会在当前镜像创建过程中被执行,而是其被当做源镜像被使用时才会被执行。举例:              Docker系列文章---定制Docker镜像基础  
再创建一个Dockerfile,并以images:0.1为源镜像                                    
Docker系列文章---定制Docker镜像基础


1.1.10   CMD和ENTRYPOINT


   CMD和ENTRYPOINT都用于指定在容器启动时,执行的命令,但两个命令并非完全相同,以下罗列它们的异同。


Docker系列文章---定制Docker镜像基础


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系列文章---定制Docker镜像基础


以上这个表格来自Docker 官网,简单总结一下:


   A:用数组形式定义命令和参数的情况下,都是以/bin/sh -c 形式执行

   B:直接命令形式定义的情况下,都是以exec形式执行

   C:Dockerfile中同时用了CMD和ENTRYPOINT两个指令,最终CMD中定义的命令会成为ENTRYPOINT定义命令的参数



1.2   Dockerfile编写思路


1.2.1   基本的原则

Dockerfile内容尽可能精简,比如run命令,一条命令就是生产一个新的层。对于复用性很低的配置,可以通过上传脚本的方式,在启动的时候,由脚本来完成。


1.2.2   源镜像的选择


   Docker安装完成之后,默认就可以下载docker hub中提供的镜像,访问https://hub.docker.com网站,注册一个账号,然后登陆。查找你需要的镜像,比如: centos。如下图,官方提供了相应CentOS版本的镜像

Docker系列文章---定制Docker镜像基础


接着我们可以直接  docker pullcentos:centos5.11,下载centos5.11的官方镜像。使用官方镜像的原因主要两个,第一是安全,第二是体积比较小。


1.2.3   构建Base镜像


Base镜像作为之后其他镜像的基础,仅做一些最基本的配置,比如

  • 添加公司自有的yum源

  • 安装一些基础的包,如:gcc、wget、gcc、git等等

  • 安装统一程序包,比如监控的客户端程序。

  • 拷贝一些基础的脚本


通常这部分安装的内容都是能被高度复用的,避免之后重复的安装工作,同时也要注意Base镜像的大小。在应用大批量部署的时候,Docker镜像的大小,将决定业务上线的速度。

 

1.2.4   业务拆解


业务的运行,依赖于两个东西,第一是运行环境,第二是业务程序。


在使用Dockerfile创建镜像的时候,主要应对的是运行环境,在这个基础之上,进一步将业务整合进来,最终是将两者打包成一个完整的业务镜像,直接在Docker宿主机上批量部署,上线业务。


业务拆解,包括应用分拆和应用通信。比如Wordpress应用,这是一个比较典型的网站类业务,其中主要包含LAMP环境,mysql可以作为一个独立的容器运行,也可以在同一个容器中。同一个容器这种情况,要简单许多,但是无法应对高负载的情况。数据库负载高的情况下,其中一个手段就是拆表,但这需要业务代码支持。究竟如何拆,还是需要结合实际的业务,因为并不是所有业务都是满足微服务架构的,特别是早期的一些业务,相互之间耦合非常厉害,那么面对这些业务,AllInOne也是一个办法,虽然这不是Docker的强项。最好的方式是,一个业务就在一个容器中,它的发布,销毁都只和这个容器有关系。


1.2.5   单容器多服务管理


这种场景,本身Docker是不推崇的,但是在实际的应用中,却是存在的,所以对此呢,介绍一下简单的思路。还是举WordPress这个业务,如果是AllInOne的方式部署,那么这个容器里面就必须运行apache和mysql两个服务,这两个服务用什么管理呢?


常用的有Supervisor和Monit,两者都提供了WebUI,可以在里面看到有它接管的应用的状态。具体使用和注意事项,会在以后的文章中介绍。

 

 

1.3   参考文档


官方参考链接:  https://docs.docker.com/engine/reference/builder/

博客:                  http://www.tuicool.com/articles/e2YrE3j


Docker系列文章---定制Docker镜像基础

KVM云技术社区微信群加入,联系北极熊:

Docker系列文章---定制Docker镜像基础


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



查看原文:http://www.zoues.com/2016/10/18/docker%e7%b3%bb%e5%88%97%e6%96%87%e7%ab%a0-%e5%ae%9a%e5%88%b6docker%e9%95%9c%e5%83%8f%e5%9f%ba%e7%a1%80-2/
0 0