Dockerfile是Docker打包镜像时使用的说明文件,类似于构建rpm包的spec文件。里面由一些指令和配置构成。本文将一些Dockerfile的编写。其实我们可以把它看成就是spec的一个扩展版。
总的语法也和spec很像,以这样的语句来表示。支持#
注释。
命令 参数
举个栗子
这是个很简单的Dockerfile。
代码语言:javascript复制#指定父镜像
FROM fedora
#作者信息
MAINTAINER kryptosx
#安装命令
RUN yum install -y memcached
#启动命令
ENTRYPOINT ["memcached"]
里面定义了一些基础信息,安装的命令,以及最后启动的命令。下面将根据这些分类来讲解每个命令的用途。
基础信息
这是镜像的基础信息。
基础镜像指定,FROM
Docker
的构建需要指定一个父镜像,这通过FROM
指定。这表明镜像将以指定的父镜像为基础构建。
FROM ubuntu
作者信息,MAINTAINER
写代码要留名。
代码语言:javascript复制MAINTAINER x64.ink
镜像制作
在制作镜像时,Docker使用定义的父镜像创建一个容器。然后,在容器内,执行Dockerfile
中定义的操作。
安装命令,RUN
这里不同于rpm,rpm的spec定义的是安装时执行的命令。也就是安装的这个命令是在软件部署(yum install xxx)时执行的。Docker则是在打包时把安装的各种文件放到相应路径(Docker内的路径)。
代码语言:javascript复制RUN <command> (the command is run in a shell - `/bin/sh -c`)
RUN ["executable", "param1", "param2" ... ] (exec form)
不同的语法略有差异。比如第一句,直接接命令行。Docker
会添加/bin/sh -c
到命令前执行,可能会出现某些bash解析问题。下面这个类似函数穿参的做法,和exec
类函数类似。
在例子中,就用了yum直接安装了memchache。这应该是最简单的移植方式。
加入文件,ADD
这是将外部文件复制到镜像中的指令。
代码语言:javascript复制ADD <src> <dest>
- 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件
url
; - 是容器中的绝对路径
运行命令
ENTRYPOINT
和CMD
是容器启动时的相关命令,二者语法和RUN
一样。
可以单独使用,也可以组合使用。Dockerfile
中至少要定义一个。
ENTRYPOINT
指定容器启动时执行的命令,字面意思是入口点。
代码语言:javascript复制#这和RUN的语法一样。
ENTRYPOINT ["executable", "param1", "param2"] (like an exec, the preferred form)
ENTRYPOINT command param1 param2 (as a shell)
注意:可以多次设置,但是只有最后一个有效。
如果使用exec
用法,在run的时候,传入的参数会接在后面。
# 代码
ENTRYPOINT ["/bin/cat","Hello"]
# 运行
> docker run test World
#输出"Hello World"
运行时,可以通过docker run --entrypoint
覆盖。
CMD
CMD用于容器启动时指定的操作。该操作可以是执行自定义脚本,也可以是执行系统命令。 注意:该指令只能在文件中存在一次,如果有多个,则最后一条生效。
代码语言:javascript复制CMD ["executable","param1","param2"] (like an exec, this is the preferred form)
CMD command param1 param2 (as a shell)
组合使用
如果同时定义 ENTRYPOINT 和 CMD,会有集中情况。
1. ENTRYPOINT
使用了shell
模式,CMD
指令会被忽略。
2. ENTRYPOINT
使用了exec
模式,CMD
指定的内容被追加为ENTRYPOINT
指定命令的参数。如果CMD
是shell
模式,添加的bash -c
也会被放到参数中,所以此时应当使用exec
模式。
#作为参数
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
特别注意:CMD会被运行容器时 docker run
命令最后带的参数给覆盖掉。
# 代码
ENTRYPOINT ["echo","a"]
CMD ["b","c"]
# 运行
> docker run test
a b c
> docker run test d e
a d e
因此,可以让ENTRYPOINT
指定程序,然后CMD
中放入默认参数。
运行的用户,USER
可以指定运行的用户,默认root。
环境变量设置,ENV
现在不少使用Docker的运维系统都是使用环境变量来传递一些集群相关的参数。我们也可以将某些默认配置放到这里。
代码语言:javascript复制ENV <key> <value>