dockerfile是为快速构建docker image而设计的,当你使用docker build 命令的时候,docker 会读取当前目录下的命名为Dockerfile(首字母大写)的纯文本文件并执行里面的指令构建出一个docker image。

  而另一种构建docker iamge 的方法是pull一些基础镜像下来启动成容器,然后进入容器内安装各种需要的程序以及配置好需要的环境,最后commit成一个镜像。但是相比之 Dockerfile的方法会更加自动化,更加方便快捷,而且功能也更强大。(Docker build方法底层里也是在基础镜像下启动容器然后commit的,但是这些不需要我们手动去commit以及rm,都是自动化的。)

======(注:以下大部分内容均参考自官方文档)

首先,是关于构建docker image的一些优化建议

我们希望构建出的image对应的容器应该是可以在服务群中暂停(解耦性)并且快速替换,这要求容器可以在极短的时间内完成启动并配置运行起来。

优化手段:

 使用.dockerignore文件 .

dockerignore文件的设计是为了在docker build的过程中排除不需要用到的文件以及目录,目的是为了docker build这个过程可以尽可能地快速高效以及构建出来的image没有多余的“垃圾”。

不要安装不必要的程序包

我们希望构建出来的image尽可以的轻小、依赖性小以及构建过程尽可能地快。这就需要你在构建的时候不要安装不必要的程序,例如,一个存储数据的数据库容器不需要安装文本编辑器。

单一容器只运行单一的服务

大部分情况下一个容器只建议运行一个服务,这样的好处在于:减小耦合度、利于容器复用以及提高容器的横向可扩展性。如果服务之间是需要联系的,就应该把服务放在不现的容器内,然后用container linking来关联这些容器以达到目的。

最小化镜像层数(layers)

关于镜像层数(layers)的概念请参考:docker镜像与容器存储结构分析http://www.programfish.com/blog/?p=9

把镜像层数减到最少可能加快容器的启动速度,但是这里也要权衡另一个问题:dockerfile的可读性。你可以把一个dockerfile写得很 复杂以达到构建出最小层数的镜像,但同时你的dockerfile可读性也降低了。所以我们要在镜像层数和dockerfile可读性之间做出让步与妥 协。

对多行参数进行排序(一般按字母顺序)

对参数排序可以方便以后修改更新这些参数以及确保不会重复重复输入了某些参数。例如官方的一个例子是:

RUN apt-get update && apt-get install -y \

bzr \

cvs \

git \

mercurial \

Subversion

把要安装的程序包名按字母排序可以方便管理。

构建的时候使用cache

Docker build期间docker会按你提供的dockerfile文件里面的指令按顺序逐条执行。Docker在首先检查每一条指令的时候会去cache里搜 查是否有执行过这条指令并且可以复用的镜像,如果没有再去构造一个新的镜像。这是默认的情况,如果你指定不要这个过程可以在docker build里用如下参数:

–no-cache=true

Docker查找cache的过程:

