Dockerfile详解

一、介绍

1.基于dockerfile创建

  • dockerfile是由一组指令组成的文件。

  • dockerfile结构四部分

    • 基础镜像信息
    • 维护者信息
    • 镜像操作指令
    • 容器启动时执行指令
  • dockerfile每行支持一条指令,每条指令可携带多个参数,支持使用以“#”号开头的注释

二、操作指令

1642039184753

1.ADD和COPY的区别

COPY只能用于复制,ADD复制的同时,如果复制的对象是压缩包,ADD还可以解压。但是COPY比ADD节省资源。

2.CMD和ENTRYPOINT的区别

CMD设置容器启动后默认执行的命令及其参数,但CMD能够被docker run后面跟的命令行参数替换(覆盖)。如果docker run没有指定任何的执行命令或者dockerfile里面也没有entrypoint,那么就会使用cmd指定的默认执行命令执行。cmd命令只有最后一个会生效。
entrypoint指定容器启动时要执行的命令,可以追加命令。entrypoint指定的命令需要与docker run启动容器进行搭配,将docker run指令后面跟的内容当做参数作为entrypoint指令指定的运行命令的参数,entrypoint指定的linux命令一般是不会被覆盖的。entrypoint指令并不是必须的,因为它会增加复杂度。

总结:
CMD 是容器环境启动时默认加载的命令。
ENTRYPOINT 是容器环境启动时第一个加载的命令程序/脚本程序 init(init pid 1)

如果 ENTRYPOINT 使用了 shell 模式,CMD 指令会被忽略。
如果 ENTRYPOINT 使用了 exec 模式,CMD 指定的内容被追加为 ENTRYPOINT 指定命令的参数。
如果 ENTRYPOINT 使用了 exec 模式,CMD 也应该使用 exec 模式。
ENTRYPOINT ["sh","-c","echo $HOME"]

三、docker镜像的分层

1642325681780

镜像不是一个单一的文件,而是有多层构成。容器其实是在镜像的最上面加了一层读写层,在运行容器里做的任何文件改动,都会写到这个读写层。如果删除了容器,也就删除了其最上面的读写层,文件改动也就丢失了。Docker 使用存储驱动管理镜像每层内容及可读写层的容器层。

  • Dockerfile 中的每个指令都会创建一个新的镜像层

  • 镜像层会被缓存和复用(下一层执行完后的缓存会给上一层使用)

  • 当 Dockerfile 的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效
    如果某层命令修改了,当前缓存层会失效,上层引用当前缓存层的也会失效,需要重构镜像,常用于版本升级(功能修改、添加)

  • 镜像层是不可变的,如果在某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件,只是这个文件在 Docker 容器中不可见了

  • Docker 镜像每一层有唯一的编号,可以通过 docker history 来查看一个镜像由哪些层组成

    查看源图像

四、dockerfile基础编写

例:tomcat镜像

1642326634962

Dockerfile镜像实例 - 丨君丶陌 - 博客园 (cnblogs.com)

五、dockerfile优化

我们在构建镜像的时候会发现官网上下的镜像比我们自己构建的镜像小很多,这是因为官网上下载的镜像都经过了优化,常用的优化方式有以下几种:

  • 不需要输出的指令丢入/dev/null
  • 减少RUN构建
  • 多阶段构建(使用FROM命令生成多个镜像,将指定的镜像做为其他镜像的基础镜像环境来构建)
  • 使用更为轻量级的Linux发行版本(debian,alpine)

未优化之前

image-20220117172036021

不需要输出的指令丢入/dev/null

image-20220117172959713

减少RUN构建

image-20220117173634717

多阶段构建

image-20220117182506409

