Skip to content

Instantly share code, notes, and snippets.

@patlegu
Created August 4, 2021 00:08
Show Gist options
  • Select an option

  • Save patlegu/ac87b89d403de7d0017d8d5c0f62c684 to your computer and use it in GitHub Desktop.

Select an option

Save patlegu/ac87b89d403de7d0017d8d5c0f62c684 to your computer and use it in GitHub Desktop.

Revisions

  1. patlegu created this gist Aug 4, 2021.
    221 changes: 221 additions & 0 deletions Building_Docker_image.
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,221 @@
    # 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

    * 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

    ```



    # 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
    ```