Docker学习过程 (7-Dockerfile)

Dockerfile 文件是由 Docker 提供的进行镜像自动化构建的配置文件,包含了所有用于构建镜像所执行的命令。[1]把操作写在一个几K的文件里,肯定比迁移几十几百兆的镜像容易。这就是 Dockerfile 的精要。
  今天讲的内容实践操作不多,后面几期会讲几个用 Dockerfile 的应用,先和命令混个脸熟。

概要

Dockerfile 的内容主要以两种方式呈现:注释行和指令行

# Comment
INSTRUCTION arguments

注释行以 # 开头,命令行由指令名称 INSTRUCTION 和指令的参数 arguments 构成。虽然两者都不区分大小写,但习惯还是指令名称大写,参数小写。
有一类特殊的参数是通过 # 开头的,叫做解析指令行。基本形式如下,具体的以后说:

# directive=value

如果有了 Dockerfile 文件,那用下面命令来构建镜像:

sudo docker build $dir 

$dir 是 Dockerfile 所在的文件夹。如果存放 Dockerfile 指令的文件名不是 Dockerfile,可以通过携带 -f 参数来指定要采用的文件名。

基础指令 FROM MAINTAINTER
FROM $image
FROM $image:$tag
FROM $image@$tag				#以上三个均用来指定镜像,且 FROM 指令必须为第一条指令

MAINTAINER $name				#用来提供镜像的作者信息

#栗子
FROM alpine:3.4
MAINTAINER gengli
控制指令 RUN WORKDIR ONBUILD
RUN $command $param1 $param2 ... 				#用 Shell 程序执行 $command
RUN ["$executable", "$para1", "$para2", ...] 	#两者作用相同,前者支持反斜杠换行

WORKDIR $dir   					#用于切换构建过程的工作目录,可以使相对或绝对路径,
								#如果是相对路径,就是容器内当前的工作路径,注意不是容器在宿主机的路径
ONBUILD $INSTRUCTION arguments 	#此条指令在当前镜像构建过程中不会执行
								#以当前构建的容器生成的镜像为基础镜像的容器构建时才执行

#栗子:
RUN apt-get install -y \
	autoconf \
	file \
	...
	
RUN ["/bin/bash", "-c", "echo Good!"]

WORKDIR /usr
WORKDIR local 					#此时工作目录变成 /usr/local
引入指令 ADD
ADD $src1 $src2 ... $srcn $dest
ADD ["$src1", "$src2", ..., "$srcn", "$dest"]		
								#ADD可以把软件源码、配置文件、执行脚本等导入到镜像的构建过程
								#$src 目录或文件可以采用Go语言的通配符
								#如果 $src 是Docker能识别的压缩文件格式,则Docker会自动将其解压到 $desc 中
								#可以获得网络文件,但推荐使用专业的 curl,wget 等工具
								
