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;

ADD arr[[]0].txt /mydir/

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

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

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

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

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

分析

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

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

func Match(pattern, name string) (matched bool, err error)

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

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示例:

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"))
}

运行结果如下:

true 
false 

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

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

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

你可能感兴趣的:(docker,docker,golang)