首先在cache里从base image(详见:docker镜像与容器存储结构分析http://www.programfish.com/blog/?p=9)起,docker会比较dockerfile里的下一条指令与这个base image的每一个子镜像的构建指令是否匹配,如果匹配则命中,否则cache标为无效。

对于一般指令这样简单比较就足够了,但是有些精确的指令要求更详细精确的比较或者说明。 (add和copy指令见官方文档https://docs.docker.com/articles/dockerfile_best-practices/) 一旦cache在dockerifle里某一条指令检查时被标为无效,执行这个dockerfile以后的指令就不再使用cache。

Dockerfile主要指令简介:

FROM   

dockerfile里的第一条指令,后面跟有效的镜像名(如果该镜像你的本地仓库没有则会从远程仓库Pull取)。后面的指令在些镜像中执行。

FROM <image>:<tag>

MAINTAINER

MAINTAINER <name> 作者信息

RUN    

后跟要执行的linux命令,每一条RUN指令(可能会有多条linux命令)会在当前容器最上面的可读写层执行并且提交成一个新的镜像层,接下来的指令会在这个新的镜像层里执行。

RUN <command> (the command is run in a shell – /bin/sh -c – shell form)

RUN ["executable", "param1", "param2"] (exec form)

注意下面的情况:  

不要在一条RUN指令里单一使用apt-get update命令,这样可能会导致以后的apt-get install 安装出错。

避免使用RUN apt-get upgrade 或者dist-upgrade,这样有些重要的软件包可能更新失败,如果你确实想要更新某个包A,使用apt-get install install  -y A 。这样会自动更新这个软件包。

更多请参考官方文档。

CMD

CMD指令指定你制作出来的镜像在启动成容器时运行命令的默认的参数。

CMD有三种写法:

CMD ["executable","param1","param2"] (exec form, this is the preferred form)

CMD ["param1","param2"] (as default parameters to ENTRYPOINT)

CMD command param1 param2 (shell form)

第一种是可执行文件加参数,第二种是作为ENTRYPOINT的参数,第三种是作为”/bin/sh -c”的参数。

这里CMD与ENTRYPOINT的区别强烈推荐你去看 论docker CMD与ENTRYPOINT的大区别 http://www.cnblogs.com/programfish/p/4101884.html 这篇文章。看完你就懂了。

ENTRYPOINT

ENTRYPOINT字面意思指定容器的进入点。可以把你的容器制作成类似可执行文件的用法。这个指令会覆盖它前面的CMD指令,而多个 ENTRYPOINT指令只有最后一个生效(后面覆盖前面)。同时你也可以在在启动container 的时候指定–entrypoint参数来覆盖dockerfile里的ENTRYPOINT。详见官方文档。

例如我用了这样的指令制作镜像名叫echotest:

ENTRYPOINT ["/bin/echo"]

然后之后这样运行:

docker  run  -it  echotest  “this is a echo”

实际上是平时这样的命令:

docker  run  -it  echotest  /bin/echo  “this is a echo”

这样你应该明白了吧。 这样一个容器的行为就很类似一个可执行文件了。 这里CMD与ENTRYPOINT的区别强烈推荐你去看 论docker CMD与ENTRYPOINT的大区别 http://www.cnblogs.com/programfish/p/4101884.html 这篇文章。看完你就懂了。
EXPOSE

EXPOSE指定容器对外暴露的端口号。

ENV

指定环境变量的值,例如你要确保CMD[“nginx”]能成功启动,你应该用ENV PATH /usr/local/nginx/bin:$PATH设定环境变量。另外你可以设定另外一些变量用于RUN命令里以便于dockerfile文件的维护:

ENV PG_MAJOR 9.3

ENV PG_VERSION 9.3.4

RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …

ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

这样多次出现版本号就可以通过一个变量来管理方便维护。

VOLUME   

VOLUME ["path"] 创建指定的挂载点。

WORKDIR   

进入指定目录工作。

其它指令详情见官方文档:https://docs.docker.com/reference/builder/

这里引用官方的一个dockerfile例子:

# Nginx

#

# VERSION               0.0.1

FROM      ubuntu

MAINTAINER  Victor  Vieux  <victor@docker.com>

RUN  apt-get  update  &&  apt-get install -y  inotify-tools  nginx  apache2  openssh-server

# Firefox over VNC

#

# VERSION               0.3

FROM  ubuntu

# Install  vnc,  xvfb  in  order  to  create  a  ‘fake’  display  and  firefox

RUN  apt-get  update  &&  apt-get  install  -y  x11vnc  xvfb  firefox

RUN  mkdir  ~/.vnc

# Setup  a  password

RUN  x11vnc  -storepasswd  1234  ~/.vnc/passwd

# Autostart  firefox  (might  not  be  the  best  way,  but  it  does  the  trick)

RUN  bash  -c  ‘echo  “firefox”  >>  /.bashrc ‘

EXPOSE  5900

CMD    ["x11vnc",  "-forever" , "-usepw",  "-create" ]

# Multiple  images  example

#

#VERSION               0.1

FROM  ubuntu

RUN  echo  foo  >  bar

# Will  output  something  like ===> 907ad6c2736f

FROM ubuntu

RUN  echo  moo > oink

# Will  output  something  like ===> 695d7793cbe4

# You᾿ll  now  have  two  images, 907ad6c2736f with /bar, and 695d7793cbe4 with

# /oink.

#号为注释符,这里一个dockerfile构建4个镜像。

写好Dockerfile文件后就可以在该目录下运行docker build . 命令了(可以用 -t 参数指定tag)。

欢迎访问本人网站:http://www.programfish.com

LinuxCoder 社区: http://linuxcoder.org

注意:转载请注明 “作者:广州Linux爱好者+云计算 刁金明”

 

用Dockerfile构建docker image的更多相关文章

  1. 使用Dockerfile构建docker lnmp环境

    一.mysql 1.创建 Dockerfile mkdir mysql # 创建一个目录存放之后的Dockerfile,目录名无所谓 cd mysql # 进入目录 vi Dockerfile # 创 ...

  2. Dockerfile构建jar镜像

    dockerDockerfilejar包docker-compose 一.安装docker和compose 二.准备jar包 三.编写配置文件 1. Dockerfile 2. docker-comp ...

  3. 使用DockerFile构建运行GoWeb

    安装docker # 安装一些必要的系统工具 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 # 添加软件源信息 # ...

  4. 使用Dockerfile构建镜像-Docker for Web Developers(5)

    1.理解Dockerfile语法 语法命令 命令功能 举例 FROM 所有的dockerfile都必须以FROM命令指定镜像基于哪个基础镜像来制作 FROM ubuntu:14:04 MAINTAIN ...

  5. Docker 使用 Dockerfile 构建自己的镜像

    可以使用Dockerfile的配置文件方式进行构建自己的镜像 下面利用docker构建一个Caddy web服务器 构建脚本 Dockerfile有自己的命令,下面使用了一些比较常用的命令,更多的Do ...

  6. docker(四) 使用Dockerfile构建镜像

    下面以一个例子来演示构建镜像的过程. #在/tmp目录下演示 cd tmp mkdir build-redis-image 1.创建Dockerfile文件 vim Dockerfile 并写入如下内 ...

  7. Docker容器学习梳理 - Dockerfile构建镜像

    在Docker的运用中,从下载镜像,启动容器,在容器中输入命令来运行程序,这些命令都是手工一条条往里输入的,无法重复利用,而且效率很低.所以就需要一 种文件或脚本,我们把想执行的操作以命令的方式写入其 ...

  8. docker:Dockerfile构建LNMP平台

    docker:Dockerfile构建LNMP平台   1.dockerfile介绍  Dockerfile是Docker用来构建镜像的文本文件,包含自定义的指令和格式.可以通过docker buil ...

  9. Docker 使用Dockerfile构建redis镜像

    Dockerfile实现: FROM centos: MAINTAINER hongdada "hongdaqi159505@gmail.com" WORKDIR /home RU ...

随机推荐

  1. python——lambda

    一lambda函数基础 1.lambda函数为匿名函数,即没有具体的函数名,而def函数创建的函数有函数名. >>> def foo(): return 'test' #命名为foo ...

  2. 使用pip install 或者easy_install安装Python的各种包出现cc failed with exit status 1

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  3. Silverlight js html 相互调用

    1.sl调用js 比如我们在页面中定义一个js函数: <script type="text/javascript">        function fnTest(ms ...

  4. AFNetworking 使用方法(2.0)

    AFNetworking 使用方法(2.0) 分类: IOS2014-11-12 09:17 2018人阅读 评论(0) 收藏 举报   目录(?)[+]   本文介绍的是AFNetworking-2 ...

  5. CoreData (三)备

    NSFetchedResultsController 什么是NSFetchedResultsController NSFetchedResultsController是一个让人爱恨交加的一个类.如果使 ...

  6. REDIS主从配置及切换

    最近公司项目也用上了.但有个点没有弄很明白. requirepass只是给CLIENT认证用的,还是同时给从REDIS认证用的?(masterauth) 一般的思路是主服务器不开AOF,从服务器打开A ...

  7. LeetCode_Spiral Matrix

    Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...

  8. keil 中用函数指针调用函数的参数限制

    NSIC中,通过函数指针调用的函数的参数的个数没有限制,但是KeilC对此有限制,至多3个参数.因为,KeilC编译时,无法通过函数指针找到该函数的局部数据段,也就无法通过局部数据段传递参数,只能通过 ...

  9. 《Programming WPF》翻译 第5章 1.不使用样式

    原文:<Programming WPF>翻译 第5章 1.不使用样式 作为一个样式如何使其在WPF使用的例子,,让我们看一下TTT简单的实现,如示例5-1. 示例5-1 <!-- W ...

  10. spring框架源码编译

    程序猿小菜一枚,最近从github上面下载下来一份spring各个项目的源码一份,但是弄了很长时间,因为网速和(fanqiang)的速度,希望大家不要再为这种无谓的时间花费时间,简单来说github上 ...