Dockerfile 是用于构建 Docker 镜像的文本文件,其中包含了按顺序执行的一系列指令。每个指令都会在镜像中创建一个新的层,这使得 Docker 镜像具有分层的结构,可以高效地利用存储空间并加快构建速度[^1]。 ### Dockerfile 的基本结构 Dockerfile 通常由以下几个部分组成: - **基础镜像信息**:使用 `FROM` 指令指定。 - **维护者信息**:可选,使用 `LABEL` 或 `MAINTAINER` 指令指定。 - **镜像操作指令**:如 `RUN`、`COPY`、`ADD` 等,用于对镜像进行操作。 - **容器启动命令**:如 `CMD`、`ENTRYPOINT`,用于指定容器启动时运行的命令。 - **其他配置指令**:如 `WORKDIR`、`ENV`、`EXPOSE`、`VOLUME` 等,用于设置容器的工作环境。 ### Dockerfile 指令详解 #### `FROM` `FROM` 指令用于指定基础镜像,这是 Dockerfile 的第一条指令,并且每个 Dockerfile 至少要有一个 `FROM` 指令。可以指定标签来选择特定版本的基础镜像,也可以使用 `AS` 关键字为构建阶段命名,常用于多阶段构建[^3]。 ```dockerfile FROM ubuntu:20.04 ``` #### `ARG` `ARG` 指令用于定义构建时的变量,可以在构建镜像时通过 `--build-arg` 参数传递值。这些变量可以在 Dockerfile 中被 `RUN` 指令等引用[^2]。 ```dockerfile ARG VERSION=1.0 RUN echo "Version: $VERSION" ``` #### `ENV` `ENV` 指令用于设置环境变量,这些变量在构建过程中以及容器运行时都可用。环境变量可以通过 `$VAR` 的形式在 Dockerfile 中引用。 ```dockerfile ENV MY_PATH /usr/local/myapp WORKDIR $MY_PATH ``` #### `COPY` `COPY` 指令用于将本地文件系统中的文件或目录复制到镜像中的指定路径。支持从构建阶段复制文件(多阶段构建)[^3]。 ```dockerfile COPY . /app ``` #### `WORKDIR` `WORKDIR` 指令用于设置工作目录。后续的 `RUN`、`CMD`、`ENTRYPOINT` 等指令都会在这个目录下执行。如果目录不存在,会被自动创建[^4]。 ```dockerfile WORKDIR /app ``` #### `RUN` `RUN` 指令用于在镜像构建过程中执行命令。这些命令通常用于安装软件包或编译代码[^1]。 ```dockerfile RUN apt-get update && apt-get install -y nginx ``` #### `CMD` `CMD` 指令用于指定容器启动时默认执行的命令。如果有多个 `CMD` 指令,只有最后一个会生效。`CMD` 提供的默认参数可以在运行容器时被覆盖。 ```dockerfile CMD ["nginx", "-g", "daemon off;"] ``` #### `ENTRYPOINT` `ENTRYPOINT` 指令用于配置容器启动时运行的可执行文件。与 `CMD` 不同的是,`ENTRYPOINT` 的参数不会被覆盖,而是将 `CMD` 或运行时提供的参数作为其参数。 ```dockerfile ENTRYPOINT ["nginx", "-g"] CMD ["daemon off;"] ``` #### `LABEL` `LABEL` 指令用于为镜像添加元数据,如版本号、描述等信息。这些标签可以通过 `docker inspect` 命令查看[^2]。 ```dockerfile LABEL version="1.0" LABEL description="This is a sample Dockerfile" ``` #### `EXPOSE` `EXPOSE` 指令用于声明容器运行时监听的端口。虽然它不会自动映射端口,但可以作为文档说明,帮助用户了解容器需要暴露哪些端口[^1]。 ```dockerfile EXPOSE 80 ``` #### `VOLUME` `VOLUME` 指令用于创建挂载点,使数据可以在容器之间共享或持久化。即使容器停止或删除,卷中的数据仍然存在[^4]。 ```dockerfile VOLUME ["/data"] ``` #### `USER` `USER` 指令用于指定运行容器时使用的用户。这有助于提高安全性,避免以 root 用户身份运行容器。 ```dockerfile USER myuser ``` #### `ONBUILD` `ONBUILD` 指令用于设置一个触发器,当该镜像被其他镜像作为基础镜像时,这些触发器会在子镜像构建时自动执行。这对于构建依赖于父镜像的子镜像非常有用。 ```dockerfile ONBUILD COPY . /app ONBUILD RUN make /app ``` ### 多阶段构建 多阶段构建允许在一个 Dockerfile 中使用多个 `FROM` 指令,每个 `FROM` 指令定义一个独立的构建阶段。通过这种方式,可以在一个阶段中编译代码,在另一个阶段中仅包含运行所需的文件,从而减少最终镜像的大小。 ```dockerfile # 第一阶段:构建阶段 FROM golang:1.18 AS builder WORKDIR /app COPY . . RUN go build -o myapp # 第二阶段:运行阶段 FROM alpine:latest WORKDIR /app COPY --from=builder /app/myapp . CMD ["./myapp"] ``` ### 最佳实践 - **最小化镜像大小**:尽量使用轻量级的基础镜像(如 Alpine Linux),并清理不必要的文件和缓存。 - **合理使用缓存**:Docker 在构建镜像时会利用缓存来加速构建过程。为了充分利用缓存,应将不经常变化的指令放在前面。 - **安全性和权限管理**:避免以 root 用户身份运行容器,使用 `USER` 指令指定非特权用户。 - **多阶段构建**:利用多阶段构建减少最终镜像的体积,只保留必要的文件和依赖项。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值