"Dockerfile 入门级教程:如何使用 COPY 和 ADD 优化镜像"

196 阅读8分钟

我正在参加「掘金·启航计划」

👨‍🎓作者:Java学术趴

🏦仓库:GithubGitee

✏️博客:CSDN掘金InfoQ云+社区

💌公众号:Java学术趴

🚫特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系小编授权。

🙏版权声明:文章里的部分文字或者图片来自于互联网以及百度百科,如有侵权请尽快联系小编。微信搜索公众号Java学术趴联系小编。

☠️每日毒鸡汤:那些曾经把我击倒的人,谢谢你们,躺着真舒服。

第五章 Dockerfile

5.1 Dockerfile简介

  • Dockerfile是用于构建Docker镜像的脚本文件,由一系列指令构成。通过docker build命令构建镜像时,Dockerfile中的指令会由上到下依次执行,每条指令都将会构建出一个镜像,这就是镜像分层。因此,指令越多,层次越多,创建的镜像就越多,效率就越低。所以,在创建 Dockerfile文件时,能在一个指令完成的动作不要分为两条。

5.2 Dockerfile注意点

  • Dockerfile命令不区分大小写,但是推荐使用大写。
  • Dockerfile中可以使用 # 符号添加注释,注释从 # 开始,到行末结束。注释可以提高 Dockerfile 的可读性和可维护性。
  • Dockerfile中的指令顺序很重要,因为每个指令都会生成一个新的镜像层。一般情况下,应先设置基础镜像,再安装依赖,拷贝文件,设置环境变量等。
  • Dockerfile中,应尽量合并多个操作,以减少镜像层数。可以将多个 RUN 操作合并成一个,使用&&连接多个命令。
  • 清理不必要的文件:在使用 COPY 或 ADD 指令时,要尽量只复制必要的文件,并在复制前清理不需要的文件,以减少镜像的大小。
  • 使用 .dockerignore 文件:可以使用 .dockerignore 文件来忽略不需要复制到镜像中的文件和目录,以减少镜像的大小。
  • 指定标签:在构建镜像时,应使用 -t 参数给镜像打上标签,以便后续引用和管理。

5.3 Dockerfile指令

5.3.1 FROM

指令功能:

  • FROM指令用于指定当前镜像的基础镜像。

指令语法:

  • 简单语法格式:

    
    FROM <image>
    

    这种格式的 FROM 指令指定了当前镜像的基础镜像。例如:

    
    FROM ubuntu:20.04
    

    这个命令使用了简单格式的 FROM 指令,并将 ubuntu:20.04 镜像作为当前镜像的基础镜像。需要注意的是,使用简单格式的 FROM 指令时,如果没有指定标签,则默认使用 latest 标签。

  • 复杂语法格式:

    
    FROM <image>[:<tag>] [AS <name>]
    

    这种格式的 FROM 指令除了指定基础镜像之外,还可以指定标签和别名。例如:

    
    FROM ubuntu:20.04 AS base
    

    这个命令使用了复杂格式的 FROM 指令,并将 ubuntu:20.04 镜像作为当前镜像的基础镜像,并将其命名为 base。

指令注意:

  • FROM指令必须作为 Dockerfile 中的第一条指令,且每个 Dockerfile 只能有一个 FROM 指令。这是因为每个 Docker 镜像都必须基于一个基础镜像构建,而 FROM指令就是用于指定该基础镜像的。
  • 使用简单、复杂语法的时候,如果没有指定镜像的标签,默认使用的都是 latest 标签。

5.3.2 RUN

指令功能:

  • 该指令用于在容器内部执行命令或操作。

指令语法:

  • 简单语法格式:

    
    RUN <command>
    

    这种写法的 RUN 指令用于在容器内部执行命令或操作。例如:

    
    RUN apt-get update && apt-get install -y curl
    

    这个命令将在容器内部执行 apt-get update 和 apt-get install -y curl 两个命令,用于更新软件源并安装 curl 工具。

  • 复杂语法格式:

    
    RUN ["<executable>", "<param1>", "<param2>", ...]
    

    这种写法的 RUN 指令也用于在容器内部执行命令或操作,但是使用了 JSON 数组的形式指定命令和参数。例如:

    
    RUN ["apt-get", "update"]
    RUN ["apt-get", "install", "-y", "curl"]
    

    这个命令与前面的例子相同,分别在容器内部执行 apt-get update 和 apt-get install -y curl 两个命令。

