Skip to content

Instantly share code, notes, and snippets.

@wilmoore
Forked from maxivak/__readme.md
Created September 7, 2019 15:25
Show Gist options
  • Save wilmoore/090d7048c3e89bd24ffeeb54f05d0445 to your computer and use it in GitHub Desktop.
Save wilmoore/090d7048c3e89bd24ffeeb54f05d0445 to your computer and use it in GitHub Desktop.
Building Docker image with Packer and provisioning with Ansible

Building Docker image with Packer and provisioning with Ansible

Overview

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.

Install Packer

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
    

Build image with Packer

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 workflow

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 as vars.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"
      }
    ]
  ]

build configuration

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


Configs

Build image

sudo packer build -var-file=vars/prod.json build.json

Run Docker container

sudo docker run -d -p 8080:80 --name=my-server1 my-nginx:0.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment