packer学习—用Docker构建器构建docker镜像

前言:packer是根据HCL模板构建容器镜像的
注:HCL2 模板最初是作为 Packer 版本 1.5 的 beta 功能引入的。从 v1.7 开始,HCL2 支持不再处于测试阶段,并且是编写 Packer 配置的首选方式。对于老式的稳定配置语言,请参阅模板文档。从 v1.6.2 开始,您可以使用 hcl2_upgrade 命令将旧 JSON 模板转换为 HCL2 配置文件。
所以只有1.5版本以后的packer才支持HCL模板

一、 安装packer

官方文档:Packer官方网站

1.Packer 可以通过以下方式安装:

  • 使用预编译的二进制文件。Packer官方为所有受支持的平台和架构发布二进制文件。建议大多数用户使用此方法。
  • 从源安装。此方法仅推荐给高级用户。
  • 使用系统的包管理器。

2.如何安装预编译的二进制文件

1.思路:

(1)要安装预编译的二进制文件,请为您的系统下载适当的软件包。 Packer 当前打包为 zip 文件。
(2)下载 Packer 后,解压缩包。 Packer 作为一个名为 packer 的二进制文件运行。(解压后可直接运行)
(3)最后,确保打包程序二进制文件在您的 PATH 中可用。(即将packer移动到你的系统环境变量PATH的目录下)
tip:如何确保打包程序二进制文件在您的 PATH 中可用
分两步:
①首先打印系统环境目录(环境位置以冒号隔开):

echo $PATH
#测试
[root@zsh bin]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

将 Packer 二进制文件移动到列出的位置之一。(此命令假定二进制文件当前位于您的下载文件夹中,并且您的 PATH 包含 /usr/local/bin,但如果您的位置不同,您可以自定义它)。

mv ~/Downloads/packer /usr/local/bin/
2.演示:这里在Linux系统中进行packer安装演示:

如何下载:不同平台的packer下载方法
①在centos7.9下安装packer,执行以下命令

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install packer

②在进行yum安装完packer后,会自动进行解压,解压后的二进制文件就是packer。

#下载完packer的默认存储路径为/usr/bin/目录下
#如何查看是否下载安装包成功呢,列出所有安装包,用grep筛选
[root@zsh~]# rpm -qa|grep packer
packer-1.8.0-1.x86_64
#查看安装包路径
[root@zsh ~]# rpm -ql packer-1.8.0-1.x86_64
/usr/bin/packer

#现在将packer移动到/usr/local/bin/目录下
mv usr/bin/packer /usr/local/bin/

③将packer移动到/usr/local/bin/后,验证packer。

#命令:packer -v
#测试
[root@zsh bin]# packer -v
1.8.0
#或者直接输入packer
[root@zsh bin]# packer
Usage: packer [--version] [--help] <command> [<args>]

Available commands are:
    build           build image(s) from template
    console         creates a console for testing variable interpolation
    fix             fixes templates from old versions of packer
    fmt             Rewrites HCL2 config files to canonical format
    hcl2_upgrade    transform a JSON template into an HCL2 configuration
    init            Install missing plugins or upgrade plugins
    inspect         see components of a template
    plugins         Interact with Packer plugins and catalog
    validate        check that a template is valid
    version         Prints the Packer version

二、 构建docker镜像(Build Image)

安装 Packer 后,是时候构建您的第一个映像了,您将构建一个 Docker 容器。如果你没有安装 Docker,你可以在这里下载它Docker

1.编写 Packer 模板

注意:编写Packer模板前要确认packer版本>=1.5,否则无法解析HCL语言

Packer 模板是一个配置文件,它定义了您要构建的映像以及如何构建它。 Packer 模板使用 Hashicorp 配置语言 (HCL)。

①创建一个名为 packer_tutorial 的新目录。该目录将包含本教程的 Packer 模板。

 mkdir packer_tutorial

②导航到packer_tutorial目录。

cd packer_tutorial