COPY $src1 ... $srcn $dest
COPY ["$src1", ..., "$srcn", $dest"]	
								#COPY 指令和 ADD 差不多,只是 COPY 不会对压缩文件自动解压,也不能识别网络地址

#栗子:
ADD hom* home?.txt /mydir/
COPY ["in.py", "start.sh", "/build"]
执行指令 CMD ENTYRPOINT

书[1] 这样介绍 CMD :
  Docker 容器是我运行单独应用程序而设计的,当 Docker 容器启动时,实际上是对程序的启动,而容器是否停止也以程序是否结束为标准。而在 Dockerfile 中,就可以通过 CMD 指令来指定由镜像创建容器中的主体程序。
具体的大家在后面的例子中慢慢感受吧。

CMD $command $param1 $param2 ...
CMD ["$executable", "param1", "param2", ...]
CMD ["param1", "param2"]

  不要混淆了 CMD 指令和 RUN 指令,它们的区别是很大的。RUN 指令是在镜像构建的过程中执行,并将执行结果提交到新的镜像层中; CMD 指令在镜像的构建过程中不执行,它只是配置镜像的默认入口程序。
可以在构建容器时荣国指定新的应用程序覆盖掉 CMD 设置。例如下面命令用指定了新的程序 /bin/bash:

sudo docker run -it nginx /bin/bash

  下面介绍 ENTRYPOINT 。镜像所指定的应用程序在容器中运行时,难免要一些系统服务或其他程序的支持和配合,我们可以在 CMD 指令中启动这些服务,但这样会让启动服务的命令与启动主程序的命名杂糅在一起,显得比较混乱。 ENTYRPOINT 指令就是专门用于主程序的启动前的准备工作的。
  使用 ENTRYPOINT 指令的方式与使用 CMD 指令的方式非常相似。[1]

ENTRYPOINT ["executable", "param1", "param2", ...]
ENTRYPOINT command param1 param2 ...

需要注意的是,当 ENTRYPOINT 指令被指定时,所有的 CMD 指令或通过 docker run 等方式指定的应用程序命令,不会在容器启动时被直接执行,而是把这些命令当做参数,完整地拼接在 ENTRYPOINT 指令的后面。

配置指令 EXPOSE ENV LABEL USER ARG STOPSIGNAL SHELL

EXPOSE
每个容器的端口如果不向外界打开,那即使用前面的 -P 、 -p 或 --link 参数连接,也不能通过端口访问容器内部。让容器端口敞开的指令就是 EXPOSE.

EXPOSE $port $port2 ...

ENV
设置环境变量用 ENV

ENV $key $value		#$key之后的所有内容都会被当做 $value
ENV $key=$value		#可以一次指定多个变量,并且指令之间可以用换行连接。

#例子:
ENV myDog The yellow dog!
ENV myCat The cute cat!
等价于
ENV myDog="The yellow dog!" \
	myCat=The\ cute\ cat!

ENV 可以通过 --env 参数在构造镜像时指定,覆盖 Dockerfile 里面的设置,比如下面:

sudo docker run --env myDog="The cute dog!" ...

推荐使用第二种,因为每个 ENV 意味着提交一次镜像,少用点 ENV 总是好的。
LABEL
LABEL 指令不是必要的,只是为了向别人展示镜像信息,其格式如下:

LABEL $key1=$value1 $key2=$value2 ... \
	  $keyn=$valuen

USER
USER 用于设置执行用户,对之后的各指令都起作用。格式如下

USER $username

ARG
ARG 用于设定变量

ARG $argname
ARG $argname=$default_value

用 --build-arg 构建镜像时指定其值:

sudo docker build --build-arg user=root .

STOPSIGNAL
STOPSIGNAL 用于容器停止时修改 Docker 所传递的信号。
信号源有两种格式,一种是Linux内核的 syscall 信号的数字表示,另外一种是用信号名称表示。

#例子:
STOPSIGNAL 9
STOPSIGNAL SIGKILL

SHELL
SHELL 命令用于指定 Shell。格式如下:

SHELL ["executable", "parameters"]

#例子,把 Docker 默认的 /bin/sh 改为 /bin/bash
SHELL ["/bin/bash", "-c"]
特殊指令 解析指令

这个不多说。举个例子,因为 Windows 的文件路径是反斜杠,而 Linux 都是正斜杠,有时会造成一些麻烦。用下面一条指令加在 Dockerfile 文件开头,就能像写 Linux 文件一样写 Windows 命令。

# escape=`

注意:前面的 # 也是命令一部分,等号后面是 Tab 键上面的那个斜点,不是单引号。
其实我不知道微软当年为什么用反斜杠当文件路径,感觉纯属自找麻烦,还麻烦后面千万要跨平台开发的人。
今天的内容都没有用出来,下一次就可以用了。这几天事比较多,还有期末考试最后一科。不过刀已经在这前7节磨好了,后面就是牛刀小试!!

[1]熊昌隆.没什么难的Docker入门与开发实战.电子工业出版社.2017.6

猜你喜欢

转载自blog.csdn.net/gengli2017/article/details/86470115