Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,所以每一条指令的内容,就是描述该层应当如何构建。mysql
ROM 就是指定 基础镜像,Dockerfile 中 FROM 是必备的指令,而且必须是第一条指令。nginx
FROM scratch 表示一个空白镜像。因此 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将做为镜像第一层开始存在。sql
RUN 指令是用来执行命令行命令的。因为命令行的强大能力,RUN 指令在定制镜像时是最经常使用的指令之一。其格式有两种:docker
须要注意的是,Dockerfile 中每个指令都会创建一层,因此每一个Run都会建立一层镜像,若是有多个命令能够尽可能写在一个RUN里面。可使用&&
串联起来shell
<目标路径> 能够是容器内的绝对路径,也能够是相对于工做目录的相对路径(工做目录能够用 WORKDIR 指令来指定)。目标路径不须要事先建立,若是目录不存在会在复制文件前先行建立缺失目录。 数据库
使用 COPY 指令,源文件的各类元数据都会保留。好比读、写、执行权限、文件变动时间等。
在使用该指令的时候能够加上 --chown=
COPY --chown=55:mygroup files* /mydir/ COPY --chown=bin files* /mydir/ COPY --chown=1 files* /mydir/ COPY --chown=10:11 files* /mydir/
ADD 和 COPY 的格式和性质都是基本一致的。区别在于:服务器
若是权限须要调整的话就须要另外的一层RUN,因此并不推荐使用。
对于复制文件,应该尽量的使用COPY。网络
与RUN类似,有两种格式:架构
容器就是进程,因此在启动容器的时候须要指定所运行的程序及参数。CMD 指令就是用于指定默认容器主进程的启动命令的。
在运行时能够指定新的命令来替代镜像设置中的这个默认命令。
须要注意的是 Docker 不是虚拟机,容器中的命令都应该之前台执行而不是像虚拟机、物理机里面那样,用 systemd 去启动后台服务,容器内没有后台服务的概念。
对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它须要关心的东西。
CMD service nginx start
CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT 的目的和 CMD 同样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也能够替代,不过比 CMD 要略显繁琐,须要经过 docker run 的参数 --entrypoint 来指定。
当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,再也不是直接的运行其命令,而是将 CMD 的内容做为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:
<ENTRYPOINT> "<CMD>"
ENTRYPOINT的做用:
格式:
支持环境变量的指令:ADD、COPY、ENV、EXPOSE、LABEL、USER、WORKDIR、VOLUME、STOPSIGNAL、ONBUILD。
格式:ARG <参数名> [= <默认值> ]
构建参数和 ENV 的效果同样,都是设置环境变量。所不一样的是,ARG 所设置的构建环境的环境变量,在未来容器运行时是不会存在这些环境变量的。可是不要所以就使用 ARG 保存密码之类的信息,由于 docker history 仍是能够看到全部值的。
Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值能够在构建命令 docker build 中用 --build-arg <参数名> = <值> 来覆盖。
格式:
容器运行时,应该尽可能保持容器存储层不发生写操做,对于数据库类须要保存动态数据的应用,其数据库文件应该保存于卷(VOLUME)中。在Dockerfile中,能够事先指定某些目录为挂载为你命卷,这样在运行时若是用户不指定挂载,其应用也能够正常运行,不会向容器存储层写入大量数据。
VOLUME /data
这里的 /data 目录就会在运行时自动挂载为匿名卷,任何想 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。固然,运行时能够覆盖这个挂载设置。好比:
docker run -d -v mydata:/data xxxx
在这行命令中,就使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置。
格式:
EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会由于这个声明应用就会开启这个端口的服务。
格式:WORKDIR <工做目录路径>
使用 WORKDIR 指令能够来指定工做目录(或者称为当前目录),之后各层的当前目录就被改成指定的目录,如该目录不存在,WORKDIR 会帮你创建目录。
若是须要改变之后各层的工做目录的位置,应该使用 WORKDIR 指令。
格式:
USER 指令和 WORKDIR 类似,都是改变环境状态并影响之后的层。WORKDIR 是改变工做目录,USER 则是改变以后层的执行 RUN, CMD 以及 ENTRYPOINT 这类命令的身份。
和 WORKDIR 同样,USER 只是切换到指定的用户而已,这个用户必须是事先创建好的,不然没法切换。
格式:
当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为 starting,在 HEALTHCHECK 指令检查成功后变为 healthy,若是连续必定次数失败,则会变为 unhealthy。
HEALTHCHECK 支持下列选项:
和 CMD, ENTRYPOINT 同样,HEALTHCHECK 只能够出现一次,若是写了多个,只有最后一个生效。
格式:
ONBUILD 是一个特殊的指令,它后面跟的是其它指令,好比 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
格式:
docker build [OPTIONS] PATH | URL | -
参数:
-build-arg=[] :设置镜像建立时的变量;
--cpu-shares :设置 cpu 使用权重;
--cpu-period :限制 CPU CFS周期;
--cpu-quota :限制 CPU CFS配额;
--cpuset-cpus :指定使用的CPU id;
--cpuset-mems :指定使用的内存 id;
--disable-content-trust :忽略校验,默认开启;
-f :指定要使用的Dockerfile路径;
--force-rm :设置镜像过程当中删除中间容器;
--isolation :使用容器隔离技术;
--label=[] :设置镜像使用的元数据;
-m :设置内存最大值;
--memory-swap :设置Swap的最大值为内存+swap,"-1"表示不限swap;
--no-cache :建立镜像的过程不使用缓存;
--pull :尝试去更新镜像的新版本;
--quiet, -q :安静模式,成功后只输出镜像 ID;
--rm :设置镜像成功后删除中间容器;
--shm-size :设置/dev/shm的大小,默认值是64M;
--ulimit :Ulimit配置。
--tag, -t: 镜像的名字及标签,一般 name:tag 或者 name 格式;能够在一次构建中为一个镜像设置多个标签。
--network: 默认 default。在构建期间设置RUN指令的网络模式
docker build 命令最后有一个 .。. 表示当前目录,而 Dockerfile 就在当前目录,所以很多初学者觉得这个路径是在指定 Dockerfile 所在路径,这么理解实际上是不许确的。若是对应上面的命令格式,你可能会发现,这是在指定 上下文路径。那么什么是上下文呢?
首先咱们要理解 docker build 的工做原理。Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API,而如 docker 命令这样的客户端工具,则是经过这组 API 与 Docker 引擎交互,从而完成各类功能。所以,虽然表面上咱们好像是在本机执行各类 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也由于这种 C/S 设计,让咱们操做远程服务器的 Docker 引擎变得垂手可得。
当咱们进行镜像构建的时候,并不是全部定制都会经过 RUN 指令完成,常常会须要将一些本地文件复制进镜像,好比经过 COPY 指令、ADD 指令等。而 docker build 命令构建镜像,其实并不是在本地构建,而是在服务端,也就是 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端得到本地文件呢?
这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的全部内容打包,而后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会得到构建镜像所需的一切文件。