文件配置器
类型: file
Packer 的文件配置器可以将文件上传到由 Packer 构建的机器上。建议使用文件配置器上传文件,然后使用 shell
配置器将它们移动到正确的位置,设置权限等。
警告:您只能上传文件到配置器使用的用户(通常不是root用户)有权限访问的位置。在 /tmp
中创建文件,并使用 shell 配置器将它们移动到目标位置,是上传文件到 root 所拥有的目录的唯一方法。
文件配置器可以上传单个文件,也可以上传整个目录。
基础样例
JSON:
{
"type": "file",
"source": "app.tar.gz",
"destination": "/tmp/app.tar.gz"
}
HCL:
provisioner "file" {
source = "app.tar.gz"
destination = "/tmp/app.tar.gz"
}
配置参数
必填参数:
content
(string) - 这是要复制到目的地的内容。如果 destination
是一个文件,内容将被写入该文件,如果是目录,则会创建一个名为 pkr-file-content
的文件。建议使用文件作为目标。可以在此处使用 templatefile
函数或任何插值语法。该参数不可与 source
或 sources
一同设置。
source
(string) - 要上传到机器的本地文件或目录的路径。路径可以是绝对的或相对的。如果是相对路径,就是相对于 Packer 执行时的工作目录。如果这是一个目录,路径务必以斜杠结尾。下文会详述关于上传目录的内容。除非设置了 sources
,否则必须设置该参数。
destination
(string) - 文件将被上传到机器上的目标路径。位置必须可写,并且所有父级目录必须已经存在。如果配置器使用的用户(通常不是 root)无法写入此目录,您将收到“Permission Denied”错误。如果源是一个文件,那么将最好也把目标设置为文件,但是如果将目标设置为目录,至少要确保目标路径以斜杠结尾,以便 Packer 知道使用源文件的文件名拼接到目标路径之后。否则可能会导致 Packer 无法上传文件。如果目标文件已经存在,它将被覆盖。
选填参数:
sources
([]string) - 要上传的文件夹列表。如果你有多个文件要上传到同一个地方,这可以用来代替source
选项。请注意,目标必须是带尾部斜杠的目录,sources
中列出的所有文件都将上传到同一目录,并保留其文件名。direction
(string) - 文件传输的方向。默认值为upload
。如果设置为download
,则远程机器中的文件source
将下载到本地destination
generated
(bool) - 仅适用于高级用户。如果为true
,则仅在上传前检查文件是否存在,而不是在构建前验证时检查。这允许用户在上传时即时地创建的文件。该参数默认为false
。我们不建议使用此功能,因为它会导致 Packer 变得依赖于系统状态。我们希望您在 Packer 运行之前生成您的文件,但我们也承认在某些情况下这可能是不可避免的。
所有配置器共有的参数:
pause_before
(duration) - 执行前休眠一段时间。max_retries
(int) - provisioner 在失败的情况下重试的最大次数。默认为零 (0)。零表示不会重试错误。only
(array of string) - 只运行列表中指定的的配置器程序。override
(object) - 使用特定配置器的不同设置覆盖配置器,例如:
HCL2:
source "null" "example1" {
communicator = "none"
}
source "null" "example2" {
communicator = "none"
}
build {
sources = ["source.null.example1", "source.null.example2"]
provisioner "shell-local" {
inline = ["echo not overridden"]
override = {
example1 = {
inline = ["echo yes overridden"]
}
}
}
}
Json:
{
"builders": [
{
"type": "null",
"name": "example1",
"communicator": "none"
},
{
"type": "null",
"name": "example2",
"communicator": "none"
}
],
"provisioners": [
{
"type": "shell-local",
"inline": ["echo not overridden"],
"override": {
"example1": {
"inline": ["echo yes overridden"]
}
}
}
]
}
timeout
(duration)- 如果配置器完成时间超过配置值(例如1h10m1s
或10m
),则配置器将超时并失败。
上传目录
file
配置器还能够将完整的目录上传到远程机器。上传目录时,您应该了解一些重要事项。
首先,目标目录必须已经存在。如果您需要创建它,请在运行文件配置器之前使用 shell
配置器来创建目录。如果目标目录不存在,文件配置器可能不会报错,同时引发意外的结果。
接下来,source
路径上尾部是否有斜杠将决定目录名称是否将嵌入到目标路径中,或者是否将创建目标。我们举例说明:
如果 source
是 /foo
(尾部没有斜杠),目标是 /tmp
,那么本地机器上 /foo
的内容将被上传到远程机器上的 /tmp/foo
。远程机器上的 foo
目录将由 Packer 创建。
但是,如果源是 /foo/
(尾部有斜杠),而目标是 /tmp
,那么 /foo
的内容将直接上传到 /tmp
。
此行为源自 rsync。请注意,Packer 在实际运行时,不一定会使用 rsync。
上传在 Packer 运行前还不存在的文件
通常来说,作为 source
的本地文件必须在 Packer 运行之前就已存在。这对于捕获拼写错误并确保构建一旦开始就会成功非常有用。但是,这也意味着您不能在构建期间生成文件,然后再使用文件配置器上传它。一个窍门是上传目录而不是文件。该目录仍然必须存在,但其内容一开始可以不存在。您可以在 Packer 运行期间将生成的文件写入该目录,并在稍后上传。
上传符号链接
上传符号链接时的行为取决于通信器。 Docker 通信器将保留符号链接,但所有其他通信器会将本地符号链接视为常规文件。如果您希望在上传时保留符号链接,建议您使用 tar
。下面是一个可能的例子:
$ ls -l files
total 16
drwxr-xr-x 3 mwhooker staff 102 Jan 27 17:10 a
lrwxr-xr-x 1 mwhooker staff 1 Jan 27 17:10 b -> a
-rw-r--r-- 1 mwhooker staff 0 Jan 27 17:10 file1
lrwxr-xr-x 1 mwhooker staff 5 Jan 27 17:10 file1link -> file1
$ ls -l toupload
total 0
-rw-r--r-- 1 mwhooker staff 0 Jan 27 17:10 files.tar
Json:
{
"provisioners": [
{
"type": "shell-local",
"command": "tar cf toupload/files.tar files"
},
{
"destination": "/tmp/",
"source": "./toupload",
"type": "file"
},
{
"inline": [
"cd /tmp && tar xf toupload/files.tar",
"rm toupload/files.tar"
],
"type": "shell"
}
]
}
HCL2:
build {
sources = [
"source.docker.example"
]
provisioner "shell-local" {
command = "tar cf toupload/files.tar files"
}
provisioner "file" {
destination = "/tmp/"
source = "./toupload"
}
provisioner "shell" {
inline = [
"cd /tmp && tar xf toupload/files.tar",
"rm toupload/files.tar"
]
}
}
通过 WinRM 传输大文件时速度缓慢的问题
由于我们的 WinRM 传输方式的限制,即使是中等大小的文件,上传和下载可能也需要很长时间。如果您在 Windows 上使用 file
配置器时遇到缓慢问题,建议您设置 SSH 服务并使用 ssh
通信器。如果您只想将文件传输给构建的机器,并且您的构建器支持使用 HTTP,您也可以使用 http_directory
或 http_content
指令。这将使构建机可以通过 HTTP 来访问该目录,并将环境变量 PACKER_HTTP_ADDR
设置为该地址。