当前位置: 首页 > news >正文

Dockerfile指令详解

Dockerfile 文件详解

用于构建镜像。

常用指令介绍

1、FROM

定制的镜像都是基于 FROM 的镜像,就是基础镜像。

2、RUN

用于执行后面跟着的命令行命令。

在构建过程中**在镜像中**执行命令。也就是构建镜像时运行的指令。

执行结束后, commit 这一层的修改,构成新的镜像。

有以下俩种格式:

# 1、shell 格式:
RUN <命令行命令>
# 备注: <命令行命令> 等同于,在终端操作的 shell 命令。## 2、exec 格式:
RUN ["可执行文件", "参数1", "参数2"]
# 例如:RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

简单的例子:

FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。

例如:

FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz

以上执行会创建 3 层镜像。可简化为以下格式:

FROM centos
RUN yum -y install wget \&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \&& tar -xvf redis.tar.gz

如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。

最简单例子:

$ docker build -t nginx:v3 .

上下文路径说明

上下文路径(就是上面的点 " . "),是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。

解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

3、LABEL

添加镜像的元数据,使用键值对的形式。

注意

也可以使用 MAINTAINER ,指定Dockerfile的作者/维护者,但是已弃用,推荐使用 LABEL 指令。

4、CMD

指定容器创建时的默认命令。(可以被覆盖)

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在docker run 时运行。
  • RUN 是在 docker build。

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

格式:

CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

5、ENTRYPOINT

设置容器创建时的主要命令。(不可被覆盖)

运行容器时执行的shell命令。

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

格式:

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。

示例:

假设已通过 Dockerfile 构建了 nginx:test 镜像:

FROM nginxENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参 
  1. 不传参运行
$ docker run nginx:test# 容器内会默认运行以下命令,启动主进程。
nginx -c /etc/nginx/nginx.conf
  1. 传参运行
$ docker run nginx:test -c /etc/nginx/new.conf# 容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)
nginx -c /etc/nginx/new.conf

6、EXPOSE

声明容器运行时监听的特定网络端口。

仅仅只是声明端口。

作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

格式:

EXPOSE <端口1> [<端口2>...]

7、ENV

在容器内部设置环境变量。

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

格式:

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

以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:

ENV NODE_VERSION 7.2.0RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

8、ADD

将文件、目录或远程URL复制到镜像中。

拷贝文件或目录到容器中,如果是URL或压缩包便会自动下载或自动解压。

ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

9、COPY

将文件或目录复制到镜像中。

拷贝文件或目录到容器中,跟ADD类似,但不具备自动下载或解压的功能。

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

格式:

COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]

