Docker学习笔记:DockerFile
本文是自己的学习笔记
- 1、基本概念
- 2、DockerFile的执行流程
- 3、关键字介绍
- 3.1、CMD和ENTRYPOINT的区别
- 4、DockerFile运用示例
- 4.1、DockerFile
- 4.2、构建镜像
1、基本概念
DockerFile
是用来构建Docker
镜像的构建文件,它里面是一系列的命令和参数组成的脚本。
基本上流行的镜像都有自己的一套dockerFile
,下图是centos
的dockerFile
。
DockerFile
的指令遵循下面四个规则。
- 关键字必须大写,并且后面必须跟至少一个参数。比如
FROM openjdk8-jdk-bullseye
,或者RUN mkdir -p "$CATALINA_HOME/bin:$PATH
。 - 指令从上到下执行。
#
表示注释- 每条指令都会穿件一个新的镜像层,并对镜像提交。
我们以Tomcat
镜像的DockerFile
为例,下面是其开头的五行指令。
FROM openjdk:8-jdk-bullseye
ENV CATALINA_HOME /us/local/tomcat
ENV PATH §CATALINA_HOME/bin: $PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME
执行FROM openjdk:8-jdk-bullseye
时,Tomcat
就加了一层镜像。执行完这五条,Tomcat
就加了五层镜像。
2、DockerFile的执行流程
docker执行一个Dockerfile脚本的流程大致如下:
- docker从基础镜像运行一个容器
- 执行一条指令并对容器作出修改
- 执行类似docker commit的操作提交一个新的镜像层
- docker再基于刚提交的镜像运行一个新的容器
- 执行dockerfile中的下一条指令直到所有指令都执行完成
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
- Dockerfile是软件的原材料
- Docker镜像是软件的交付品
- Docker容器则可以认为是软件的运行态。
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
3、关键字介绍
指令 | 说明 |
---|---|
FROM | 基础镜像,当前新镜像是基于哪个镜像的,有继承的意味。 比如我们可以写 FROM tomcat 或者FROM centos |
MAINTAINER | 镜像维护者的姓名和邮箱地址 |
RUN | 容器构建时需要运行的命令。 比如 RUN mkdir test 。 |
EXPOSE | 当前容器对外暴露的端口 |
WORKDIR | 指定在创建容器后,终端默认登录的进来工作目录,一个落脚点 |
ENV | 用来在构建镜像过程中设置环境变量 |
ADD | 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包 |
COPY | 类似ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置 COPY src dest COPY [“src”,“dest”] |
VOLUME | 容器数据卷,用于数据保存和持久化工作 |
CMD | 指定一个容器启动时要运行的命令 Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换 |
ENTRYPOINT | 指定一个容器启动时要运行的命令 ENTRYPOINT的目的和CMD一样,只能有一个,但是其不会被docker run之后的参数替换 |
ONBUILD | 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发 |
3.1、CMD和ENTRYPOINT的区别
CMD
和ENTRYPOINT
都会用来执行命令。但却有很大的不同。
DockerFile
中可以有多个CMD
指令,但只有最后一个生效。并且CMD
会被docker run
之后的参数替换掉。
比如在tomcat
镜像中,其DockerFile
的最后部分是这样的。
RUN set -e \&& nativeLines="$(catalina.sh configtest 2›&1)" \&& nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')" \ && nativeLines="$(echo "$nativeLines" | sort -u)" \&& if ! echo "$nativeLines" | grep 'INFO: Loaded APR based Apache Tomcat Native library'echo >&2 "$nativeLines"; \ exit 1; \fi
EXPOSE 8080
CMD ["catalina.sh", "run"]
如果我们启动tomcat
镜像时,在后面加了其他的linux指令,比如加上ls -l
docker run -it -p 8888:8080 tomcat ls -l
那这个指令的执行效果就相当于
RUN set -e \&& nativeLines="$(catalina.sh configtest 2›&1)" \&& nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')" \ && nativeLines="$(echo "$nativeLines" | sort -u)" \&& if ! echo "$nativeLines" | grep 'INFO: Loaded APR based Apache Tomcat Native library'echo >&2 "$nativeLines"; \ exit 1; \fi
EXPOSE 8080
CMD ["catalina.sh", "run"]
CMD ls -l
并且CMD
只有最后一个会生效,所以这个镜像创建的tomcat
容器不会正常启动,因为启动tomcat
的语句CMD ["catalina.sh", "run"]
没有生效。
ENTRYPOINT
和CMD
基本一样,但是ENTRYPOINT
不会被docer run
之后的命令替换。
## 3.2、COPY和ADD的区别 ```COPY```和```ADD```的功能都是复制文件。但```ADD```有一些隐藏的自动功能,平时```COPY```使用得更频繁。
COPY
的功能很纯粹,就是将文件原封不动的复制到指定位置;而ADD
在复制文件时,如果文件是压缩文件则会自动解压。
另外COPY
只能支持复制本地文件;而ADD
支持URL,但URL安全性不保证。
下面是具体的差别。
特性 | COPY | ADD | 最佳实践建议 |
---|---|---|---|
复制源 | 仅限本地文件/目录 | 本地文件/目录,也支持 URL | 优先使用 COPY ,因为它更简单、透明,且行为可预测。 |
自动解压 | 不会,原样复制 | 如果是本地可识别的压缩文件,会自动解压 | 如果需要解压本地压缩文件,推荐先用 COPY 复制,然后使用 RUN tar -xzf <file> && rm <file> 命令手动解压。这样可以精确控制解压过程,并能在同一层中清理源文件,避免镜像膨胀。 |
URL 支持 | 不支持 | 支持 | 不推荐使用 ADD 来下载 URL。 更好的做法是使用 RUN curl -SL <URL> -o <dest_path> 或 wget 。这种方式能让你更好地控制下载过程(例如验证哈希值),并且可以在下载后立即清理临时文件,有效控制镜像大小。 |
透明性 | 高度透明,行为明确 | 相对不透明,有隐藏的自动行为(如自动解压) | COPY 的行为更直观,更易于理解和调试。 |
安全性 | 较低的安全风险 | 潜在的安全风险(如从不受信任的 URL 下载、自动解压可能存在的漏洞) | COPY 更安全,因为它将文件处理限制在构建上下文内。 |
缓存利用 | 通常更好,更易于 Docker 缓存 | 自动解压或 URL 下载的特性可能导致缓存失效或行为不确定 | 建议使用 COPY 以充分利用 Docker 的缓存机制,加速镜像构建。 |
4、DockerFile运用示例
4.1、DockerFile
这里我们会基于官方的迷你版的centos
自定义一个新的镜像。因为mini的不带有vim
等基本命令,我们自定义的版本会通过DockerFile
安装好这些基本的配置。
我们先写好DockerFile
FROM centos:centos7ENV MYPATH /usr/local
WORKDIR $MYPATHRUN yum -y install vimEXPOSE 80CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash
脚本内容还是比较简单的,其中核心的就是RUN yum -y install vim
,安装一个vim
4.2、构建镜像
指定刚才写的脚本文件dockerFileVim
来构建镜像
docker build -f dockerFileVim -t mycentos:1.0
下图可以看到执行步骤。
这时候输入docker images
就可以看到我们建立的镜像,通过这个镜像创建的centos
容器就能直接运行vim
命令。