Dockerfile指令详解
说明:
Docker 构建镜像的命令 时 docker build , 需要有一个Dockerfile 文件。
这里对Dockerfile命令,简单的介绍一下,所有指令如下:
- FROM
- MAINTAINER
- RUN
- CMD
- EXPOSE
- ENV
- ADD
- COPY
- ENTRYPOINT
- VOLUME
- USER
- WORKDIR
- ONBUILD
下面我来逐一介绍:
一、FROM
FROM <image>
FROM 必须是Dockerfile 中非注释行的第一个指令。
FROM 制定构建镜像的基础源镜像,镜像可以本地没有,会自动从公共库pull 镜像下来。
FROM 可以在一个Dockerfile 文件中,出现多次。
二、MAINTAINER
MAINTAINER <name>
创建镜像的作者。
三、RUN
RUN "executable" , "param1" , "param2"
解释:
RUN命令是Dockerfile执行命令的核心部分。它接受命令作为参数并用于创建镜像。不像CMD命令,RUN命令用于创建镜像(在之前commit的层之上形成新的层)。也就是说,在创建镜像的时候,执行的一些指令,比如安装一些插件,下载文件之类的。
举例:
创建一个tomcat镜像,需要把安装包从本地传递到容器中,需要进行解压,那么要使用tar 指令,就 RUN tar xxx xxx.
,在比如要创建一个文件夹,需要使用mkdir指令,那么就RUN mkdir /xxx/xxx
即可。
注:RUN产生换缓存,在下一次构建的时候,是不会实效的,会被重用,可以使用 --no-cache选项,即 docker build --no-cache ,这样就不会被缓存。
四、CMD
CMD有三种方式
CMD "executable" , "param1","param2"
CMD "param1" , "param2"
CMD command param1 param2 (shell from)
解释:
CMD 在 Dockerfile 中 只能使用一次,如果有多个,则最后一个会生效。
注:
CMD 是会在容器启动时候执行的,build 时 不执行,会有遇到 一些镜像,在docker start 后, docker ps 看不到,停止了,就是因为没有加入 CMD。
五、EXPOSE
EXPOSE [ ...]
解释:
告诉Docker 服务端容器对外映射的端口。比如tomcat 8080
、mysql3306
,如果不写,也可以在docker run 的时候, -p 或者 -P 选项代替,写于不写的区别在于,是否需告诉别人我的端口,如果容器中有多个tomcat,端口不一样,别人需要进入容器内部,去查看端口,体验就不友好了。
六、ENV
ENV #只允许一个变量
ENV = #允许一次设置多个变量
解释:
创建一个环境变量,可以被后续RUN 指令使用,并且在容器运行时保留。
比如:
ENV name="will" age="18"
等同
ENV name will
ENV age 18
七、ADD
ADD <src>.... <dest>
ADD 复制本地主机文件、目录 .
解释:
相当于 我们在制作tomcat镜像的时候, ADD war包, 到 tomcat webapp 目录下。
- 路径 必须是绝对路径。
- 可以制定远程路径。
八、COPY
COPY <src>.... <dest>
解释:
用法和ADD 一样, 区别是不能访问远程的地址。
九、ENTRYPOINT
ENTRYPOINT "executable" ,"param1" , "param2"
ENTRYPOINT command param1 param2 (shell form)
解释:
配置容器启动执行的命令,并且不可悲docker run 提供参数覆盖,而CMD 是可以被覆盖的。
每个Dockerfile 中,只能有一个ENTRYPOINT , 写多个,只有最后一个生效。
ENTRYPOINT 帮助你配置一个容器使之可执行化,如果你结合CMD命令和ENTRYPOINT命令,你可以从CMD命令中移除“application”而仅仅保留参数,参数将传递给ENTRYPOINT命令。
Usage: ENTRYPOINT application "argument", "argument", ..
Remember: arguments are optional. They can be provided by CMD
or during the creation of a container.
ENTRYPOINT echo
Usage example with CMD:
Arguments set with CMD can be overridden during run
CMD "Hello docker!"
ENTRYPOINT echo
十、VOLUME
VOLUME ["/data"]
创建一个可以从本地主机或则其他容器挂载的挂载点,后续具体介绍。
十一、WORKDIR
WORKDIR /path/to/workdir
为后续的RUN 、CMD 、ENTRYPINT 指令配置工作目录,可以使用多个WORKDIR 指令,后续命令如果参数十相对路径,则会给予之前命令制定的路径。
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最终的路径是 /a/b/c
WORKDIR指令可以在ENV 设置变量之后调用环境变量。
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
最终的路径为 /path/$DIRNAME
十二、ONBUILD 转自[http://www.cnblogs.com/51kata/p/5265107.html]
DNBUILD [INSTRUCTION]
ONBUILD指令可以为镜像添加触发器。其参数是任意一个Dockerfile 指令。
当我们在一个Dockerfile文件中加上ONBUILD指令,该指令对利用该Dockerfile构建镜像(比如为A镜像)不会产生实质性影响。
但是当我们编写一个新的Dockerfile文件来基于A镜像构建一个镜像(比如为B镜像)时,这时构造A镜像的Dockerfile文件中的ONBUILD指令就生效了,在构建B镜像的过程中,首先会执行ONBUILD指令指定的指令,然后才会执行其它指令。
需要注意的是,如果是再利用B镜像构造新的镜像时,那个ONBUILD指令就无效了,也就是说只能再构建子镜像中执行,对孙子镜像构建无效。其实想想是合理的,因为在构建子镜像中已经执行了,如果孙子镜像构建还要执行,相当于重复执行,这就有问题了。
利用ONBUILD指令,实际上就是相当于创建一个模板镜像,后续可以根据该模板镜像创建特定的子镜像,需要在子镜像构建过程中执行的一些通用操作就可以在模板镜像对应的dockerfile文件中用ONBUILD指令指定。 从而减少dockerfile文件的重复内容编写。
接下来我们来看一个简单例子。
示例一:先编写一个Dockerfile文件,内容如下:
#test
FROM ubuntu
MAINTAINER hello
ONBUILD RUN mkdir mydir
利用上面的dockerfile文件构建镜像: docker build -t imagea .
利用imagea镜像创建容器: docker run --name test1 -it imagea /bin/bash
我们发现test1容器的根目录下并没有mydir目录。说明ONBUILD指令指定的指令并不会在自己的构建中执行。
示例二:再编写一个新的Dockerfile文件,内容 如下
#test
FROM imagea
MAINTAINER hello1
注意,该构建准备使用的基础镜像是上面构造出的镜像imagea
利用上面的dockerfile文件构建镜像: docker build -t imageb .
利用imagea镜像创建容器: docker run --name test2 -it imageb /bin/bash
我们发现test2容器的根目录下有mydir目录,说明触发器执行了。 这个其实从构建imageb的输出日志就可看出。日志如下:
复制代码
xxx@ubuntu:~/myimage$ docker build -t imageb .
Sending build context to Docker daemon 15.87 kB
Step 1 : FROM imagea
Executing 1 build trigger...
Step 1 : RUN mkdir mydir
---> Running in e16c35c94b03
---> 4b393d1610a6
Removing intermediate container e16c35c94b03
Step 2 : MAINTAINER hello1
---> Running in c7b0312516ea
---> 0f63b8e04d82
Removing intermediate container c7b0312516ea
Successfully built 0f63b8e04d82
复制代码
我们可以看出,FROM指令执行之后,就立即执行的是触发器(ONBUILD指令指定的指令)
示例三:创建一个MongoDB的镜像
在这部分中,我们讲一步一步创建一个Dockfile,这个Dockerfile可用于构建MongoDB镜像进而构建MongoDB容器。
创建一个Dockerfile
让阅读者明确Dockerfile的目的永远是必要的。为此,我们通常从注释开始写Dockerfile。
############################################################
# Dockerfile to build MongoDB container images
# Based on Ubuntu
############################################################
#设置基础镜像
FROM ubuntu
#定义作者
MAINTAINER Example McAuthor
#设置命令与参数下载MongoDB
################## BEGIN INSTALLATION ######################
# Install MongoDB Following the Instructions at MongoDB Docs
# Ref: http://docs.mongodb.org/manual/tutorial/install-mongodb-on-ubuntu/
# Add the package verification key
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
# Add MongoDB to the repository sources list
RUN echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | tee /etc/apt/sources.list.d/mongodb.list
# Update the repository sources list once more
RUN apt-get update
# Install MongoDB package (.deb)
RUN apt-get install -y mongodb-10gen
# Create the default data directory
RUN mkdir -p /data/db
##################### INSTALLATION END #####################
#设置MongoDB端口
EXPOSE 27017
CMD ["--port 27017"]
ENTRYPOINT usr/bin/mongod
保存Dockerfile。
构建镜像
使用上述的Dockerfile,我们已经可以开始构建MongoDB镜像sudo docker build -t my_mongodb .
示例四:创建一个Nginx的镜像
Nginx简述
Nginx是一个高性能的 HTTP 和 反向代理 服务器。它因为它的轻量级,易用,易于扩展而流行于业界。基于优良的架构设计,它能够比之前的类似软件处理更多的请求。它也可以用来提供静态文件服务,比如图片,脚本和CSS。
和上个例子一样,我们还是从基础镜像开始,运用FROM命令和MAINTAINER命令
############################################################
# Dockerfile to build Nginx Installed Containers
# Based on Ubuntu
############################################################
#下载 ubuntu
FROM ubuntu
#作者
MAINTAINER Will
#安装Nginx
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
#更新一些必要插件 and 工具包
RUN apt-get update
RUN apt-get install -y nano wget dialog net-tools
RUN apt-get install -y nginx
Bootstrapping
#安装Nginx后,我们需要配置Nginx并且替换掉默认的配置文件
RUN rm -v /etc/nginx/nginx.conf
ADD nginx.conf /etc/nginx/
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80
CMD service nginx start
保存 dockfile。
使用Dockerfile自动构建Nginx容器
因为我们命令Docker用当前目录的Nginx的配置文件替换默认的配置文件,我们要保证这个新的配置文件存在。在Dockerfile存在的目录下,创建nginx.conf:
sudo nano nginx.conf
然后用下述内容替换原有内容:
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
server {
listen 80;
location / {
proxy_pass http://httpstat.us/;
proxy_set_header X-Real-IP $remote_addr;
}
}
}