.
Packer
In this HashiQube DevOps lab you will get hands on experience with HashiCorp Packer.
Packer is an open source tool for creating identical machine images for multiple platforms from a single source configuration. Packer is lightweight, runs on every major operating system, and is highly performant, creating machine images for multiple platforms in parallel.
Packer will build a Docker container, use the Shell and Ansible provisioners, Ansible will also connect to Vault to retrieve secrets using a Token.
Keeping track of base images can be challenging. In this whiteboard video, HashiCorp Co-Founder and CTO Armon Dadgar explains how HCP Packer forms the core of a multi-cloud golden image pipeline.
HashiCorp Packer allows you to codify and automate build pipelines for machine images in multiple formats. But how do you make these images discoverable and ensure only the correct versions are deployed to production?
HCP Packer, part of the HashiCorp Cloud Platform, provides a registry that tracks your image metadata and presents it to downstream processes through an API. Together with the Packer data source in the HCP provider for Terraform, this forms the foundation of a multi-cloud golden image pipeline to automate the lifecycle of images from build through deployment.
https://learn.hashicorp.com/vault/getting-started/secrets-engines https://docs.ansible.com/ansible/latest/plugins/lookup/hashi_vault.html
Packer Templates can be found in packer/packer/linux and packer/packer/windows
You can build local Windows and Ubuntu boxes with packer using these commands
You must be in the directory packer
Now you can run ./run.sh
Links
Packer Templates
Packer uses the HashiCorp Configuration Language - HCL - designed to allow concise descriptions of the required steps to get to a build file.
Ubuntu 22.04 Packer Template
packer/linux/ubuntu/ubuntu-2204.pkr.hcl
# Hashicorp Packer
#
# https://www.packer.io/
#
# source blocks are generated from your builders; a source can be referenced in
# build blocks. A build block runs provisioner and post-processors on a
# source. Read the documentation for source blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/source
source "azure-arm" "ubuntu-2204" {
client_id = "${var.azure_client_id}"
client_secret = "${var.azure_client_secret}"
#tenant_id = "${var.azure_tenant_id}"
subscription_id = "${var.azure_subscription_id}"
image_offer = "0001-com-ubuntu-server-jammy"
image_publisher = "Canonical"
image_sku = "22_04-lts-gen2"
image_version = "latest"
managed_image_name = "ubuntu-2204"
location = "${var.azure_region}"
managed_image_resource_group_name = "resourcegroup"
os_type = "linux"
vm_size = "Standard_DS2_v2"
shared_image_gallery_destination {
gallery_name = "SharedImageGallery"
image_name = "ubuntu-2204"
image_version = "${local.azure_version_number}"
replication_regions = ["${var.azure_region}"]
resource_group = "resourcegroup"
}
azure_tags = {
vm_name = "ubuntu-2204"
}
}
source "amazon-ebs" "ubuntu-2204" {
source_ami_filter {
filters = {
name = "*ubuntu-jammy-22.04-amd64-server*"
architecture = "x86_64"
}
owners = ["099720109477"]
most_recent = true
}
access_key = "${var.aws_access_key}"
secret_key = "${var.aws_secret_key}"
region = "${var.aws_region}"
instance_type = "${var.aws_instance_type}"
ssh_username = "ubuntu"
ami_name = "ubuntu-2204-${local.version_number}"
tags = {
vm_name = "ubuntu-2204"
}
}
source "googlecompute" "ubuntu-2204" {
project_id = "${var.gcp_project_id}"
account_file = "${var.gcp_account_file}"
disk_size = "${var.disk_size}"
image_name = "ubuntu-2204-${local.version_number}"
source_image_family = "ubuntu-2204-lts"
ssh_username = "packer"
zone = "${var.gcp_zone}"
image_labels = {
vm_name = "ubuntu-2204"
}
image_family = "soe-ubuntu-2204-lts"
}
source "vagrant" "ubuntu-2204" {
source_path = "ubuntu/jammy64"
template = "linux/ubuntu/templates/ubuntu/2204/Vagrantfile.tpl"
provider = "virtualbox"
teardown_method = "suspend"
skip_package = true
communicator = "ssh"
box_name = "ubuntu-2204"
output_dir = "${var.build_directory}/ubuntu-2204/vagrant"
}
source "docker" "ubuntu-2204" {
image = "ubuntu:22.04"
commit = false
discard = true
}
# a build block invokes sources and runs provisioning steps on them. The
# documentation for build blocks can be found here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/build
build {
sources = ["source.docker.ubuntu-2204", "source.vagrant.ubuntu-2204", "source.azure-arm.ubuntu-2204", "source.amazon-ebs.ubuntu-2204", "source.googlecompute.ubuntu-2204"]
provisioner "shell" {
inline = ["cat /etc/os-release"]
}
provisioner "ansible" {
command = "./scripts/ansible.sh"
extra_arguments = [
"-vvv",
"--tags", "always,day0",
"--extra-vars", "ansible_become=true version_number=${local.version_number}"
]
ansible_ssh_extra_args = [
"-o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedKeyTypes=+ssh-rsa"
]
host_alias = "none"
playbook_file = "../../ansible/roles/ansible-role-example-role/site.yml"
only = ["vagrant.ubuntu-2204", "azure-arm.ubuntu-2204", "googlecompute.ubuntu-2204"]
}
provisioner "ansible" {
command = "./scripts/ansible.sh"
user = "${build.User}"
extra_arguments = [
#"-v",
"--extra-vars", "foo=bar"
]
ansible_ssh_extra_args = [
"-o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedKeyTypes=+ssh-rsa"
]
host_alias = "none"
playbook_file = "../../ansible/galaxy/roles/UBUNTU22-CIS/site.yml"
only = ["vagrant.ubuntu-2204", "azure-arm.ubuntu-2204", "googlecompute.ubuntu-2204"]
}
provisioner "ansible" {
command = "./scripts/ansible.sh"
user = "${build.User}"
extra_arguments = [
#"-v",
"--extra-vars", "foo=bar"
]
ansible_ssh_extra_args = [
"-o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedKeyTypes=+ssh-rsa"
]
host_alias = "none"
playbook_file = "../../ansible/galaxy/roles/UBUNTU22-CIS/site.yml"
only = ["amazon-ebs.ubuntu-2204"]
}
provisioner "shell-local" {
inline = ["curl -s https://api.ipify.org/?format=none"]
}
provisioner "shell" {
execute_command = "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'"
inline = ["/usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync"]
inline_shebang = "/bin/sh -x"
only = ["azure-arm.ubuntu-2204"]
}
}
Windows 2019 Packer Template
packer/windows/windowsserver/windows-2019.pkr.hcl
# Hashicorp Packer
#
# https://www.packer.io/
#
# source blocks are generated from your builders; a source can be referenced in
# build blocks. A build block runs provisioner and post-processors on a
# source. Read the documentation for source blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/source
source "azure-arm" "windows-2019" {
client_id = "${var.azure_client_id}"
client_secret = "${var.azure_client_secret}"
#tenant_id = "${var.azure_tenant_id}"
subscription_id = "${var.azure_subscription_id}"
image_offer = "WindowsServer"
image_publisher = "MicrosoftWindowsServer"
image_sku = "2019-Datacenter"
image_version = "latest"
managed_image_name = "windows-2019"
location = "${var.azure_region}"
managed_image_resource_group_name = "resourcegroup"
os_type = "windows"
vm_size = "Standard_DS2_v2"
communicator = "winrm"
winrm_username = "packer_user"
winrm_insecure = true
winrm_use_ssl = true
shared_image_gallery_destination {
gallery_name = "SharedImageGallery"
image_name = "windows-2019"
image_version = "${local.azure_version_number}"
replication_regions = ["${var.azure_region}"]
resource_group = "resourcegroup"
}
azure_tags = {
vm_name = "windows-2019"
image_version = "${local.version_number}"
}
}
source "amazon-ebs" "windows-2019" {
force_deregister = true
access_key = "${var.aws_access_key}"
secret_key = "${var.aws_secret_key}"
region = "${var.aws_region}"
ami_name = "windows-2019-${local.version_number}"
instance_type = "${var.aws_instance_type}"
user_data_file = "./windows/windowsserver/scripts/bootstrap.txt"
communicator = "winrm"
winrm_username = "Administrator"
winrm_insecure = true
winrm_use_ssl = true
source_ami_filter {
filters = {
name = "Windows_Server-2019-English-Full-Base*"
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = ["801119661308"]
}
}
source "googlecompute" "windows-2019" {
project_id = "${var.gcp_project_id}"
account_file = "${var.gcp_account_file}"
disk_size = "${var.disk_size}"
image_name = "windows-2019-${local.version_number}"
source_image_family = "windows-2019"
communicator = "winrm"
winrm_username = "packer_user"
winrm_insecure = true
winrm_use_ssl = true
zone = "${var.gcp_zone}"
metadata = {
windows-startup-script-cmd = "winrm quickconfig -quiet & net user /add packer_user & net localgroup administrators packer_user /add & winrm set winrm/config/service/auth @{Basic=\"true\"}"
}
image_labels = {
vm_name = "windows-2019"
}
image_family = "soe-windows-2019"
}
source "vagrant" "windows-2019" {
source_path = "jborean93/WindowsServer2019"
provider = "virtualbox"
# the Vagrant builder currently only supports the ssh communicator
communicator = "ssh"
ssh_username = "vagrant"
ssh_password = "vagrant"
teardown_method = "suspend"
skip_package = true
box_name = "windows-2019"
output_dir = "${var.build_directory}/windows-2019/vagrant"
}
# a build block invokes sources and runs provisioning steps on them. The
# documentation for build blocks can be found here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/build
build {
sources = ["source.azure-arm.windows-2019", "source.amazon-ebs.windows-2019", "source.googlecompute.windows-2019", "source.vagrant.windows-2019"]
provisioner "powershell" {
script = "./windows/windowsserver/scripts/ConfigureRemotingForAnsible.ps1"
only = ["azure-arm.windows-2019"]
}
provisioner "ansible" {
command = "./scripts/ansible.sh"
user = "${build.User}"
use_proxy = false
ansible_env_vars = [
"ANSIBLE_HOST_KEY_CHECKING=False",
"ANSIBLE_SSH_ARGS='-o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'",
"ANSIBLE_NOCOLOR=True"
]
extra_arguments = [
#"-v",
"--extra-vars",
"ansible_ssh_pass=${build.User} version_number=${local.version_number} ansible_shell_type=cmd ansible_shell_executable=None"
]
host_alias = "none"
playbook_file = "../../ansible/roles/ansible-role-example-role/site.yml"
only = ["vagrant.windows-2019"]
}
provisioner "ansible" {
command = "./scripts/ansible.sh"
user = "vagrant"
use_proxy = false
ansible_env_vars = [
"ANSIBLE_HOST_KEY_CHECKING=False",
"ANSIBLE_SSH_ARGS='-o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'",
"ANSIBLE_NOCOLOR=True"
]
extra_arguments = [
#"-v",
"--extra-vars",
"ansible_ssh_pass=vagrant version_number=${local.version_number} ansible_shell_type=cmd ansible_shell_executable=None rule_2_3_1_5=false win_skip_for_test=true rule_2_3_1_1=false"
]
host_alias = "none"
playbook_file = "../../ansible/galaxy/roles/Windows-2019-CIS/site.yml"
only = ["vagrant.windows-2019"]
}
provisioner "ansible" {
command = "./scripts/ansible.sh"
user = "vagrant"
use_proxy = false
ansible_env_vars = [
"ANSIBLE_HOST_KEY_CHECKING=False",
"ANSIBLE_SSH_ARGS='-o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'",
"ANSIBLE_NOCOLOR=True"
]
extra_arguments = [
# "-vvv",
"--extra-vars",
"ansible_ssh_pass=vagrant version_number=${local.version_number} ansible_shell_type=cmd ansible_shell_executable=None ansbile_become=yes ansible_become_method=runas"
]
host_alias = "none"
playbook_file = "../../ansible/roles/ansible-role-vm-config/site.yml"
only = ["vagrant.windows-2019"]
}
provisioner "ansible" {
command = "./scripts/ansible.sh"
user = "${build.User}"
use_proxy = false
extra_arguments = [
#"-v",
"--extra-vars",
"ansible_winrm_server_cert_validation=ignore version_number=${local.version_number}"
]
host_alias = "none"
playbook_file = "../../ansible/roles/ansible-role-example-role/site.yml"
only = ["amazon-ebs.windows-2019", "googlecompute.windows-2019", "azure-arm.windows-2019"]
}
/*
provisioner "ansible" {
command = "./scripts/ansible.sh"
user = "${build.User}"
use_proxy = false
extra_arguments = [
#"-v",
"--extra-vars",
"ansible_winrm_server_cert_validation=ignore version_number=${local.version_number}"
]
host_alias = "none"
playbook_file = "../../ansible/galaxy/roles/ansible-role-win_openssh/site.yml"
only = ["amazon-ebs.windows-2019", "googlecompute.windows-2019", "azure-arm.windows-2019"]
}
*/
provisioner "ansible" {
command = "./scripts/ansible.sh"
user = "${build.User}"
use_proxy = false
extra_arguments = [
#"-v",
"--extra-vars",
"ansible_winrm_server_cert_validation=ignore version_number=${local.version_number}"
]
host_alias = "none"
playbook_file = "../../ansible/roles/ansible-role-example-role/site.yml"
only = ["amazon-ebs.windows-2019", "googlecompute.windows-2019", "azure-arm.windows-2019"]
}
provisioner "ansible" {
command = "./scripts/ansible.sh"
user = "${build.User}"
use_proxy = false
extra_arguments = [
#"-v",
"--extra-vars",
"ansible_winrm_server_cert_validation=ignore section02_patch=false rule_2_3_1_5=false rule_2_3_1_1=false win_skip_for_test=true rule_2_3_1_5=false rule_2_3_1_6=false"
]
host_alias = "none"
playbook_file = "../../ansible/galaxy/roles/Windows-2019-CIS/site.yml"
only = ["amazon-ebs.windows-2019", "googlecompute.windows-2019", "azure-arm.windows-2019"]
}
provisioner "shell-local" {
inline = ["curl -s https://api.ipify.org/?format=none"]
}
provisioner "powershell" {
inline = [
"Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State",
"C:\\windows\\system32/sysprep\\sysprep.exe /oobe /generalize /quiet /quit /mode:vm",
"while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10 } else { break } }"
]
only = ["azure-arm.windows-2019"]
}
provisioner "powershell" {
inline = [
"Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State",
"GCESysprep -no_shutdown"
]
only = ["googlecompute.windows-2019"]
}
}
Packer Vagrant Provisioner
packer.sh
#!/bin/bash
function packer-install() {
arch=$(lscpu | grep "Architecture" | awk '{print $NF}')
if [[ $arch == x86_64* ]]; then
ARCH="amd64"
elif [[ $arch == aarch64 ]]; then
ARCH="arm64"
fi
echo -e '\e[38;5;198m'"CPU is $ARCH"
if pgrep -x "vault" >/dev/null
then
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Vault is running.."
echo -e '\e[38;5;198m'"++++ "
else
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Ensure Vault is running.."
echo -e '\e[38;5;198m'"++++ "
sudo bash /vagrant/vault/vault.sh
fi
grep -q "PACKER_LOG=1" /etc/environment
if [ $? -eq 1 ]; then
echo "PACKER_LOG=1" >> /etc/environment
else
sudo sed 's/PACKER_LOG=.*/PACKER_LOG=1/g' /etc/environment
fi
grep -q "PACKER_LOG_PATH=/var/log/packer.log" /etc/environment
if [ $? -eq 1 ]; then
echo "PACKER_LOG_PATH=/var/log/packer.log" >> /etc/environment
else
sudo sed 's/PACKER_LOG_PATH=.*/PACKER_LOG_PATH=\/var\/log\/packer.log/g' /etc/environment
fi
sudo touch /var/log/packer.log
sudo chmod 777 /var/log/packer.log
sudo DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install -qq curl unzip jq python3-hvac < /dev/null > /dev/null
if [ -f /usr/local/bin/packer ]; then
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ `/usr/local/bin/packer version` already installed at /usr/local/bin/packer"
echo -e '\e[38;5;198m'"++++ "
else
LATEST_URL=$(curl --silent https://releases.hashicorp.com/index.json | jq '{packer}' | egrep "linux.*$ARCH" | sort -rh | head -1 | awk -F[\"] '{print $4}')
wget -q $LATEST_URL -O /tmp/packer.zip
sudo mkdir -p /usr/local/bin
(cd /usr/local/bin && unzip /tmp/packer.zip)
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Installed: `/usr/local/bin/packer version`"
echo -e '\e[38;5;198m'"++++ "
fi
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Ensure Environment Variables from /etc/environment"
echo -e '\e[38;5;198m'"++++ "
set -a; source /etc/environment; set +a;
# Packer will build a Docker container, use the Shell and Ansible provisioners, Ansible will also connect to Vault to retrieve secrets using a Token.
# https://learn.hashicorp.com/vault/getting-started/secrets-engines
# https://docs.ansible.com/ansible/latest/plugins/lookup/hashi_vault.html
# https://learn.hashicorp.com/vault/identity-access-management/iam-authentication
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ https://www.vaultproject.io/docs/auth/approle/"
echo -e '\e[38;5;198m'"++++ Using the root Vault token, enable the AppRole auth method"
echo -e '\e[38;5;198m'"++++ vault auth enable approle"
echo -e '\e[38;5;198m'"++++ "
vault auth enable approle
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Using the root Vault token, Create an Ansible role"
echo -e '\e[38;5;198m'"++++ Create an policy named ansible allowing Ansible to read secrets"
echo -e '\e[38;5;198m'"++++ "
tee ansible-vault-policy.hcl <<"EOF"
# Read-only permission on 'kv/ansible*' path
path "kv/ansible*" {
capabilities = [ "read" ]
}
EOF
vault policy write ansible ansible-vault-policy.hcl
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ vault write auth/approle/role/ansible \
secret_id_ttl=10h \\n
token_policies=ansible \\n
token_num_uses=100 \\n
token_ttl=10h \\n
token_max_ttl=10h \\n
secret_id_num_uses=100"
vault write auth/approle/role/ansible \
secret_id_ttl=10h \
token_policies=ansible \
token_num_uses=100 \
token_ttl=10h \
token_max_ttl=10h \
secret_id_num_uses=100
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Fetch the RoleID of the Ansible's Role"
echo -e '\e[38;5;198m'"++++ vault read auth/approle/role/ansible/role-id"
echo -e '\e[38;5;198m'"++++ "
vault read auth/approle/role/ansible/role-id
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Using the root Vault token,Get a SecretID issued against the AppRole"
echo -e '\e[38;5;198m'"++++ vault write -f auth/approle/role/ansible/secret-id"
echo -e '\e[38;5;198m'"++++ "
vault write -f auth/approle/role/ansible/secret-id
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Fetch the Token that Ansible will use to lookup secrets"
echo -e '\e[38;5;198m'"++++ "
ANSIBLE_ROLE_ID=$(vault read auth/approle/role/ansible/role-id | grep role_id | tr -s ' ' | cut -d ' ' -f2)
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ ANSIBLE_ROLE_ID: ${ANSIBLE_ROLE_ID}"
echo -e '\e[38;5;198m'"++++ "
ANSIBLE_ROLE_SECRET_ID=$(vault write -f auth/approle/role/ansible/secret-id | grep secret_id | head -n 1 | tr -s ' ' | cut -d ' ' -f2)
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ ANSIBLE_ROLE_SECRET_ID: ${ANSIBLE_ROLE_SECRET_ID}"
echo -e '\e[38;5;198m'"++++ vault write auth/approle/login role_id=\"${ANSIBLE_ROLE_ID}\" secret_id=\"${ANSIBLE_ROLE_ID}\""
echo -e '\e[38;5;198m'"++++ "
vault write auth/approle/login role_id="${ANSIBLE_ROLE_ID}" secret_id="${ANSIBLE_ROLE_SECRET_ID}"
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Using the root Vault token, add a Secret in Vault which Ansible will retrieve"
echo -e '\e[38;5;198m'"++++ vault secrets enable -path=kv kv"
echo -e '\e[38;5;198m'"++++ "
vault secrets enable -path=kv kv
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Create a Secret that Ansible will have access too"
echo -e '\e[38;5;198m'"++++ vault kv put kv/ansible devops=\"all the things\""
echo -e '\e[38;5;198m'"++++ "
vault kv put kv/ansible devops="all the things"
ANSIBLE_TOKEN=$(vault write auth/approle/login role_id="${ANSIBLE_ROLE_ID}" secret_id="${ANSIBLE_ROLE_SECRET_ID}" | grep token | head -n1 | tr -s ' ' | cut -d ' ' -f2)
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ ANSIBLE_TOKEN: ${ANSIBLE_TOKEN}"
# sed -i "s:token=[^ ]*:token=${ANSIBLE_TOKEN}:" /vagrant/packer/packer/linux/ubuntu/playbook.yml
echo -e '\e[38;5;198m'"++++ Install Ansible to configure Containers/VMs/AMIs/Whatever"
echo -e '\e[38;5;198m'"++++ "
sudo pip3 install ansible --break-system-packages --quiet
if [ -f /usr/local/bin/ansible ]; then
echo -e '\e[38;5;198m'"++++ `/usr/local/bin/ansible --version | head -n 1` already installed at /usr/local/bin/ansible"
else
sudo pip3 install ansible --break-system-packages --quiet
fi
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Install Docker so we can build Docker Images"
# https://docs.docker.com/install/linux/docker-ce/ubuntu/
if [ -f /usr/bin/docker ]; then
echo -e '\e[38;5;198m'"++++ `/usr/bin/docker -v` already installed at /usr/bin/docker"
else
sudo bash /vagrant/docker/docker.sh
fi
echo -e '\e[38;5;198m'"++++ Packer build Linux Docker container configured with Ansible"
echo -e '\e[38;5;198m'"++++ "
# packer build /vagrant/packer/packer/linux/ubuntu/ubuntu-2204.hcl
cd /vagrant/packer/packer/
./run.sh
}
packer-install