Dockerfile 增强新语法

Dockerfile 是使用 Docker 的相关开发人员的基本工具,用来充当构建 Docker 镜像的模板,在这个文件中包含用户可以在命令行上调用来构建镜像的所有命令。了解并有效利用 Dockerfile 可以显着简化开发流程,实现镜像创建的自动化并确保不同开发阶段的环境一致。Dockerfile 对于定义 Docker 容器内的项目环境、依赖项和应用程序配置至关重要。

借助新版本的 BuildKit 构建器工具包、Docker Buildx CLI 和 BuildKit v1.7.0 版本的 Dockerfile 前端,开发人员现在可以访问增强的 Dockerfile 功能。本文我们将深入探讨这些新的 Dockerfile 功能,并解释如何在项目中利用它们来进一步优化 Docker 工作流程。

版本控制

在开始之前,我们先快速提醒一下 Dockerfile 的版本控制方式以及您应该执行哪些操作来更新它。

尽管大多数项目使用 Dockerfile 来构建镜像,但其实 BuildKit 不仅限于该格式。BuildKit 支持多个不同的前端来定义 BuildKit 要处理的构建步骤。任何人都可以创建这些前端,将它们打包为常规容器镜像,并在调用构建时从注册表加载它们。

在新版本中,我们向 Docker Hub 发布了两个此类镜像:docker/dockerfile:1.7.0docker/dockerfile:1.7.0-labs

要使用新特性,您需要在文件开头指定 #syntax 指令,以告诉 BuildKit 用于构建的前端镜像。这里我们将其设置为使用最新的 1.x.x 主要版本,例如:

# syntax=docker/dockerfile:1.x.x

FROM alpine
...

这意味着 BuildKit 与 Dockerfile 前端语法解耦,您可以立即开始使用新的 Dockerfile 特性,而不必担心您正在使用哪个 BuildKit 版本。只要您在 Dockerfile 顶部定义正确的 #syntax 指令,本文中描述的所有示例都适用于任何支持 BuildKit 的 Docker 版本。

您可以在文档中 了解有关 Dockerfile 前端版本的更多信息。

变量扩展

编写 Dockerfile 时,构建步骤可以包含使用构建参数 (ARG) 和环境变量 (ENV) 指令定义的变量。构建参数和环境变量之间的区别在于,环境变量保留在生成的镜像中,并在从中创建容器时持续存在。

当您使用此类变量时,您很可能在 COPYRUN 和其他命令中使用 **${NAME},或者 $NAME。您可能不知道 Dockerfile 支持两种形式的类似 Bash 的变量扩展:

  • ${variable:-word}: 如果变量未设置,则将值设置为 word
  • ${variable:+word}: 如果变量已设置,则将值设置为 word

到目前为止,这些特殊形式在 Dockerfile 中并没有多大用处,因为 ARG 指令的默认值可以直接设置:

FROM alpine
ARG foo="default value"

如果您是各种 Shell 专家,您就会知道 Bash 和其他工具通常具有许多附加形式的变量扩展,以简化脚本的开发。