③创建一个文件 docker-ubuntu.pkr.hcl。

touch docker-ubuntu.pkr.hcl

④将以下 HCL 块添加到其中并保存文件。

这是一个完整的 Packer 模板,您将使用它来构建 Ubuntu Docker 映像。在以下部分中,您将更详细地查看此模板的每个块。

packer {
  required_plugins {
    docker = {
      version = ">= 0.0.7"
      source = "github.com/hashicorp/docker"
    }
  }
}

source "docker" "ubuntu" {
  image  = "ubuntu:xenial"
  commit = true
}

build {
  name    = "learn-packer"
  sources = [
    "source.docker.ubuntu"
  ]
}

2.初始化 Packer 配置

1.packer init .
packer init .

Packer 将下载您在上面定义的插件。在这种情况下,Packer 将下载大于 0.0.7 版本的 Packer Docker 插件

3.格式化并验证您的 Packer 模板

1.格式化模板
packer fmt .
2.验证模板
packer validate .

4.构建 Packer 映像

1.构建镜像
packer build docker-ubuntu.pkr.hcl
2.列出所有镜像
docker images

5.过程演示图
目录结构
文件目录结构
HCL模板

构建镜像

三、使用配置器将软件安装和配置到您的映像(镜像)中

在上一教程中,您使用 Packer 创建了第一个容器映像。但是,您构建的映像实质上是重新打包了现有的 Docker 映像。 Packer 的真正实用性是自动配置,以便在将软件转换为映像之前在机器中安装和配置软件。

在本教程中,您将使用配置器设置环境变量并在 Docker 映像中创建文件。虽然定义环境变量和在 Docker 映像中创建文件只是一个小示例,但它应该让您了解 Packer 配置程序可以做什么

1.Prerequisite(先决条件)

本教程基于前面的教程继续操作,如果没有进行前面操作,请先进行以下操作。

①安装packer

②编写HCL模板

创建一个名为 packer_tutorial 的目录并将以下配置粘贴到名为 docker-ubuntu.pkr.hcl 的文件中。

packer {
  required_plugins {
    docker = {
      version = ">= 0.0.7"
      source = "github.com/hashicorp/docker"
    }
  }
}

source "docker" "ubuntu" {
  image  = "ubuntu:xenial"
  commit = true
}

build {
  name    = "learn-packer"
  sources = [
    "source.docker.ubuntu"
  ]
}

③初始化Packer模板配置(pcaker init .)

packer init .

2.Add provisioner to template(将配置器添加到模板)

使用配置器可以让您完全自动化对镜像的修改。您可以使用 shell 脚本、文件上传以及与现代配置管理工具(例如 Chef 或 Puppet)的集成。

要编写您的第一个配置程序,请将以下块添加到您的 Packer 模板中,在构建块内部源分配下方(即build内,source下方)

provisioner "shell" {
  environment_vars = [
    "FOO=hello world",
  ]
  inline = [
    "echo Adding file to Docker Container",
    "echo \"FOO is $FOO\" > example.txt",
  ]
}
#这个块定义了一个 shell 配置器,它在 shell 执行环境中设置一个名为 FOO 的环境变量,并运行 inline 属性中的命令。此配置程序将创建一个名为 example.txt 的文件,其中包含 FOO is hello world。

您的构建块应该为:

build {
  name    = "learn-packer"
  sources = [
    "source.docker.ubuntu"
  ]
  provisioner "shell" {
    environment_vars = [
      "FOO=hello world",
    ]
    inline = [
      "echo Adding file to Docker Container",
      "echo \"FOO is $FOO\" > example.txt",
    ]
  }
}

添加后为:

packer {
  required_plugins {
    docker = {
      version = ">= 0.0.7"
      source = "github.com/hashicorp/docker"
    }
  }
}
source "docker" "ubuntu" {
  image  = "ubuntu:xenial"
  commit = true
}
#构建器
build {
  name    = "learn-packer"
  #源分配
  sources = [
    "source.docker.ubuntu"
  ]
   provisioner "shell" {
    environment_vars = [
      "FOO=hello world",
    ]
    inline = [
      "echo Adding file to Docker Container",
      "echo \"FOO is $FOO\" > example.txt",
    ]
  }
}

