DockerFile简介
官网:https://docs.docker.com/engine/reference/builder/
概述
Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。
1.构建三步骤
编写Dockerfile文件 - docker build命令构建镜像 - docker run依镜像运行容器实例
2.Dockerfile内容基础知识
1:每条保留字指令都必须为大写字母且后面要跟随至少一个参数
2:指令按照从上到下,顺序执行
3:#表示注释
4:每条指令都会创建一个新的镜像层并对镜像进行提交
DockerFile构建过程解析
Docker执行Dockerfile的大致流程
(1)docker从基础镜像运行一个容器
(2)执行一条指令并对容器作出修改
(3)执行类似docker commit的操作提交一个新的镜像层
(4)docker再基于刚提交的镜像运行一个新容器
(5)执行dockerfile中的下一条指令直到所有指令都执行完成
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
* Dockerfile是软件的原材料
* Docker镜像是软件的交付品
* Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
1 Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
2 Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时会真正开始提供服务;
3 Docker容器,容器是直接提供服务的。
DockerFile常用保留字指令
FROM | 基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是from(最好挑一些apline,slim之类的基础小镜像) | ||||||||||
LABEL |
标注镜像的一些说明信息 |
LABEL multi.label1="value1" multi.label2="value2" other="value3" | |||||||||
MAINTAINER | 镜像维护者的姓名和邮箱地址 | ||||||||||
RUN |
容器构建时需要运行的命令 RUN指令在当前镜像层顶部的新层执行任何命令,并提交结果,生成新的镜像层 生成的提交映像将用于Dockerfile中的下一步。 分层运行RUN指令并生成提交符合Docker的核心概念,就像源代码控制一样 exec形式可以避免破坏shell字符串,并使用不包含指定shell可执行文件的基本映像运行RUN命令。可以使用SHELL命令更改shell形式的默认shell。 在shell形式中,您可以使用\(反斜杠)将一条RUN指令继续到下一行。 |
||||||||||
两种格式 |
shell格式 /bin/sh -c <command>的方式, |
# 测试案例
|
|||||||||
exec格式 ["/bin/sh","-c",command] 的方式== shell方式 |
|||||||||||
RUN是在 docker build时运行 | |||||||||||
EXPOSE | EXPOSE指令通知Docker容器在运行时在指定的网络端口上进行侦听。 可以指定端口是侦听TCP还是UDP,如果未指定协议,则默认值为TCP。 EXPOSE指令实际上不会发布端口。 它充当构建映像的人员和运行容器的人员之间的一种文档,即有关打算发布哪些端口的信息。 要在运行容器时实际发布端口,请在docker run上使用-p标志发布并映射一个或多个端口,或使用-P标志发布所有公开的端口并将其映射到高阶端口 |
EXPOSE <port> [<port>/<protocol>...] EXPOSE [80,443] EXPOSE 80/tcp EXPOSE 80/udp |
|||||||||
WORKDIR | WORKDIR指令为Dockerfile中跟随它的所有 RUN,CMD,ENTRYPOINT,COPY,ADD 指令设置工作目 录。 如果WORKDIR不存在,即使以后的Dockerfile指令中未使用它也将被创建。 WORKDIR指令可在Dockerfile中多次使用。 如果提供了相对路径,则它将相对于上一个WORKDIR指 令的路径 |
例如: WORKDIR /a |
例如: ENV DIRPATH=/path |
||||||||
USER | USER指令设置运行映像时要使用的用户名(或UID)以及可选的用户组(或GID),以及Dockerfile中USER后面所有RUN,CMD和ENTRYPOINT指令 | USER <user>[:<group>] USER <UID>[:<GID>] |
|||||||||
ARG |
ARG指令定义了一个变量,用户可以在构建时使用--build-arg = 传递,docker build命令会将其传递 |
||||||||||
ENV | 在构建阶段中所有后续指令的环境中使用,并且在许多情况下也可以内联替换。 引号和反斜杠可用于在值中包含空格。 ENV 可以使用key value的写法,但是这种不建议使用了,后续版本可能会删除 参照右侧示例 |
ENV MY_MSG hello |
docker run --env 可以修改这些值 容器运行时ENV值可以生效 ENV在image阶段就会被解析并持久化(docker inspect image查看),参照右侧示例 |
FROM alpine ENV arg=1111111 ENV runcmd=$arg RUN echo $runcmd CMD echo $runcmd #ENV的固化问题: 改变arg,会不会改变 echo的值,会改变哪些值,如何修改这些值? |
|||||||
ADD | 同COPY用法,不过 ADD拥有自动下载远程文件和解压的功能 |
注意: src 路径必须在构建的上下文中; 不能使用 ../something /something 这种方式,因为docker构建的第一步是将上下文目录(和子目录)发送到docker守护程序。 |
|||||||||
COPY |
类似ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置
COPY指令从 src 复制新文件或目录,并将它们添加到容器的文件系统中,路径为 dest 。 |
COPY [--chown=<user>:<group>] <src>... <dest> | COPY hom* /mydir/ #当前上下文,以home开始的所有资源 COPY hom?.txt /mydir/ # ?匹配单个字符 COPY test.txt relativeDir/ # 目标路径如果设置为相对路径,则相对与 WORKDIR 开始 # 把 “test.txt” 添加到 <WORKDIR>/relativeDir/ COPY test.txt /absoluteDir/ #也可以使用绝对路径,复制到容器指定位置 #所有复制的新文件都是uid(0)/gid(0)的用户,可以使用--chown改变 COPY --chown=55:mygroup files* /somedir/ COPY --chown=bin files* /somedir/ COPY --chown=1 files* /somedir/ COPY --chown=10:11 files* /somedir/ |
||||||||
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] | |||||||||||
--chown=<user>:<group> 用户:用户组权限(--chown功能仅在用于构建Linux容器的Dockerfiles上受支持,而在Windows容器上不起作用) | |||||||||||
<src源路径>:源文件或者源目录 | |||||||||||
<dest目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。 | |||||||||||
VOLUME |
容器数据卷,用于数据保存和持久化工作 作用:把容器的某些文件夹映射到主机外部 |
VOLUME ["/var/log/"] #可以是JSON数组 |
用 VOLUME 声明了卷,那么以后对于卷内容的修改会被丢弃,所以, 一定在volume声明之前修改内容 |
||||||||
CMD | 指定容器启动后的要干的事情 | ||||||||||
注意 | Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换 | ||||||||||
参考官网Tomcat的dockerfile演示讲解 | 官网最后一行命令 | ||||||||||
我们演示自己的覆盖操作 | |||||||||||
它和前面RUN命令的区别 | CMD是在docker run 时运行。 | ||||||||||
RUN是在 docker build时运行。 | |||||||||||
ENTRYPOINT | 也是用来指定一个容器启动时要运行的命令 | ||||||||||
类似于 CMD 指令,但是ENTRYPOINT不会被docker run后面的命令覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序 |
|||||||||||
命令格式和案例说明 | 命令格式: | ||||||||||
ENTRYPOINT可以和CMD一起用,一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参。 当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,他两个组合会变成 |
|||||||||||
案例如下:假设已通过 Dockerfile 构建了 nginx:test 镜像:
|
|||||||||||
优点 | 在执行docker run的时候可以指定 ENTRYPOINT 运行所需的参数。 | ||||||||||
注意 | 如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。 |
CMD和ENTRYPOINT
写法 | CMD 的三种写法 |
CMD ["executable","param1","param2"] ( exec 方式, 首选方式) |
# 示例 FROM alpine LABEL maintainer=leifengyang CMD ["1111"] CMD ["2222"] ENTRYPOINT ["echo"] #构建出如上镜像后测试 docker run xxxx:效果 echo 1111 |
||||||||||||||||||||||||
CMD ["param1","param2"] (为ENTRYPOINT提供默认参数) |
|||||||||||||||||||||||||||
CMD command param1 param2 ( shell 形式) |
|||||||||||||||||||||||||||
ENTRYPOINT 的两种写法: |
ENTRYPOINT ["executable", "param1", "param2"] ( exec 方式, 首选方式) |
||||||||||||||||||||||||||
ENTRYPOINT command param1 param2 (shell 形式) |
|||||||||||||||||||||||||||
只能有一个CMD |
Dockerfile中只能有一条CMD指令。 如果您列出多个CMD,则只有最后一个CMD才会生效。 CMD的主要目的是为执行中的容器提供默认值。 这些默认值可以包含可执行文件,也可以省略可执行文件,在这种情况下,您还必须指定ENTRYPOINT指令。 |
||||||||||||||||||||||||||
CMD为ENTRYPOINT提供默认参数 |
如果使用CMD为ENTRYPOINT指令提供默认参数,则CMD和ENTRYPOINT指令均应使用JSON数组格式指定
|
||||||||||||||||||||||||||
组合最终效果 |
|
||||||||||||||||||||||||||
docker run启动参数会覆盖CMD内容 |
# 一个示例 FROM alpine LABEL maintainer=leifengyang CMD ["1111"] ENTRYPOINT ["echo"] #构建出如上镜像后测试 docker run xxxx:什么都不传则 echo 1111 docker run xxx arg1:传入arg1 则echo arg1 |