指令注意:

  • 每个 RUN 指令都会创建一个新的镜像层,因此建议将多个命令合并成一个命令,以减少镜像层数和镜像大小。

  • 为了减小镜像大小,可以将不必要的文件和中间文件删除,并使用 && 连接多个命令,以在单个 RUN 指令中执行多个操作。例如:

    
    RUN apt-get update && apt-get install -y curl \
        && apt-get clean && rm -rf /var/lib/apt/lists/*
    

    这个命令将在容器内部执行更新软件源、安装 curl、清理缓存和删除不必要的文件等多个操作,并在单个 RUN 指令中完成。

  • JSON 数组形式的 RUN 指令将整个命令和参数列表都作为一个字符串传递给解释器执行,因此需要确保命令和参数列表中的引号和转义符正确。此外,JSON 数组形式的 RUN 指令也可以避免在命令和参数中使用空格等特殊字符时的问题。

5.3.3 COPY

指令功能:

  • 该指令用于将本地文件或目录复制到容器中。

指令语法:

  • 简单语法格式:

    
    COPY <src> <dest>
    

    其中, 是要复制的本地文件或目录路径, 是容器内部的目标路径。例如:

    
    COPY app.py /app/
    

    此外,COPY 指令还支持一些可选的参数,例如:

    • --chown=::设置复制后的文件或目录的用户和组;
    • --from=:从另一个镜像中复制文件或目录。

    例如,以下命令将从名为 base-image 的镜像中复制 /app/ 目录到当前镜像中的 /app/ 目录,并设置复制后的文件或目录的用户和组为 www-data:www-data:

    
    COPY --chown=www-data:www-data --from=base-image /app/ /app/
    
  • 复杂语法格式:

    
    COPY ["<src>", "<dest>"]
    

    这种写法的 COPY 指令也用于将本地文件或目录复制到容器中,但是使用了 JSON 数组的形式指定源文件和目标路径。例如:

    
    COPY ["app.py", "/app/"]
    

    这个命令与前面的例子相同,将本地的 app.py 文件复制到容器内部的 /app/ 目录中。

指令注意:

  • 如果 是一个目录,则会将该目录及其内容复制到容器内部的 目录中。如果 包含多个文件,则 必须是一个目录,否则会出现错误。
  • JSON 数组形式的 COPY 指令将整个源文件和目标路径作为一个字符串传递给解释器执行,因此需要确保文件路径中的引号和转义符正确。此外,JSON 数组形式的 COPY 指令也可以避免在文件路径中使用空格等特殊字符时的问题。

5.3.4 ADD

指令功能:

  • ADD指令用于将本地文件或者远程文件复制到镜像中。

指令语法:

  • 简单语法格式:

    
    ADD <src> <dest>
    

    这种格式的 ADD 指令可以将本地的 文件或目录复制到镜像中的 路径中,例如:

    
    ADD app.tar.gz /app/
    

    这个命令将本地的 app.tar.gz 文件复制到镜像的 /app/ 目录中,并自动解压缩文件(如果需要)。

    需要注意的是,使用简单格式的 ADD 指令时,如果 是一个 URL,则 Docker 将尝试下载并复制该文件或目录。但是,这种方式不推荐使用,因为它会使构建上下文变得更大,并可能导致构建速度变慢。

  • 复杂语法格式:

    ADD ["<src>", "<dest>"]
    

    这种格式的 ADD 指令与简单格式类似,但是使用了 JSON 数组的形式,并将 和 包装在双引号中。例如:

    ADD ["app.tar.gz", "/app/"]
    

    这个命令与前面的例子相同,将本地的 app.tar.gz 文件复制到镜像的 /app/ 目录中,并自动解压缩文件(如果需要)。

指令注意:

  • ADD 指令会自动解压缩压缩文件(如 tar、gzip、bzip2 等),并且可以递归地复制目录和子目录。但是,如果您只需要复制单个文件,可以使用 COPY 指令代替 ADD 指令,因为 COPY 指令比 ADD 指令更简单、更可预测,不会自动解压缩文件,也不会执行任何复杂的操作。

  • ADD 指令会使镜像构建上下文(包括指定的源文件或目录)变得更大,而且可能会导致镜像构建速度变慢,因此建议仅在必要时使用 ADD 指令。如果您只需要将文件或目录复制到镜像中,可以使用 COPY 指令或者使用 RUN 指令执行 cp 命令来实现。

  • 在使用 ADD 命令将远程文件添加到 Docker 镜像中时,如果指定的目标路径是一个目录,则必须在路径末尾添加一个斜杠 /,否则会出现以下错误:

    
    ADD failed: stat /var/lib/docker/tmp/docker-builder[...]: no such file or directory
    

    因此,为了确保目标路径是一个有效的目录,必须在路径末尾添加一个斜杠 / ,这样 Docker 将识别目标路径为一个目录,并在复制文件时自动创建该目录(如果不存在)。

  • 使用复杂格式的 ADD 指令时,在 Dockerfile 中使用双引号是必需的,以确保解析 JSON 格式的正确性。此外,复杂格式的 ADD 指令还可以在 <src> 中使用通配符(例如 *.txt)来复制一组文件。

以上项目的源代码,点击星球进行免费获取 星球 (Github地址)如果没有Github的小伙伴儿。可以关注本人微信公众号:Java学术趴,发送jQuery,免费给发给大家项目源码,代码是经过小编亲自测试的,绝对可靠。免费拿去使用

--------看完的大佬们可以关注一下小编,会一直更新小技巧,免费分享给大家呦!!!---------

点击星球可快速进入小编的Github星球呦!!里边还有更多好玩的技术,等待大家去探索呦!!