构建镜像DockerFile
1. 简介
(1) 场景
自定义构建镜像,如果使用docker commit,优缺点
① commit打包过程,对操作不可见,不知道内部打包了什么,做了什么,又什么问题。
② 所有容器的改动,需要手工操作,不具备可复制性,不具备自动化,不具备规模性。
(2) DockerFile简介
一种脚本语言,用来描述Docker镜像构建过程,也就是一个说明书,Docker通过dockerfile构建出来一个
自定义镜像
。
(3) Dockerfile作用
通过使用Dockerfile,开发人员可以通过简单的文本文件定义和管理镜像的构建过程,实现自动化、可重复和可管理的镜像构建。
-
自动化构建:
通过编写Dockerfile,可以自动构建Docker镜像,而无需手动逐步执行构建步骤。Docker根据Dockerfile中的指令顺序执行构建步骤,从而实现自动化构建过程。
效率高,便于管理,便于和其他平台集成。 -
版本控制:
Dockerfile本身是一个文本文件,通过对Dockerfile内容版本控制,也就实现了Image镜像的版本控制管理。
(4) 指令
指令 | 作用 |
---|---|
FROM | 基础镜像,从这个镜像开始制作 |
LABEL | 描述,描述镜像的信息:作者、文字描述、日期、要求数据卷路径 (没有任何docker构建的作用,仅仅给工作人员看的 ) |
maintainer | 描述信息,写作者信息。作用类似label。逐渐被废弃。 |
RUN | 在构建镜像的时候,执行一些命令的。 |
ADD | 向镜像中拷贝文件 |
COPY | 向镜像中拷贝文件 |
VOLUME | 数据卷目录,指定镜像中的那个目录,作为日后数据卷挂载目录。(不写也能挂载,给工作人看的 ) |
EXPOSE | 暴露开放容器端口 |
ENV | 定义环境变量 |
WORKDIR | 工作目录,就是exec进入容器,默认初始位置。 |
CMD | 在容器启动的时候,会执行的命令。 |
entrypoint | 在容器启动的时候,会执行的命令,例如:redis镜像,一定有redis-server ./redis.conf |
2. 第一个案例
构建一个自定义的tomcat镜像,基于tomcat:8.5构建。
(1) 创建dockerfile文件
例如:dockerfile/tomcat/dockerfile-tomcat-1.0
注意:dockerfile到一定要放在一个单独的目录中。
命令:
touch dockerfile-tomcat-1.0
(2) 编写dockerfile指令
# 基础镜像
FROM tomcat:8.5
# 描述
LABEL name="yangdd@zparkhr.com.cn"
LABEL desc="这是一个dockerfile构建的tomcat镜像"
(3) 构建镜像
1. 语法
docker build -t 镜像名:tag -f dockerfile的文件名 .
2. 命令
docker build -t my-tomcat:1.0 -f dockerfile-tomcat-1.0 .
(4) 验证
查看镜像信息
docker inspect 镜像名:tag
3. 详解指令
(1) FROM
基础镜像,本次docker镜像的构建基于From镜像基础之上进行操作。
-
语法
FROM <image>:<tag>
-
说明
-
FROM
必须是Dockerfile文件的第一行指令。 - 用于为镜像文件构建过程指定基础镜像,后续的指令都基于该基础镜像环境运行
- 基础镜像可以是任何一个镜像文件
-
(2) LABEL
镜像描述信息,描述镜像的信息:作者、文字描述、日期、要求数据卷路径,(没有任何docker构建的作用,
仅仅给工作人员看的
)
-
语法
# 形式1: LABEL author="fanqingfuming@zparkhr.com.cn" LABEL desc="这是描述" # 形式2: LABEL name="反清复明" age="18" desc="这是一段image描述"
-
说明
-
LABEL
指令用来给镜像以name=value对的形式添加一些描述信息 - 会集成基础镜像中的
LABEL
属性,通过docker inspect
,name不能重复,如果value相同会被覆盖
-
(3) COPY
从主机(执行docker build)中,拷贝文件或者目录到镜像里面。主机路径?
-
语法
COPY <主机src> <镜像dest>
-
说明
-
<src>
:要复制的源文件或目录,支持通配符 -
<src>
必须在build所在路径或子路径下,不能是其父目录 -
<dest>
:目标路径,即镜像中文件系统的路径 -
<dest>
目录结尾必须以/结尾。
-
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/
(4) ADD
类似COPY,但ADD支持tar包自解压和网络路径。
-
语法
ADD <src> <dest>
-
说明
-
<src>
可以是一个文件,可以是一个目录,也可以是一个网络url路径。 -
<src>
如果是一个压缩文件(tar),被被解压为一个目录,如果是通过URL下载一个文件不会被解压 -
<dest>
必须以/结尾。
-
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/ ADD dir/* /opt/adddir/dir/ ADD https://www.cnblogs.com/azulearncode/p/14043606.html /opt/adddir/ ADD ./jdk-8u291-linux-x64.tar.gz /opt/adddir/dir/
(5) ENV
设置镜像中的环境变量,这个变量可以在镜像中直接使用,也可以给会在镜像中执行的命令使用,后续的dockerfile指令使用。
-
语法
- 定义环境变量
# 一次设置一个 ENV <key>=<value> # 一次设置多个 ENV <key>=<value> <key1>=<value1> <key2>=<value2> .....
- 使用环境变量
$key ${key}
-
说明
- 可以用来定义镜像使用的环境变量
- 也可以为后续的指令,定义shell变量。
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/ ADD dir/* /opt/adddir/dir/ ADD https://www.cnblogs.com/azulearncode/p/14043606.html /opt/adddir/ ADD ./jdk-8u291-linux-x64.tar.gz /opt/adddir/dir/ ENV PATH=$PATH:/opt/adddir/dir/jdk1.8.0_291/bin ENV JAVA_HOME=/opt/adddir/dir/jdk1.8.0_291
(6) WORKDIR
指定创建容器后,终端进入容器后的默认路径,后续的RUN、CMD、ENTRYPOINT、COPY、ADD涉及到的路径,均已此目录作为当前目录。
-
语法
WORKDIR /opt/centos
-
说明
- 如果设置的目录不存在会自动创建,包括他的父目录
- 如果使用相对路径,则相对workdir的路径
-
WORKDIR
也可以调用ENV指定的变量
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/ ADD dir/* /opt/adddir/dir/ ADD https://www.cnblogs.com/azulearncode/p/14043606.html /opt/adddir/ ADD ./jdk-8u291-linux-x64.tar.gz /opt/adddir/dir/ ENV PATH=$PATH:/opt/adddir/dir/jdk1.8.0_291/bin ENV JAVA_HOME=/opt/adddir/dir/jdk1.8.0_291 WORKDIR ${JAVA_HOME}
(7) RUN
构建
镜像
过程中,需要执行的命令,可以用来安装依赖,初始化脚本执行等。
-
语法
# 语法1,shell 形式 RUN command1 && command2 RUN yum install -y vim && yum install -y wget # 语法2,exec 形式 RUN ["executable","param1","[param2]"] RUN ["yum","install","-y","vim"] RUN ["yum","install","-y","wget"]
-
说明
-
RUN
在下一次建构期间,会优先查找本地缓存,若不想使用缓存可以通过docker build --no-cache
解除 -
RUN
指令指定的命令是否可以执行取决于 基础镜像中是否允许执行该命令。 - shell形式,可以使用 && 或
\
连接多个命令 - 一个run就会构建一层镜像,尽量减少run个数。如果命令多,尽量使用&&连接。
-
exec
形式,必须使用"“,且第一个命令必须独立是一个命令,后面可以是参数,每个参数独立放在一个”"中。 - 与 shell 形式不同,exec 形式不会调用shell解析。例如
RUN ['echo','$PATH']
这样的指令$PATH
并不会被解析。
-
-
案例
FROM centos:7 LABEL name="反清复明" age="18" desc="这是一段image描述" COPY C.txt /opt/cpdir/ COPY dir/* /opt/cpdir/dir/ ADD dir/* /opt/adddir/dir/ ADD https://www.cnblogs.com/azulearncode/p/14043606.html /opt/adddir/ ADD ./jdk-8u291-linux-x64.tar.gz /opt/adddir/dir/ ENV PATH=$PATH:/opt/adddir/dir/jdk1.8.0_291/bin ENV JAVA_HOME=/opt/adddir/dir/jdk1.8.0_291 WORKDIR ${PATH} RUN ["java","-version"] RUN echo "哈哈" && echo $(date) RUN ['/bin/sh','-c','echo $PATH']