3.Build image(构建修改后的镜像)

使用配置器构建镜像

packer build docker-ubuntu.pkr.hcl

操作过程
从packer的输出中可以清晰地看到进行的改动信息。

在输出中,您将找到使用 shell 脚本进行配置,确认 Packer 运行了配置步骤。注意 Packer 如何输出第一个内联命令(将文件添加到 Docker 容器)。

4.Verify update image(验证更新后的镜像)

通过使用 Docker 运行镜像来验证镜像。
首先查找Image ID,并修改镜像标签(新建的镜像是没有REPOSITORY和TAG的,可以根据创建时间判断哪个是我们新建的镜像)

[root@zsh packer_tutorial]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
<none>        <none>    4637a109718e   13 minutes ago   135MB
<none>        <none>    f9d33370206f   11 hours ago     135MB
hello-world   latest    feb5d9fea6a5   6 months ago     13.3kB
ubuntu        xenial    b6f507652425   7 months ago     135MB
[root@zsh packer_tutorial]# docker tag 4637a109718e ubuntu_update:xenial_addfile
[root@zsh packer_tutorial]# docker images
REPOSITORY      TAG              IMAGE ID       CREATED          SIZE
ubuntu_update   xenial_addfile   4637a109718e   14 minutes ago   135MB
<none>          <none>           f9d33370206f   11 hours ago     135MB
hello-world     latest           feb5d9fea6a5   6 months ago     13.3kB
ubuntu          xenial           b6f507652425   7 months ago     135MB

②要验证配置器在新镜像中创建了 example.txt 文件,首先启动新创建的 Docker 镜像。在终端中将 IMAGE_ID 替换为上面显示的值(如上面的输出所示,本地等效于 4637a109718e)。

docker run -it IMAGE_ID
//测试,启动镜像后就会进入ubuntu容器,此时容器就是一个ubuntu操作系统实例(启动ubuntu容器实例,进入shell终端)
[root@zsh packer_tutorial]# docker run -it 4637a109718e
#

③在 Docker 容器Shell中,打印 example.txt 文件的内容。这应该返回 FOO is hello world 正如预期的那样。

cat example.txt

//测试
#启动添加了example.txt文件的镜像,生成Ubuntu容器实例
[root@zsh packer_tutorial]# docker run -it 4637a109718e
# ls
bin   dev  example.txt  lib    media  opt           proc  run   srv  tmp  var
boot  etc  home         lib64  mnt    packer-files  root  sbin  sys  usr
#  cat example.txt
FOO is hello world
#

过程截图如下:
启动ubuntu容器实例,进入shell终端
启动ubuntu容器实例,进入shell终端
④退出容器

exit

在这里插入图片描述

5.总结

  • 上面演示的 shell 配置器非常强大和灵活。对于复杂的配置,您可以传递整个 shell 脚本,而不是上面显示的内联声明。

  • 您可以根据需要运行任意数量的配置器。配置器按照声明的顺序运行。

  • 用以下内容替换现有的构建块。这会在构建块的末尾添加一个配置器,它将在 shell 执行环境中打印一条消息。

build {
  name    = "learn-packer"
  sources = [
    "source.docker.ubuntu"
  ]

  provisioner "shell" {
    environment_vars = [
      "FOO=hello world",
    ]
    inline = [
      "echo Adding file to Docker Container",
      "echo \"FOO is $FOO\" > example.txt",
    ]
  }

  provisioner "shell" {
    inline = ["echo This provisioner runs last"]
  }
}

HCL模块分析

  • Build and verify updated image(构建并验证更新的镜像)

    再次构建镜像。

packer build docker-ubuntu.pkr.hcl