[–chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。

<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

COPY hom* /mydir/
COPY hom?.txt /mydir/

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

10、VOLUME

为容器创建挂载点或声明卷。

指定容器挂载点到宿主机自动生成的目录或其他容器。

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。

格式:

VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

11、WORKDIR

设置后续指令的工作目录。

为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录,就是切换目录。

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

格式:

WORKDIR <工作目录路径>

12、其它命令

USER、ARG、ONBUILD、STOPSIGNAL、HEALTHCHECK、SHELL


99、实践总结

总结一
  • RUN

    我们在使用 Dockfile构建镜像时,就是通过 RUN 来构建镜像层,每执行一行 RUN 命令,就会构建一层镜像,其命令也是在该层镜像层中执行的。常用于安装软件包、下载文件等操作。

    执行时机就是 docker build 命令执行时候,比如:

    RUN yum install -y net-tools vim
    
  • CMD

    提供容器启动时默认执行的命令或参数,如果运行容器时指定了其他命令,则 CMD 指定的默认命令会被覆盖。

    记住

    • 只能有一个 CMD 指令在 Dockerfile 中生效(如果有多个,只有最后一个会起作用)。
    • CMD 可以被 docker run 命令行参数覆盖。

    CMD 支持三种格式,但最常用的是提供一个默认的可执行文件及其参数:

    # 格式:CMD ["executable","param1","param2"]# 执行python文件
    CMD ["python", "app.py"]
    

    执行时机就是 docker run 命令执行时候。

    Tips

    我们知道,镜像就是由多个镜像层堆叠起来,就是由多个 RUN命令执行构建的。我们启动容器就是在启动我们自己的服务,肯定只有最后的 CMD 指令起作用,这样才有意义。

    再者,我们再执行 docker run 时候,其实也是在构建最后一层镜像,然后添加各种参数,比如 -p-v等等之类的。

  • ENTRYPOINT

    配置容器启动时要运行的命令,并且这个命令不会被 docker run 命令行参数覆盖。它更倾向于定义容器的主要任务是什么。

    • 类似于 CMD,但是更不容易被覆盖,旨在为容器提供一个固定的入口点。
    • 使用 --entrypoint 标志可以在运行时覆盖 ENTRYPOINT。

    形式:同样支持三种格式,最常见的是使用 JSON 数组来指定命令和参数:

    ENTRYPOINT ["executable", "param1", "param2"]# 运行Java
    ENTRYPOINT ["java", "-jar", "/app/myapp.jar"]
    

对比

  • RUN 是在构建阶段执行命令,目的是修改镜像。
  • CMD 提供了容器启动时默认执行的命令,但容易被覆盖。
  • ENTRYPOINT 设定容器的主命令,不易被覆盖,适合明确容器的主要功能。

结合使用:可以将 ENTRYPOINTCMD 结合使用,其中 ENTRYPOINT 定义应用本身,而 CMD 则定义传递给该应用的默认参数。这样,用户可以通过覆盖 CMD 来更改参数,但不改变应用本身。

FROM ubuntu
ENTRYPOINT ["echo", "Hello"]
CMD ["world"]

运行容器时不带额外参数会输出 “Hello world”,但如果运行时指定参数如 docker run <image> User,则输出 “Hello User”。


总结二
  • COPY

    简单地将文件或目录,从主机系统复制到镜像中指定的位置。

    • 直观且易于理解,主要用于将本地文件复制到镜像中。
    • 支持通配符(如 *.txt),可以方便地选择多个文件。
    • 不会自动解压归档文件(如 .tar.gz 文件)。
    • 对于简单的文件复制任务,推荐使用 COPY
  • ADD

    除了可以完成与 COPY 相同的任务外,还提供了一些额外的功能。

    • 可以自动解压缩本地的 .tar.tar.gz 等格式的归档文件到目标位置(注意:对于远程 URL 下载的归档文件不会自动解压)。
    • 支持通过 URL 添加远程文件到镜像中(不过通常不推荐这样做,因为这可能引起构建不稳定的问题,例如网络问题导致构建失败)。
    • 如果源路径是一个可识别的 Git 仓库,ADD 还会尝试克隆该仓库而不是直接复制内容(但同样,这不是最佳实践,建议明确控制依赖项)。

对比

  • 功能差异COPY 更加直接,仅限于将本地文件复制到镜像内;而 ADD 提供了更多高级功能,比如自动解压归档文件和支持从远程 URL 获取资源。
  • 透明度和安全性:由于 ADD 的一些高级特性可能导致不可预期的行为(如自动解压),因此对于只需简单复制文件的情况,使用 COPY 更加透明和安全。
  • 性能考虑ADD 自动解压归档文件可能会增加不必要的处理时间,尤其是在不需要解压的情况下。

使用建议

  • 当你需要将本地文件复制到 Docker 镜像时,除非需要 ADD 的特殊功能(如自动解压或从 URL 加载文件),否则优先选择 COPY。这样可以使 Dockerfile 更加简洁明了,并减少潜在的错误来源。

  • 如果需要添加一个 .tar.tar.gz 归档文件并希望它被自动解压,或者想要从 URL 添加资源,那么 ADD 就是更合适的选择。


总结三
  • EXPOSE

    指定容器将监听的网络端口。这个指令并不会实际发布(port publish)端口。

    它只是一个**声明**,告知使用者该镜像内的服务将会监听哪些端口。

    在运行时并不会因为这个声明应用就会开启这个端口的服务。

    • 可以指定TCP或UDP协议,默认为TCP。
    • 实际上暴露端口需要在运行容器时通过 -p--publish 参数来完成。
    EXPOSE 80/tcp
    EXPOSE 53/udp
    
  • VOLUME

    创建一个挂载点,用于绑定宿主机的一个目录到容器内,或者指定容器内的数据卷(data volume),主要用于持久化数据或共享数据。

    比较重要

    如果你仅在 Dockerfile 中使用 VOLUME 指令而不指定宿主机上的具体路径,Docker 会自动为该容器创建一个数据卷,并将其挂载到指定的容器目录。这种情况下,Docker 管理这个数据卷的位置,通常位于宿主机文件系统的特定区域(例如,在 Linux 上可能是 /var/lib/docker/volumes/)。

    这种方式的好处在于简化了数据持久化的过程,因为你不需要手动指定宿主机的路径,同时也能确保数据独立于容器的生命周期存在。

    VOLUME ["/data"]
    # 或者多路径
    VOLUME ["/data1", "/data2"]
    
    • 数据卷允许你在容器之间共享和重用数据。
    • 宿主机上的文件或目录可以被挂载到容器中指定的位置,从而使得数据能够在容器重启后仍然存在。
    • 使用 -v--volume 在运行容器时指定具体的宿主机路径。

    比如mysql:

    VOLUME /var/lib/mysql
    
  • WORKDIR

    设置工作目录。后续的 RUN, CMD, ENTRYPOINT, COPY 和 ADD 指令都会在这个目录下执行。如果目录不存在,WORKDIR 会帮你创建它。

    WORKDIR /path/to/workdir
    
    • 可以多次使用 WORKDIR,路径是相对前面的 WORKDIR 设置进行累加的,也可以直接给出绝对路径。
    • 改变工作目录对于组织复杂的构建过程非常有用,并且可以让 Dockerfile 更加清晰易读。
    WORKDIR /app
    RUN npm install
    COPY . .
    CMD ["npm", "start"]
    

完毕。

模板例子

Java服务模板

FROM openjdk:8-jre
MAINTAINER wangxf <1437211236@qq.com>
VOLUME /tmp
WORKDIR /app
COPY /target/your-app-name-server.jar your-app-name-serve.jar
EXPOSE 8090
# ENTRYPOINT ["java", "-Dspring.profiles.active=test", "-jar", "your-app-name-serve.jar"]
ENTRYPOINT ["java", "-jar", "your-app-name-serve.jar"]

实际例子:

FROM dockette/jdk8
MAINTAINER wangxf <1437211236@qq.com>
VOLUME /temp # 用于存放我们的附件
WORKDIR /app
COPY target/app.jar app.jar
EXPOSE 8090
ENTRYPOINT ["java", "-jar", "app.jar"]
# 把当前Dockerfile下target文件下的app复制到容器的工作目录

上面这种是制作镜像的流程,既是把 app.jar 做成一个镜像(虽然上面没有使用 RUN 命令,其实也可以使用),使用命令 docker build -t app:latest . 就可以生成镜像,使用 docker images 查看镜像。然后使用 docker run 去运行镜像,运行命令:

docker run -itd -p 8090:8090 -v /opt/server/ttt:/temp --name app app
# app 是我们生成的镜像名称,默认版本为:app:latest

其实还有一种就是,不使用 docker build -t app:latest . 命令生成镜像,直接运行 jdk8 的基础镜像,然后做目录挂载,直接运行我们的服务,这样就可以不用生成镜像,一定层面上减少存储空间的使用,这种情况就不能使用 Dockerfile 文件,必须使用 docker-compose.yml 文件,或者直接使用 docker run 命令。

  • docker-compose.yml 文件:该文件是运行多个容器服务,或者说管理容器服务,是使用镜像,具体见 Compose介绍

  • 直接使用 docker run 命令:

    docker run -itd -p 8090:8090 -v /opt/server/ttt:/temp -v /opt/server/target:/app -w /app --name app dockette/jdk8 java -jar app.jar
    

    上面就是直接运行我们的 dockette/jdk8 镜像,并不是我们做的镜像,这种方式也可以;

    当然还是推荐使用 docker-compose.yml 文件,如果有特殊需求可以先制作镜像(比如安装环境),然后再使用镜像。


完毕。

http://www.xdnf.cn/news/571231.html

相关文章:

  • 打卡第二十四天
  • Swagger在java的运用
  • PostgreSQL 日常维护
  • Elasticsearch常用命令
  • 宁夏建设工程专业技术职称评审条件
  • 嵌入式Linux:移植使用scp指令
  • Java多线程深度解析:从核心机制到高阶实战
  • upload-labs通关笔记-第16关 文件上传之exif_imagetype绕过(图片马)
  • springcloud集成seata报错Error creating bean with name ‘globalTransactionScanner‘
  • 解决RedisTemplate的json反序列泛型丢失问题
  • SpringAI开发SSE传输协议的MCP Server
  • 安卓开发用到的设计模式(1)创建型模式
  • OpenCv高阶(十四)——LBPH人脸识别
  • 如何用 Qwen1.5-7B-Chat 模型打造高效轻量的 Python 智能助手(详细实操指南)
  • Windows在PowerShell或CMD运行 curl 命令报错 解决办法 (zx)
  • 如何支持Enhanced RTMP H.265(HEVC)
  • 蓝耘Ubantu服务器测试最新 PP-StructureV3 教程
  • linux 查看java的安装路径
  • Java面试问题基础篇
  • Wireshark 抓包工具使用
  • Visual Studio Code插件离线安装指南:从市场获取并手动部署
  • Android Framework学习八:SystemServer及startService原理
  • 鸿蒙开发——9.wrapBuilder与@BuilderParam对比解析
  • Oracle 11g post PSU Oct18 设置ssl连接(使用jks)
  • 拉普拉斯高斯(LoG)滤波器掩模的注意事项
  • 计及可再生能源不确定性的经济优化调度方法
  • AI与IT从业者的关系更似“进化催化剂“而非“职业终结者“
  • 太阳能电池IV测试设备AAA型AMG1.5太阳光模拟器
  • 道可云人工智能每日资讯|浙江省人民政府印发《关于支持人工智能创新发展的若干措施》
  • [特殊字符] 遇见Flask