Packer
-
Packer is used to build image from a base image, perform provisions and store (commit) the final image.
-
We use provisioners and Packer templates to do the actual work to create the final image.
-
We use Ansible for provisioning.
Ansible
- Ansible runs playbooks on localhost (inside Docker container).
- Ansible must be installed on the image you're provisioning.
- Packer uploads the contents of the Ansible playbook to the Docker container instance, and runs it locally.
-
Follow instructions here: https://www.packer.io/docs/installation.html
-
Check Packer is installed:
packer
usage: packer [--version] [--help] <command> [<args>]
Available commands are:
build build image(s) from template
fix fixes templates from old versions of packer
inspect see components of a template
validate check that a template is valid
Files:
build.json - main file with configuration for packer
playbook.yml - Ansible playbook for provisioning
vars/prod.json - main config file for production environment
vars/default.yml - default variables passed to Ansible
vars/prod.yml - variables to pass to Ansible for production environment
Build image for production environment specified by prod.json file:
- run build process with packer build command:
sudo packer build -var-file=prod.json build.json
- packer start from the base image specified in build.json
# build.json
{
...
"builders":[
{
"type": "docker",
"image": "phusion/passenger-ruby22:0.9.18",
"commit": true,
...
}
],
...
}
- packer runs provisioners specified in build.json
- first, it installs Ansible in Docker container:
"provisioners":[
{
"type": "shell",
"inline": [
"apt-get -y update",
"apt-get install -y software-properties-common",
"apt-add-repository ppa:ansible/ansible",
"apt-get -y update",
"apt-get install -y ansible"
]
},
- packer uploads
vars/prod.yml
to the Docker container and saves it asvars.yml
{
"type": "file",
"source": "{{user `config_file`}}",
"destination": "{{user `tmp_dir`}}/vars.yml"
}
-
packer uploads playbook.yml to the Docker container
-
packer runs Ansible playbook.yml locally in the Docker container
{
"type": "ansible-local",
"staging_directory": "{{user `tmp_dir`}}/ansible",
"playbook_file": "playbook.yml",
"extra_arguments": [ "--extra-vars \"tmp_dir={{user `tmp_dir`}} \"" ]
}
- Ansible playbook uses variables defined in corresponding vars.yml file
- hosts: 127.0.0.1
user: root
vars_files:
- "{{tmp_dir}}/vars.yml"
tasks:
- The final image is saved as "my-nginx:0.1" specified in build.json
"post-processors": [
[
{
"type": "docker-tag",
"repository": "my-nginx",
"tag": "0.1"
}
]
]
Create build.json file with configuration how to build Docker image.
build.json:
{
"variables": {
"config_file": "vars/default.yml",
"tmp_dir": "/tmp"
},
"builders":[
{
"type": "docker",
"image": "nginx",
"commit": true,
"run_command": ["-d", "{{.Image}}", "nginx -g daemon off"]
}
],
"provisioners":[
{
"type": "shell",
"inline": [
"apt-get -y update",
"apt-get install -y software-properties-common",
"apt-add-repository ppa:ansible/ansible",
"apt-get -y update",
"apt-get install -y ansible"
]
},
{
"type": "shell",
"inline": [
"mkdir -p {{user `tmp_dir`}}"
]
}
,
{
"type": "file",
"source": "{{user `config_file`}}",
"destination": "{{user `tmp_dir`}}/vars.yml"
}
,
{
"type": "ansible-local",
"staging_directory": "{{user `tmp_dir`}}/ansible",
"playbook_file": "playbook.yml",
"extra_arguments": [ "--extra-vars \"tmp_dir={{user `tmp_dir`}} \"" ]
}
],
"post-processors": [
[
{
"type": "docker-tag",
"repository": "my-nginx",
"tag": "0.1"
}
]
]
}
sudo packer build -var-file=vars/prod.json build.json
sudo docker run -d -p 8080:80 --name=my-server1 my-nginx:0.1
It would be very welcome to see an example file structure described in this Gist. Can you help with that?