Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像,本小结首先介绍Dockerfile典型的基本结构和它支持的众多指令,并具体讲解通过这些指令来编写定制镜像的Dockerfile,以及如何生成镜像.最后介绍使用Dockerfile的一些最佳实践经验.

DockerFile基本结构

Dockerfile由一行行命令语句组成,并且支持以#开头的注释行,一般而言,Dockerfile分为四部分.基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令.例如下面的一个小例子.

# This Dockerfile uses the ubuntu image

FROM ubuntu:lastest
# Maintainer: docker_user <docker_user at email.com> (@docker_user)
MAINTAINER docker_user docker_user@email.com
# Commands to update the image
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
# Commands when creating a new container
CMD /usr/sbin/nginx

其中,一开始必须指明所基于的镜像名称,接下来一般是说明维护者信息.后面则是镜像操作指令,例如RUN指令,RUN指令将对镜像执行跟随的命令.每运行一条RUN指令,镜像就添加新的一层,并提交.最后是CMD指令,用来指定运行容器时的操作命令.

实例1:debian:latest基础镜像基础上安装Nginx环境,从而创建一个新的nginx镜像.

FROM debian:latest
MAINTAINER NGINX Docker Maintainers "docker-maint@nginx.com"
ENV NGINX_VERSION 1.10.1-1~jessie
RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC64107
9A6ABABF5BD827BD9BF62 \
&& echo "deb http://nginx.org/packages/debian/ jessie nginx" >> /etc/
apt/sources.list \
&& apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y \
ca-certificates \
nginx=${NGINX_VERSION} \
nginx-module-xslt \
nginx-module-geoip \
nginx-module-image-filter \
nginx-module-perl \
nginx-module-njs \
gettext-base \
&& rm -rf /var/lib/apt/lists/*
# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]

实例2: 基于buildpack-deps:latest基础镜像,安装Golang相关环境,制作一个GO语言的运行环境镜像.

FROM buildpack-deps:lastest
# gcc for cgo
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
gcc \
libc6-dev \
make \
&& rm -rf /var/lib/apt/lists/*
ENV GOLANG_VERSION 1.6.3
ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 cdde5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd
7561275a87aeb
RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz \
&& echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - \
&& tar -C /usr/local -xzf golang.tar.gz \
&& rm golang.tar.gz
ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
WORKDIR $GOPATH
COPY go-wrapper /usr/local/bin/

## DockerFile命令详解

指令的一般格式为INSTRUCTION arguments指令包括FROM、MAINTAINER、RUN等,参见下表.

指 令 指 令 说 明
FROM 创建镜像的基础镜像
MAINTAINER 维护者信息(说明)
RUN 运行命令,安装软件用
CMD 启动容器时默认执行的命令
LABEL 指生成镜像的元数据标签信息
EXPOSE 声明镜像内服务所监听的端口
ENV 声明环境变量
ADD 复制指令,将拷贝到容器中的
COPY(推荐) 复制指令,将拷贝到容器中的
ENTRYPOINT 指定镜像的默认入口
VOLUME 创建数据卷挂载点
USER 指定运行容器时的用户名或UID
WORKDIR 配置工作目录
ARG 指定镜像内使用的参数
ONBUILD 配置当所创建镜像作为其他镜像基础时,所执行的命令
STOPSIGNAL 容器退出的信号值
HEALTHCHECK 如何进行健康检查
SHELL 指定使用SHELL时的默认shell类型

接下来,我将详细介绍几个常用命令的参数的详细说明信息.

FROM:(指定基础镜像的名称)

构建指令,必须指定且需要在Dockerfile其他指令的前面.后续的指令都依赖于该指令指定的image,FROM指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库.

example:
FROM centos:latest
FROM ubuntu:14.04

MAINTAINER:(指定镜像创建者信息)

构建指令,用于将image的制作者相关的信息写入到image中,当我们对该image执行docker inspect命令时,输出中有相应的字段记录该信息.

example:
MAINTAINER LyShark "www.mkdirs.com"

RUN:(运行命令,安装软件用)

RUN指令是用来执行命令行命令的,由于命令行的强大能力,RUN指令在定制镜像时是最常用的指令之一.

设置指令,用于container启动时指定的操作.该操作可以是执行自定义脚本,也可以是执行系统命令.该指令只能在文件中存在一次,如果有多个,则只执行最后一条.

FROM centos:latest
RUN yum install -y gcc libc6-dev make
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz"
RUN mkdir -p /usr/src/redis
RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
RUN make -C /usr/src/redis
RUN make -C /usr/src/redis install

Dockerfile 中每一个指令都会建立一层,RUN也不例外.每一个RUN的行为,就和刚才我们手工建立镜像的过程一样,新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像.

而上面的这种写法,创建了 6 层镜像.这是完全没有意义的,不仅仅增加了构建部署的时间,也很容易出错,这是很多初学 Docker 的人常犯的一个错误,Union FS 是有最大层数限制的,比如 AUFS曾经是最大不得超过 42 层,现在是不得超过127 层.

上面的 Dockerfile 正确的写法应该是这样:

FROM centos:latest
RUN buildDeps='gcc libc6-dev make' \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps

CMD:(设置容器启动时执行的操作)

设置指令,用于容器启动时指定的操作,该操作可以是执行自定义脚本,也可以是执行系统命令,该指令只能在文件中存在一次,如果有多个,则只执行最后一条.

example:
CMD echo "Hello, World!"

ENTRYPOINT:(设置容器启动时执行的操作)

设置指令,指定容器启动时执行的命令,可以多次设置,但是只有最后一个有效.

example:
ENTRYPOINT ls -l

该指令的使用分为两种情况,一种是独自使用,另一种和CMD指令配合使用.当独自使用时,如果你还使用了CMD命令且CMD是一个完整的可执行的命令,那么CMD指令和ENTRYPOINT会互相覆盖只有最后一个CMD或者ENTRYPOINT有效.如下命令:CMD指令将不会被执行,只有ENTRYPOINT指令被执行

example:
CMD echo "Hello, World!"
ENTRYPOINT ls -l

另一种用法和CMD指令配合使用来指定ENTRYPOINT的默认参数,这时CMD指令不是一个完整的可执行命令,仅仅是参数部分:ENTRYPOINT指令只能使用JSON方式指定执行命令,而不能指定参数.

example:
FROM centos:latest
CMD ["-l"]
ENTRYPOINT ["/usr/bin/ls"]

USER:(设置container容器的用户)

设置指令,设置启动容器的用户,默认是root用户.或者说以那个身份的用户运行容器,如下所示运行memcached,并以daemon用户运行.

example:
USER daemon = ENTRYPOINT ["memcached", "-u", "daemon"]

EXPOSE:(指定容器需要映射到宿主机器的端口)

设置指令,该指令会将容器中的端口映射成宿主机器中的某个端口.当你需要访问容器的时候,可以不是用容器的IP地址而是使用宿主机器的IP地址和映射后的端口.要完成整个操作需要两个步骤,首先在Dockerfile使用EXPOSE设置需要映射的容器端口,然后在运行容器的时候指定-p选项加上EXPOSE设置的端口,这样EXPOSE设置的端口号会被随机映射成宿主机器中的一个端口号.也可以指定需要映射到宿主机器的那个端口,这时要确保宿主机器上的端口号没有被使用.EXPOSE指令可以一次设置多个端口号,相应的运行容器的时候,可以配套的多次使用-p选项.

example:
映射一个端口
EXPOSE 22
相应的运行容器使用的命令
docker run -p port1 image 映射多个端口
EXPOSE port1 port2 port3
相应的运行容器使用的命令
docker run -p port1 -p port2 -p port3 image 还可以指定需要映射到宿主机器上的某个端口号
docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image

ENV:(用于设置环境变量)

构建指令,在image中设置一个环境变量.设置了后,后续的RUN命令都可以使用,container启动后,可以通过docker inspect查看这个环境变量,也可以通过在docker run --env key=value时设置或修改环境变量.假如你安装了JAVA程序,需要设置JAVA_HOME,那么可以在Dockerfile中这样写:

example:
ENV JAVA_HOME /path/to/java/dirent

ADD:(从src复制文件到容器的dest路径)

example:
ADD <src> <dest>
<src> 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件url
<dest> 是容器中的绝对路径

COPY:(从src复制文件到容器的dest路径)

example:
COPY <src> <dest>

VOLUME:(指定挂载点)

设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用.我们知道容器使用的是AUFS这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失.当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令.

examp:
FROM base
VOLUME ["/tmp/data"]

WORKDIR:(切换目录)

设置指令,可以多次切换(相当于cd命令),对RUN,CMD,ENTRYPOINT生效.

example:
WORKDIR /p1 WORKDIR p2 RUN vim a.txt

ONBUILD:(在子镜像中执行)

ONBUILD指定的命令在构建镜像时并不执行,而是在它的子镜像中执行.

example:
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src

好了关于编译命令还有很多,这里就不一一列举了,更多指令操作语法请自行百度,下面我们来看使用DockerFile编译构建一些好玩的东西吧,相信看完下面的小例子,你就能丰衣足食了.

构建Apache镜像

Apache是一个高稳定性的、商业级别的开源Web服务器.目前Apache已经是世界使用排名第一的Web服务器软件,由于其良好的跨平台和安全性,Apache被广泛应用在多种平台和操作系统上.作为Apache软件基金会支持的项目,它的开发者社区完善而高效.自1995年发布至今,一直以高标准进行维护与开发.Apache名称源自美国的西南部一个印第安人部落:阿帕奇族,它支持类UNIX和Windows系统.

1.首先我们要解决Docker容器内不得网络问题.修改DockerDNS,默认没有文件自行创建即可.

[root@localhost ~]# vim /etc/default/docker

docker_OPTS="--dns 8.8.8.8 --dns 114.114.114.114"

[root@localhost ~]# systemctl restart docker

2.接着在当前目录创建一个Dockerfile文件,和一个index.html文件,文件内容如下.

[root@localhost ~]# vim DockerFile

FROM centos:latest
MAINTAINER email@email.com RUN yum install -y -q apr apr-util httpd
COPY ./index.html /var/www/html/ EXPOSE 80
ENTRYPOINT apachectl start && tail -f /var/log/httpd/access_log

3.使用docker build命令创建centos:httpd镜像,注意命令最后的"."表示当前目录.

[root@localhost ~]# docker build -t centos:httpd .

Sending build context to Docker daemon  18.94kB
Step 1/6 : FROM centos:latest
....省略....
Successfully built 65d0de3819df
Successfully tagged centos:httpd

4.下面开始使用run指令测试镜像,可以使用-P参数映射需要开放的端口(22和80端口)

[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos httpd 65d0de3819df 36 seconds ago 305MB
centos latest 1e1148e4cc2c 11 days ago 202MB [root@localhost ~]# docker run -itd -p 80:80 centos:httpd

## 构建Nginx镜像

Nginx是一款功能强大的开源反向代理服务器,支持HTTP、HTTPS、SMTP、POP3、IMAP等协议.它也可以作为负载均衡器、HTTP缓存或Web服务器.Nginx一开始就专注于高并发和高性能的应用场景,它使用类BSD开源协议,支持Linux、BSD、Mac、Solaris、AIX等类Unix系统,同时也有Windows上的移植版本.

1.首先我们要解决Docker容器内不得网络问题.修改DockerDNS,默认没有文件自行创建即可.

[root@localhost ~]# vim /etc/default/docker

docker_OPTS="--dns 8.8.8.8 --dns 114.114.114.114"

[root@localhost ~]# systemctl restart docker

2.接着在当前目录创建一个Dockerfile文件,和一个index.html文件,文件内容如下.

[root@localhost ~]# vim DockerFile

FROM centos:latest
MAINTAINER email@email.com RUN yum install -y epel-release
RUN yum install -y gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel
RUN rpm -i http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
RUN yum install -y nginx EXPOSE 80
ENTRYPOINT nginx && tail -f /var/log/nginx/access.log #tail必须加,否则容器瞬间终止

3.开始通过dockerfile编译生成nginx:centos镜像文件.

[root@localhost ~]# docker build -t nginx:centos .

Sending build context to Docker daemon  18.43kB
Step 1/8 : FROM centos:latest
....省略....
Successfully built 956a361043bc
Successfully tagged nginx:centos

4.查看生成的镜像文件,并运行这个镜像测试一下吧.

[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx centos 956a361043bc About a minute ago 591MB
centos latest 1e1148e4cc2c 11 days ago 202MB [root@localhost ~]# docker run --name nginx -p 80:80 -d nginx:centos
[root@localhost ~]# curl 127.0.0.1

## 构建Tomcat镜像

Tomcat是由Apache软件基金会下属的Jakarta项目开发的一个Servlet容器,按照Sun Microsystems提供的技术规范,实现了对Servlet和Java Server Page(JSP)的支持.同时,它提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全域管理和Tomcat阀等.由于Tomcat本身也内含了一个HTTP服务器,也可以当作一个单独的Web服务器来使用.下面介绍如何定制Tomcat镜像.

1.首先准备好原材料,Tomcat,jdk环境.

[root@localhost ~]# ls -lh
total 100M
-rw-r--r-- 1 root root 92M Dec 16 23:21 jdk.tar.gz
-rw-r--r-- 1 root root 7.6M Dec 16 23:21 tomcat.tar.gz

2.编写这个构建模板文件,如下内容.

[root@localhost ~]# vim Dockerfile

FROM centos:latest
MAINTAINER email@email.com ADD ./tomcat.tar.gz /root
ADD ./jdk.tar.gz /root ENV JAVA_HOME /root/jdk1.7.0_25
ENV PATH $JAVA_HOME/bin:$PATH EXPOSE 8080 ENTRYPOINT /root/apache-tomcat-7.0.42/bin/startup.sh && tail -F /root/apache-tomcat-7.0.42/logs/catalina.out

3.使用docker build命令创建centos:tomcat镜像,注意命令最后的"."表示当前目录.

[root@localhost ~]# docker build -t centos:tomcat .
Sending build context to Docker daemon 104.3MB
Step 1/8 : FROM centos:lastest
....省略....
Successfully built feac1f1c6ed4
Successfully tagged centos:tomcat [root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos tomcat 65d0de3819df 36 seconds ago 405MB
centos latest 1e1148e4cc2c 11 days ago 202MB

4.下面开始使用run指令测试镜像,可以使用-P参数映射需要开放的端口(22和80端口)

[root@localhost ~]# docker run --name tomcat -p 80:8080 -d centos:tomcat
[root@localhost ~]# curl 127.0.0.1:80
[root@localhost ~]# docker save 镜像ID > /home/xxx.tar

参考文献:《Docker技术入门与实战》《Docker基础与实战》

DockerFile 编译语法详解的更多相关文章

  1. cegui-0.8.2编译过程详解

    cegui 编译过程详解(cegui-0.8.2) cegui配置整了好长时间了,在一位大牛帮助下终于搞定了,网上的教程大多是老版本的,cegui-0.8.2版的配置寥寥无几,现在总结一下,献给正在纠 ...

  2. [持续交付实践] pipeline使用:语法详解

    一.引言 jenkins pipeline语法的发展如此之快用日新月异来形容也不为过,而目前国内对jenkins pipeline关注的人还非常少,相关的文章更是稀少,唯一看到w3c有篇相关的估计是直 ...

  3. Velocity魔法堂系列二:VTL语法详解

    一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不 ...

  4. Android编译过程详解(一)

    Android编译过程详解(一) 注:本文转载自Android编译过程详解(一):http://www.cnblogs.com/mr-raptor/archive/2012/06/07/2540359 ...

  5. Hive笔记--sql语法详解及JavaAPI

    Hive SQL 语法详解:http://blog.csdn.net/hguisu/article/details/7256833Hive SQL 学习笔记(常用):http://blog.sina. ...

  6. Hadoop Hive sql语法详解

    Hadoop Hive sql语法详解 Hive 是基于Hadoop 构建的一套数据仓库分析系统,它提供了丰富的SQL查询方式来分析存储在Hadoop 分布式文件系统中的数据,可以将结构 化的数据文件 ...

  7. Thymeleaf3语法详解和实战

    Thymeleaf3语法详解 Thymeleaf是Spring boot推荐使用的模版引擎,除此之外常见的还有Freemarker和Jsp.Jsp应该是我们最早接触的模版引擎.而Freemarker工 ...

  8. Xpath语法详解

    1.简介 XPath是一门在XML和HTML文档中查找信息的语言,可以用来在XML和HTML文档中对元素和属性进行遍历 XPath的安装 Chrome插件XPath Helper 点Chrome浏览器 ...

  9. mysql用户授权、数据库权限管理、sql语法详解

    mysql用户授权.数据库权限管理.sql语法详解 —— NiceCui 某个数据库所有的权限 ALL 后面+ PRIVILEGES SQL 某个数据库 特定的权限SQL mysql 授权语法 SQL ...

随机推荐

  1. Vue_(组件)过渡效果

    Vue.js进入/离开 & 列表过渡 传送门 进入/离开过渡效果:Vue在插入.更新或移除DOM时,可以设置一些动画效果: 过渡效果中也提供了对应的钩子函数,这些钩子函数需要在<tran ...

  2. highcharts柱状图、饼状图

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...

  3. C++入门经典-例8.10-实现抽象类中的成员函数

    1:抽象类通常作为其他类的父类,如果从抽象类派生的子类是抽象类,则子类必须实现父类中的所有纯虚函数.代码如下: // 8.10.cpp : 定义控制台应用程序的入口点. // #include &qu ...

  4. 打开下载CA root 证书的链接失败

    下载CA root 证书 http://adip/certsrv server error or refuse to connect 这是由于AD上没有安装Active Directory Certi ...

  5. 【java多线程】多线程中的long和double

    在看一些代码的时候,会发现在定义long型和double型的变量时,会在前面加上volatile关键字,当然也会看到在其它原子类型的变量前加上这个关键字,但这里要说的还是有区别的. 在java中,ja ...

  6. jquery 复合事件 toggle()方法的使用

    定义和用法 toggle() 方法用于绑定两个或多个事件处理器函数,以响应被选元素的轮流的 click 事件. 语法: $(selector).toggle(function1(),function2 ...

  7. mongodb将mysql数据导入

    1.首先将数据从mysql数据库导出为xls文件 SELECT * FROM user INTO OUTFILE "F:\1.xls" 2.notepad++打开,用utf8编码保 ...

  8. 百度AI---语音识别

    题记:娱乐性的玩玩百度接口. 说实话,其接口个人觉得有点烂,重试了好几个音频文件才成功. 1.重新申请AppID.SecretKey .API Key. 链接:https://console.bce. ...

  9. VMWare虚拟机->锁定文件失败,打不开磁盘的解决办法

    VMWare虚拟机提示:锁定文件失败,打不开磁盘的解决办法   如果使用VMWare虚拟机的时候突然系统崩溃蓝屏,有一定几率会导致无法启动,会提示:“锁定文件失败,打不开磁盘...或它所依赖的某个快照 ...

  10. k8s测试容器之间是否互通

    [root@lab2 .kube]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE curl-87b54756-rbqz ...