Dockerfile总结

作者: 夜醉梦紅尘 | 来源:发表于2019-11-12 19:12 被阅读0次

定义及其功能阐述

Dokcerfile 是一个普通的文本文件,文件名一般叫 Dockerfile,其中包含了一系列的指令(Instruction), 每一条指令都会构建一层镜像(就是描述该层是如何创建的)。
我们可以像写脚本一样把操作docker的命令写在这个文件里,执行这个文件就相当与执行一系列docker命令来构建镜像,并且会自己提交到本地从仓库,我们如果想改变镜像,操作这个文件就可以,分享这个文件也就相当于分享镜像,更加方便

指令详解

例子

FROM centos:latest
LABEL maintainer="king <king@wgy.com>"  description="Install tree vim*"
RUN rpm -qa | grep tree || yum  install -y tree vim*

FORM 定义一个基础镜像
LABEL 定义一些元数据信息,比如作者、版本、关于镜像的描述信息
RUN 执行命令行的命令

构建镜像
docker bulid -t 仓库名/镜像名:tag .

这个 . 表示当前目录,这实际上是在指定上下文的目录是当前目录,docker build 命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像。
docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件

docker build -t centos:1.20 .

Successfully built adc30981bc84    # 表示构建成功
Successfully tagged centos:1.20    # TAG 标签

FROM 指令

主要作用是指定一个镜像作为构建自定义镜像的基础镜像,在这个基础镜像之上进行修改定制。

这个指令是 Dockerfile 中的必备指令,同时也必须是第一条指令。

Docker Store 上有很多高质量的官方镜像,可以直接作为我们的基础镜像。

作为服务类的,如 Nginx Mongo

用于开发的, 如 Python golang

操作系统类, 如 Centos ubuntu

ADD指令

例子

[root@localhost hello_qf]# ls
Dockerfile  hello  hello.c
[root@localhost hello_king]# cat Dockerfile
FROM scratch
ADD hello /
CMD ["/hello"]

ADD 是把当前目录下的 hello 文档拷贝到 容器中的根目录下
CMD 执行根目录下的 hello 文件

ENV 指令
用于设置环境变量

格式有两种:

ENV <key> <value>

ENV <key1>=<value1> <key2>=<value2>...

示例:

推荐的方式,易读

ENV VERSION=1.0 DEBUG=on \
 NAME="Happy Feet"

下列指令可以支持环境变量: ADD、COPY、ENV、EXPOSE、LABEL、USER、WORKDIR、VOLUME、STOPSIGNAL、ONBUILD

RUN 指令

RUN 指令是在容器内执行 shell 命令,默认会是用 /bin/sh -c 的方式执行。

执行命令的两种方式
RUN <command>(shell形式,该命令在shell中运行)

RUN ["executable", "param1", "param2"](exec形式)

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

注意:Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。所以,在使用 shell 方式,尽量多的使用续行符\

CMD 指令

Dockerfile 中只能有一条CMD指令。如果列出多个,CMD 则只有最后一个CMD会生效。

CMD 主要目的是为运行容器时提供默认值

Docker 不是虚拟机,容器就是进程,CMD 指令就是用于指定默认的容器主进程的启动命令的。在启动(运行)一个容器时可以指定新的命令来替代镜像设置中的这个默认命令。

可以包含可执行文件,当然也可以省略。

CMD 指令的格式和 RUN 相似,也是两种格式:

shell 格式:CMD <命令>
exec 格式:CMD ["可执行文件", "参数1", "参数2"...]
参数列表格式:CMD ["参数1", "参数2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
注意:不要混淆RUN 和 CMD。RUN实际上运行一个命令并提交结果; CMD在构建时不执行任何操作,但指定镜像的默认命令。

Docker 不是虚拟机,容器内没有后台服务的概念。

不要期望这样启动一个程序到后台:

CMD systemctl start nginx
这行被 Docker 理解为:

CMD ["sh" "-c" "systemctl start nginx"]

ps: sh的一些选项参数理解
-c string:命令从-c后的字符串读取。
-i:实现脚本交互。
-n:进行shell脚本的语法检查。
-x:实现shell脚本逐条语句的跟踪。

对于容器而言,其启动程序就是容器的应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。

就像上面的示例中,主进程是 sh , 那么当 service nginx start 命令结束后,sh 也就结束了,sh 作为主进程退出了,自然就会使容器退出。

正确的做法是直接执行 nginx 这个可执行文件,并且关闭后台守护的方式,使程序在前台运行。

CMD ["nginx", "-g", "daemon off;"]

ENTRYPOINT 指令

ENTRYPOINT 的目的和 CMD 一样,都是在指定容器的启动程序及参数。

ENTRYPOINT 在运行时也可以被替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 --entrypoint 来指定。

ENTRYPOINT 的格式和 RUN 指令格式一样,也分为 exec 格式和 shell 格式。

当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,也就是实际执行时,将变为:

<ENTRYPOINT> "<CMD>"

WORKDIR 指令
用于声明当前的工作目录,以后各层的当前目录就被改为指定的目录。

格式为 WORKDIR <工作目录路径>。

如该目录不存在,WORKDIR 会帮你建立目录。

再次强调!不要以为编写 Dockerfiel 是在写 shell 脚本。

下面是一个错误示例:

RUN cd /app
RUN echo "hello" > world.txt

如果将这个 Dockerfile 进行构建镜像运行后,会发现找不到 /app/world.txt 文件,或者其内容不是 hello。

原因其实很简单,这两行 RUN 命令的执行环境根本不同,是两个完全不同的容器。这就是对 Dockerfile 构建分层存储的概念不了解所导致的错误。

之前说过每一个 RUN 都是启动一个容器、执行命令、然后提交存储层文件变更。

两行 RUN 分别构建了并启动了各自全新的容器。

因此如果需要改变以后各层的工作目录的位置,那么应该使用 WORKDIR 指令。

FROM alpine
WORKDIR /a/b
RUN touch a_b_f.txt
WORKDIR /a
RUN touch a_f.txt
[root@localhost workdir]# docker run -it alpine:workdir /bin/sh
/a # ls
a_f.txt  b
/a # cd b
/a/b # ls
a_b_f.txt

COPY 指令

格式:

COPY <源路径>... <目标路径>

COPY ["<源路径1>",... "<目标路径>"]

和 RUN 指令一样,也有两种格式,一种类似于命令行,一种类似于函数调用。

<目标路径> 可以是容器内的绝对路径,也可以是相对于 WORKDIR 指定的工作目录的相对路径。目标路径不需要事先创建,如果目录不存在会在复制文件前先被创建。

COPY 指令将会从构建的上下文目录中,把源路径的文件或目录复制到新的一层的镜像内的 <目标路径> 位置。比如:

COPY king.json /usr/src/app/
注意下面是错误的

COPY king.json /usr/src/app
这样会把 king.json 拷贝成为 /usr/src/ 目录下的 app 文件

<源路径> 可以是多个,支持通配符,如:

COPY king* /app/
COPY k?.txt /app/
使用 COPY 指令,源文件的各种元数据都会保留。

比如读、写、执行权限、文件变更时间等。

ADD 指令

ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。

支持自动解压缩,压缩格式支持: gzip, bzip2 以及 xz

官方推荐使用 COPY 进行文件的复制。

ADD 指定会使构建镜像时的缓存失效,导致构建镜像的速度很慢。

COPY 和 ADD 指令中选择的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。
如:
ADD qf.tar.gz /

相关文章

网友评论

    本文标题:Dockerfile总结

    本文链接:https://www.haomeiwen.com/subject/ojcxictx.html