在 Dockerfile v1.7 中,我们就添加了一部分这样的功能。现在,您可以在 Dockerfile 中使用以下形式的变量扩展:

  • ${variable#pattern} 和 ${variable##pattern} 从变量值中删除最短或最长的前缀
  • ${variable%pattern} 和 ${variable%%pattern} 从变量值中删除最短或最长的后缀
  • ${variable/pattern/replacement} 替换最先出现的 pattern 模式
  • ${variable//pattern/replacement} 替换所有出现的 pattern 模式

这些规则的使用方式一开始可能并不完全明显。让我们看一下实际 Dockerfile 中的一些示例。例如,项目通常无法就下载依赖项的版本是否应具有 v 前缀达成一致,下面的方式可以允许您获取所需的格式:

# example VERSION=1.2.3
ARG VERSION=${VERSION#v}

# VERSION is now 1.2.3

又比如下面的这个示例中同一个 VERSION 变量我们可以在不同的地方多次使用:

ARG VERSION=v1.7.13
ADD https://github.com/containerd/containerd/releases/download/${VERSION}/containerd-${VERSION#v}-linux-amd64.tar.gz /

有的时候我们可能希望不同平台的构建配置不同的命令行,这时候我们就可以使用 BuildKit 提供的内置变量,例如 TARGETOSTARGETARCH。但是需要注意并非所有项目都使用相同的值,例如,在容器和 Go 生态中,我们将 64 位 ARM 架构称为 arm64,但有时您需要 aarch64,这个时候我们就可以使用 ${variable/pattern/replacement} 来进行替换:

ADD https://github.com/oven-sh/bun/releases/download/bun-v1.0.30/bun-linux-${TARGETARCH/arm64/aarch64}.zip /

接下来让我们看看新的扩展如何在多阶段构建中发挥作用。

如果您构建多平台镜像并希望仅针对特定平台运行其他 COPYRUN 命令,则可以使用该模式。简而言之,其想法是定义一个全局构建参数,然后定义构建阶段,在阶段名称中使用构建参数值,同时通过构建参数名称指向目标阶段的基础。

以前的方式如下所示:

ARG BUILD_VERSION=1

FROM alpine AS base
RUN …

FROM base AS branch-version-1
RUN touch version1

FROM base AS branch-version-2
RUN touch version2

FROM branch-version-${BUILD_VERSION} AS after-condition

FROM after-condition
RUN …

使用此模式进行多平台构建时,限制之一是 build-arg 的所有可能值都需要由 Dockerfile 定义。因为我们希望 Dockerfile 的构建方式可以在任何平台上构建,而不是将其限制在特定的平台上,所以这种方式会有一些限制。

通过新的扩展,我们可以来演示仅在 RISC-V 上运行特殊命令,这仍然有些新,可能需要自定义行为:

#syntax=docker/dockerfile:1.7

ARG ARCH=${TARGETARCH#riscv64}
ARG ARCH=${ARCH:+"common"}
ARG ARCH=${ARCH:-$TARGETARCH}

FROM --platform=$BUILDPLATFORM alpine AS base-common
ARG TARGETARCH
RUN echo "Common build, I am $TARGETARCH" > /out

FROM --platform=$BUILDPLATFORM alpine AS base-riscv64
ARG TARGETARCH
RUN echo "Riscv only special build, I am $TARGETARCH" > /out

FROM base-${ARCH} AS base

我们再仔细看下上面的这些 ARCH 定义:

  • 第一个将 ARCH 设置为 TARGETARCH,但从该值中删除 riscv64
  • 我们实际上并不希望其他架构使用它们自己的值,而是希望它们都共享一个共同的值。因此,我们将 ARCH 设置为 common,除非它已从之前的 riscv64 规则中清除。
  • 现在,如果我们仍然有一个空值,我们将其默认为 $TARGETARCH
  • 最后一个定义是可选的,因为我们已经为这两种情况提供了唯一值,但它使最终阶段名称 base-riscv64 更易于阅读。

和老的方式相比新模式不仅限于控制构建的平台差异,而且可以与任何构建参数一起使用。如果您以前使用过此模式,那么您现在可以有效地定义 else 子句,而以前,您只能使用 if 子句。

复制并保留父目录

以下功能已在 labs 频道中发布的,需要在 Dockerfile 顶部定义以下内容以使用此功能。

#syntax=docker/dockerfile:1.7-labs

例如,当我们在 Dockerfile 中复制文件时,可以这样做:

COPY app/file /to/dest/dir/

此示例意味着源文件直接复制到目标目录,如果源路径是一个目录,则该目录中的所有文件都将直接复制到目标路径。

如果您有如下所示的文件结构怎么办:

.
├── app1
│   ├── docs
│   │   └── manual.md
│   └── src
│       └── server.go
└── app2
    └── src
        └── client.go

您只想复制 app1/src 中的文件,但目标位置的最终文件将是 /to/dest/dir/app1/src/server.go 而不仅仅是 /to/dest/dir/server.go

使用新的 COPY --parents 标志,我们可以这样来实现:

COPY --parents /app1/src/ /to/dest/dir/

这将复制 src 目录中的文件并为这些文件重新创建 app1/src 目录结构。

此外我们还可以使用通配符路径,比如我们要将两个 app 的 src 目录复制到各自的位置,可以这样实现:

COPY --parents */src/ /to/dest/dir/

这将创建 /to/dest/dir/app1/to/dest/dir/app2,但不会复制 docs 目录。以前,使用单个命令无法实现这种复制。您可能需要单个文件的多个副本,或者使用 RUN --mount 指令的一些解决方法。

同样还可以使用 ** 来匹配任何目录结构下的文件,例如,要仅将 Go 源代码文件复制到构建上下文中的任何位置,可以这样实现:

COPY --parents **/*.go /to/dest/dir/

可能你会想为什么需要复制特定文件而不是直接使用 COPY ./ 来复制所有文件,记住,当您在构建中包含新文件时,构建缓存会失效。如果复制所有文件,则当添加或更改任何文件时,缓存就会失效,而如果仅复制 Go 文件,则只有这些文件中的更改会影响缓存。

新的 --parents 标志不仅适用于构建上下文中的 COPY 指令,当使用 COPY --from 在多阶段之间复制文件时,还可以在多阶段构建中使用它们。

需要注意的是,使用 COPY --from 语法,所有源路径都应该是绝对的,这意味着如果 --parents 标志与此类路径一起使用,它们将像在源阶段一样被完全复制。这可能并不总是可取的,相反,您可能想保留一些父级,但丢弃并更换其他父级。在这种情况下,可以在源路径中使用特殊的 /./ 来标记您希望复制哪些父级以及应忽略哪些父级。这个特殊的路径组件类似于 rsync 如何与 --relative 标志一起工作。

#syntax=docker/dockerfile:1.7-labs
FROM ... AS base
RUN ./generate-lot-of-files -o /out/
# /out/usr/bin/foo
# /out/usr/lib/bar.so
# /out/usr/local/bin/baz

FROM scratch
COPY --from=base --parents /out/./**/bin/ /
# /usr/bin/foo
# /usr/local/bin/baz

上面的示例显示了如何从中间阶段生成的文件集合中仅复制 bin 目录,但所有目录将保留其相对于 out 目录的路径。

排除过滤器

该功能特性已在 labs 频道中发布的,需要在 Dockerfile 顶部定义以下内容以使用此功能。

#syntax=docker/dockerfile:1.7-labs

使用 COPYADD 指令在 Dockerfile 中移动文件时的另一个相关场景是当您想要移动一组文件但排除特定子集时。以前,您唯一的选择是使用 RUN --mount 或尝试在 .dockerignore 文件中定义排除的文件。

然而 .dockerignore 文件并不是解决此问题的好方法,因为它们仅列出从客户端构建上下文中排除的文件,而不是从远程 Git/HTTP URL 的构建中排除的文件,并且每个 Dockerfile 仅限一个。我们可以像 .gitignore 一样使用它们来忽略不属于您的项目的文件,但不能作为定义特定于应用程序的构建逻辑的方法。

使用新的 --exclude=[pattern] 标志,现在可以直接在 Dockerfile 中为 COPYADD 命令定义此类排除过滤器。该模式使用与 .dockerignore 相同的格式。

以下示例是复制目录中除 Markdown 文件之外的所有文件:

COPY --exclude=*.md app /dest/

我们可以多次使用该标志来添加多个过滤器,比如不包括 Markdown 文件和名为 README 的文件:

COPY --exclude=*.md --exclude=README app /dest/

使用 ** 双星通配符不仅排除复制目录中的 Markdown 文件,还排除任何子目录中的 Markdown 文件:

COPY --exclude=**/*.md app /dest/

与在 .dockerignore 文件中一样,还可以使用 ! 前缀可以定义排除的例外情况。以下示例排除任何复制目录中的所有 Markdown 文件,除非该文件名为 important.md — 在这种情况下,它仍然会被复制。

COPY --exclude=**/*.md --exclude=!**/important.md app /dest/

当将 --exclude 与前面描述的 --parents 复制模式一起使用时,请注意排除模式是相对于复制的父目录。例如有以下目录结构:

assets
├── app1
│   ├── icons32x32
│   ├── icons64x64
│   ├── notes
│   └── backup
├── app2
│   └── icons32x32
└── testapp
    └── icons32x32

我们可以定义如下的 Dockerfile:

COPY --parents --exclude=testapp assets/./**/icons* /dest/

该指定将创建以下目录结构,仅复制带有 icons 前缀的目录,根父目录的 assets 被跳过,此外,testapp 未被复制,因为它是使用排除过滤器定义的。

dest
├── app1
│   ├── icons32x32
│   └── icons64x64
└── app2
    └── icons32x32

总结

本文我们介绍了 Dockerfile 的一些新功能,这些功能可以帮助您更好地控制 Dockerfile 中的构建步骤,使其更加灵活和强大。记住,即使尚未更新到最新的 Docker,您的 Dockerfile 今天也可以通过定义顶部的 #syntax 来开始使用所有这些功能。

来源:k8s技术圈 原文链接: https://www.docker.com/blog/new-dockerfile-capabilities-v1-7-0/ 本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/905892.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【搜索引擎】俄罗斯搜索引擎yandex

俄罗斯搜索引擎yandex 1997年,俄罗斯搜索引擎Yandex(俄语意为:语言目录)首次上线,已发展成为全球第四大搜索引擎和第二大非英语搜索引擎 https://yandex.com/

Vue v-on

vue : v-on:func --------------------------- data(){ return{ prop:any; } } methods:{ func(){ } } template:, v-on

【django】django RESTFramework前后端分离框架快速入门

目录 一、搭建项目开发环境 1.1 pycharm创建项目 1.2 修改配置settings.py 1.3 新增 static与staticfiles文件夹 1.4 生成数据表 1.5 创建超级用户 1.6 启动项目 二、安装REST_Framework 2.1 安装 2.2 配置settings 2.3 重新执行生成数据库脚本 三、修改路由 四、s…

基于centos7.9搭建MariaDB10.5高可用集群

MariaDB-HA 环境初始化安装MariaDB配置集群 基于centos7.9搭建MariaDB10.5数据库高可用集群,对标mysql5.7 节点IPnode1192.168.200.101node2192.168.200.102node3192.168.200.103 环境初始化 #!/bin/bash# 定义节点信息 NODES("192.168.200.101 node1"…

WAF+AI结合,雷池社区版的强大防守能力

网上攻击无处不不在,为了保护我自己的网站,搜索安装了一个开源免费的WAF 刚安装完成就收到了海外的攻击,看到是海外的自动化攻击工具做的 雷池刚好也有AI分析,于是就尝试使用这个功能,看看这个ai能力到底怎么样 以下…

服务器宝塔安装哪吒监控

哪吒文档地址:https://nezha.wiki/guide/dashboard.html 一、准备工作 OAuth : 我使用的gitee,github偶尔无法访问,不是很方便。第一次用了极狐GitLab,没注意,结果是使用90天,90天后gg了,无法登…

ThingsBoard规则链节点:Math Function节点详解

引言 1. Math Function 节点简介 2. 节点配置 2.1 基本配置示例 3. 使用场景 3.1 数据预处理 3.2 阈值判断 3.3 复杂计算 3.4 动态阈值 4. 实际项目中的应用 4.1 项目背景 4.2 项目需求 4.3 实现步骤 5. 总结 引言 ThingsBoard 是一个开源的物联网平台&#xff0c…

Spark入门到实践

Spark入门到实践 一、Spark 快速入门1.1 Spark 概述1.2 Spark 最简安装1.3 Spark实现WordCount1.3.1 下载安装Scala1.3.2 添加Spark依赖1.3.3 Scala实现WordCount1.3.4 通过IDEA运行WordCount1.3.5 IDEA配置WordCount输入与输出路径1.3.6 通过IDEA运行WordCount1.3.7 查看运行结…

.NET 9 AOT的突破 - 支持老旧Win7与XP环境

引言 随着技术的不断进步,微软的.NET 框架在每次迭代中都带来了令人惊喜的新特性。在.NET 9 版本中,一个特别引人注目的亮点是 AOT( Ahead-of-Time)支持,它允许开发人员将应用程序在编译阶段就优化为能够在老旧的 Win…

网络层之IP协议,它带来了哪些功能,真的能顺着网线找到?

前言 在上一篇,学习了链路层的以太网协议,知道了MAC地址,在以太网中,找到对应的终端最终依靠的是MAC地址,但是在实际使用中,大家可能发现并不是使用的MAC地址,而是IP协议,比如 &…

linux之网络子系统- 内核发送数据包流程以及相关实际问题

一、相关实际问题 查看内核发送数据消耗的CPU时应该看sy还是si在服务器上查看/proc/softirqs,为什么NET_RX要比NET_TX大得多发送网络数据的时候都涉及那些内存拷贝操作零拷贝到底是怎么回事为什么Kafka的网络性能很突出 二、网络包发送过程总览 调用系统调用send发…

使用WebStorm开发Vue3项目

记录一下使用WebStorm开发Vu3项目时的配置 现在WebStorm可以个人免费使用啦!🤩 基本配置 打包工具:Vite 前端框架:ElementPlus 开发语言:Vue3、TypeScript、Sass 代码检查:ESLint、Prettier IDE&#xf…

操作系统及MySQL管理系统客户端的介绍

操作系统 1、Windows: 图形化管理工具:如控制面板、设置应用、任务管理器等。 客户端:命令提示符(cmd)和PowerShell用于命令行操作。 2、Linux: 图形化管理工具:如GNOME、KDE等桌面环境中的系…

基于SSM+小程序的旅游社交登录管理系统(旅游4)

👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 ​ 本旅游社交小程序功能有管理员和用户。管理员有个人中心,用户管理,每日签到管理,景点推荐管理,景点分类管理,防疫查询管理&a…

一文带你了解:六款适合PC端的工时管理工具

1. 板栗看板 板栗看板是一个可视化的事项管理工具,由看板(board)、列表(list)、卡片(card)三个基本元素构成。用户通过在 “看板” 上布置和移动 “列表” 与 “卡片”,可以跟踪事项…

数据结构算法学习方法经验总结

DSA:Data Structures, Algorithms, and Problem-Solving Techniques 三大核心支柱 一次学习一个主题,按照如下顺序学习 如何开始学习新的主题 学习资源 https://www.youtube.com/playlist?listPLDN4rrl48XKpZkf03iYFl-O29szjTrs_O (Algorithms) https://ww…

ANA基因组数据库(ANAgdb)

ANA进化阶由早期发育的被子植物谱系组成,包括无油樟目(Amborellales)、睡莲目(Nymphaeales)和木兰藤目(Austrobaileyales),在进化上具有重要地位。 ANA基因组数据库(ANA…

晟矽微PWM案例分析

/****************************************************************************** ; * 型号 : MC32F7361 ; * 创建日期 : 2021.12.21 ; * 公司/作者 : SINOMCU-FAE ; * 晟矽微技术支持 : 204…

检索引擎Elasticsearch

一.为什么要用Elasticsearch 由于我们在运行我们的项目的时候通常都是将数据存到mysql或者sql serve等数据库中,在进行数据搜索时使用sql 语句 like进行模糊匹配查询,其一:虽然可以查到数据,但是它模糊匹配查询速度较慢&#xff0…

vue前端使用pdfjs与pdfdist-mergeofd 实现预览pdf并翻页,同时解决预览pdf显示模糊的问题

vue前端使用pdfjs与pdfdist-mergeofd 实现预览pdf并翻页,同时解决预览pdf显示模糊的问题 插件介绍 pdfdist-mergeofd插件的作用可查看这篇文章,同时使用ofdjs和pdfjs遇到的问题,和解决方法——懒加载 该插件主要是为了解决pdfjs和ofdjs同时…