在这里插入图片描述
上面第二个配置器中仅显示预期的信息,没有执行其他操作,此时再查看又多了一个镜像

#查看镜像,最新的就是我们新构建的镜像。(最上面那个)
[root@zsh packer_tutorial]# docker images
REPOSITORY      TAG              IMAGE ID       CREATED         SIZE
<none>          <none>           d1d39530765d   3 minutes ago   135MB
ubuntu_update   xenial_addfile   4637a109718e   2 hours ago     135MB
<none>          <none>           f9d33370206f   13 hours ago    135MB
hello-world     latest           feb5d9fea6a5   6 months ago    13.3kB
ubuntu          xenial           b6f507652425   7 months ago    135MB

四、Variables变量

  • 在上一个教程中,您实现了第一个配置器。但是,您的 Packer 模板是静态的。目前如果你想改变文件的内容,你需要手动更新你的模板。

  • 您可以使用输入变量作为 Packer 构建的参数,允许在不更改 Packer 模板的情况下自定义构建的各个方面。此外,当您想要在整个模板中引用特定值时,Packer 变量很有用。

  • 在本教程中,您将添加 Packer 变量来参数化您的 Packer 构建,使其更加健壮。

  • 总结:就是将packer模板中的参数用变量替代,没有写死,在需要更改的时候直接改变量的值

  • 此外,当您想要在整个模板中引用特定值时,Packer 变量很有用。

  • 在本教程中,您将添加 Packer 变量来参数化您的 Packer 构建,使其更加健壮。

  • 总结:就是将packer模板中的参数用变量替代,没有写死,在需要更改的时候直接改变量的值

1.Prerequisites(先决条件)

本教程假设您从前面的教程继续学习。如果没有执行,执行2.3的先决条件中的操作。

①安装packer

②编写HCL模板

创建一个名为 packer_tutorial 的目录并将以下配置粘贴到名为 docker-ubuntu.pkr.hcl 的文件中。

packer {
  required_plugins {
    docker = {
      version = ">= 0.0.7"
      source = "github.com/hashicorp/docker"
    }
  }
}

source "docker" "ubuntu" {
  image  = "ubuntu:xenial"
  commit = true
}

build {
  name    = "learn-packer"
  sources = [
    "source.docker.ubuntu"
  ]

  provisioner "shell" {
    environment_vars = [
      "FOO=hello world",
    ]
    inline = [
      "echo Adding file to Docker Container",
      "echo \"FOO is $FOO\" > example.txt",
    ]
  }

  provisioner "shell" {
    inline = ["echo This provisioner runs last"]
  }
}

③初始化Packer模板配置(pcaker init .)

packer init .

2.Add variable to template(将变量添加到模板)

将以下变量块添加到您的 docker-ubuntu.pkr.hcl 文件中。

variable "docker_image" {
  type    = string
  default = "ubuntu:xenial"
}

变量块声明变量名称(docker_image)、数据类型(字符串)和默认值(ubuntu:xenial)。虽然变量类型和默认值是可选的,但我们建议您在创建新变量时定义这些属性。

将 Packer 变量视为常量——您不能在运行时更新它们。

在您的 Packer 模板中,更新您的源代码块以引用 docker_image 变量。请注意模板如何将变量引用为
var.docker_image(通过var.变量名来引用变量)
在这里插入图片描述
更新第二个配置器以打印 docker_image 变量。请注意,即使在上面的源代码块中直接使用了 docker_image 变量,要将变量嵌入到另一个字符串中,您需要使用语法 ${} 对其进行模板化,如在配置程序块中回显 docker_image 时所示。
在这里插入图片描述

添加后模板如下

packer {
  required_plugins {
    docker = {
      version = ">= 0.0.7"
      source = "github.com/hashicorp/docker"
    }
  }
}
#定义变量块
variable "docker_image" {
  type    = string
  default = "ubuntu:xenial"
}

source "docker" "ubuntu" {
  image