Dockerfile的ADD指令对中括号转义

文章目录

环境

  • RHEL 9.3
  • Docker Community 24.0.7

背景

在Docker官方文档 https://docs.docker.com/engine/reference/builder/#add 里有这么一段话:

When adding files or directories that contain special characters (such as [ and ]), you need to escape those paths following the Golang rules to prevent them from being treated as a matching pattern. For example, to add a file named arr[0].txt, use the following;

powershell 复制代码
ADD arr[[]0].txt /mydir/

翻译成中文就是:如果添加的文件或目录包含特殊字符(比如 [] ),需要按照Golang的规则进行转义,以避免被当成匹配模式。

例如,想要添加文件 arr[0].txt ,需要转义为 arr[[]0].txt

我测试了一下,确实是这样的,但是这种转义方法实在让人有点费解:

  • 源文件名: arr[0].txt
  • 转义后的文件名: arr[[]0].txt

Docker文档里没说清楚到底是怎么转义的,为此我查了一下Golang的文档,才明白是怎么回事。

分析

在Dockerfile里, ADD 指令的 <src> 参数里可以包含通配符。比如, * 表示"通配任意多个字符", ? 表示"通配任意一个字符"。

所以,显然Docker会采用匹配模式的方式来添加文件和目录。我们知道,Docker是用Go语言开发的。查看Go语言的官方文档,其 filepath.Match() 方法定义如下:

go 复制代码
func Match(pattern, name string) (matched bool, err error)

其第一个参数"pattern"的定义如下:

powershell 复制代码
pattern:
	{ term }
term:
	'*'         matches any sequence of non-Separator characters
	'?'         matches any single non-Separator character
	'[' [ '^' ] { character-range } ']'
	            character class (must be non-empty)
	c           matches character c (c != '*', '?', '\\', '[')
	'\\' c      matches character c

character-range:
	c           matches character c (c != '\\', '-', ']')
	'\\' c      matches character c
	lo '-' hi   matches character c for lo <= c <= hi

可见, [] 是特殊字符, [] 可以包含一个范围,比如 [1-5] 表示1到5。

下面是一个完整的Go示例:

go 复制代码
package main

import (
  "fmt"
  "path/filepath"
)

func main() {
  fmt.Println(filepath.Match("/home/catch[1-5]", "/home/catch2"))
  fmt.Println(filepath.Match("/home/catch[1-5]", "/home/catch8"))
}

运行结果如下:

powershell 复制代码
true <nil>
false <nil>

可见,因为 2[1-5] 范围里,所以返回true,而 8 不在 [1-5] 范围里,所以返回false。

现在,回到Dockerfile。已知源文件名为 arr[0].txt ,如果直接写成:

powershell 复制代码
ADD arr[0].txt dir1/

考一考:实际匹配的源文件名是什么?

答:因为 [] 被Docker当作一个范围,而范围里只有一个数字 1 ,因此只匹配了 1 ,也就是说,实际匹配的源文件名为 arr0.txt

如果有兴趣,可以动手试一试,验证一下结果。

显然,需要对 [] 转义,那么该如何转义呢?

答案:只需用 [][ 括起来。

因为 [] 被Docker当作一个范围,而范围里只有一个字符 [ ,因此只匹配了 [ 。后面的内容不需要再转义了。

因此,整个源文件名转义为 arr[[]0].txt 。这就是文章开头提到的,想要添加文件 arr[0].txt ,需要转义为 arr[[]0].txt

参考

  • https://docs.docker.com/engine/reference/builder/#add
  • https://pkg.go.dev/path/filepath#Match
相关推荐
target酱9 小时前
Docker部署全流程
前端·docker
Anthony_23110 小时前
MySQL的常用命令
运维·数据库·mysql·adb·docker
傻傻虎虎11 小时前
【Docker】常用帮忙、镜像、容器、其他命令合集(1)
运维·docker·容器
2301_7943339111 小时前
Docker Compose 运行 Milvus (Mac) 并与 python 连接测试
macos·docker·milvus
catchadmin14 小时前
开发 PHP 扩展新途径 通过 FrankenPHP 用 Go 语言编写 PHP 扩展
android·golang·php
午夜游鱼16 小时前
Go 泛型实战:一行代码封装 sync.Pool,性能与安全兼得
开发语言·安全·golang
三十_16 小时前
【Docker】学习 Docker 的过程中,我是这样把镜像越做越小的
前端·后端·docker
Lin_Aries_042118 小时前
使用阿里云容器镜像服务 ACR
linux·阿里云·docker·云原生·centos·云计算
MetaverseMan18 小时前
Golang单例模式和工厂模式详解
开发语言·golang·适配器模式
鳄鱼杆1 天前
服务器 | Docker应用开发与部署的实践以及阿里云镜像加速配置
服务器·阿里云·docker