用Dockerfile构建docker image

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的更多相关文章
- 使用Dockerfile构建docker lnmp环境
一.mysql 1.创建 Dockerfile mkdir mysql # 创建一个目录存放之后的Dockerfile,目录名无所谓 cd mysql # 进入目录 vi Dockerfile # 创 ...
- Dockerfile构建jar镜像
dockerDockerfilejar包docker-compose 一.安装docker和compose 二.准备jar包 三.编写配置文件 1. Dockerfile 2. docker-comp ...
- 使用DockerFile构建运行GoWeb
安装docker # 安装一些必要的系统工具 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 # 添加软件源信息 # ...
- 使用Dockerfile构建镜像-Docker for Web Developers(5)
1.理解Dockerfile语法 语法命令 命令功能 举例 FROM 所有的dockerfile都必须以FROM命令指定镜像基于哪个基础镜像来制作 FROM ubuntu:14:04 MAINTAIN ...
- Docker 使用 Dockerfile 构建自己的镜像
可以使用Dockerfile的配置文件方式进行构建自己的镜像 下面利用docker构建一个Caddy web服务器 构建脚本 Dockerfile有自己的命令,下面使用了一些比较常用的命令,更多的Do ...
- docker(四) 使用Dockerfile构建镜像
下面以一个例子来演示构建镜像的过程. #在/tmp目录下演示 cd tmp mkdir build-redis-image 1.创建Dockerfile文件 vim Dockerfile 并写入如下内 ...
- Docker容器学习梳理 - Dockerfile构建镜像
在Docker的运用中,从下载镜像,启动容器,在容器中输入命令来运行程序,这些命令都是手工一条条往里输入的,无法重复利用,而且效率很低.所以就需要一 种文件或脚本,我们把想执行的操作以命令的方式写入其 ...
- docker:Dockerfile构建LNMP平台
docker:Dockerfile构建LNMP平台 1.dockerfile介绍 Dockerfile是Docker用来构建镜像的文本文件,包含自定义的指令和格式.可以通过docker buil ...
- Docker 使用Dockerfile构建redis镜像
Dockerfile实现: FROM centos: MAINTAINER hongdada "hongdaqi159505@gmail.com" WORKDIR /home RU ...
随机推荐
- 为Mac自带的Apache配置PHP和虚拟机
操作系统:os x 10.11.2 1.启动apache 打开终端(terminal),输入命令:sudo apachectl -k start ; 在浏览器地址栏中输入:http://localho ...
- Onthink学习随笔
-------------------------------------(写代码不孤独_小小代) 用Onthink写了一个网站暂时还没上线功能略显不全没,完全没有发挥出应有的强大拓展之处,各种地方略 ...
- 帝国cms7.0整合百度编辑器ueditor教程
帝国cms7.0整合百度编辑器ueditor教程开始 1.根据自己使用的帝国cms版本编码下载对应的ueditor版本 下载地址 http://ueditor.baidu.com/website/do ...
- python3.4控制用户输入与输出
一.输入 1.函数格式:input() 2.函数功能:接受一个标准输入数据,返回string类型.ctrl+z结束输入. 3.实例: 默认input():等待一个任意字符的输入 str=input(‘ ...
- 函数:灵活即强大 - 零基础入门学习Python018
函数:灵活即强大 让编程改变世界 Change the world by program 上节课我们基本介绍了Python函数的用法,非常简单.这节课我们主要针对函数的参数和返回值进一步深入学习.学习 ...
- 根据identifier从StoryBoard中获取对象,UIButton的图片文件位置
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- CC2530定时器3的输入捕获中断
CC2530定时器3的输入捕获中断 使用的是tim3的通道1的输入捕获P1_7口.//GPIO配置成复用功能,同时设置P1_7为输入.void irCaptureGpioInit(void){ P1S ...
- 10个经典的Android开源项目(附源码包)
最近在抽空学习Android系统开发,对Android学习也比较感兴趣,刚开始学就试着在网上找几个项目源码研究看下,以下就将找到的Android项目源码列出,希望对正在或准备学习Android系统开发 ...
- HDU 4276 The Ghost Blows Light(树形)
题意:给出一棵n个节点的树,起点1,终点n,相连的两个节点之间有距离,每个节点有个价值,给出一个时间T.问从1到达n在给定时间T内取得的最大价值? 思路:先从1走到n,如果总的时间不够走完,直接退出, ...
- java设计模式--结构型模式--外观模式
外观模式 概述 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 适用性 1.当你要为一个复杂子系统提供一个简单接口时.子系统往往因为不 ...