Building an Ansible Controller in Docker for Windows to managing Azure deployments

Ansible is a powerful software and infrastructure provisioning tool and is becoming increasingly popular for provisioning resources in Azure. That being said, if you are a heavy Windows user like myself, building an Ansible Controller can be difficult given that it runs on Linux. In trying to find the easiest way to build my own test environment, I decided to go with Docker. Why? Because it is free, well documented, and allows me to do everything from my PC. Below are the steps I took to set this up.

NOTE: Much of this blog is taken from this article (credit: erjosito). The edits in this blog are specific to deploying in a Docker container with a few modifications to generalize the instructions for personal use. Last note, but this blog assumes an initial understanding of Azure, Docker and GitHub. Enjoy!

Step One – Installing Docker

      1. Installing Docker on Windows is fairly straight forward. Click here and select to install from either the Stable or Edge channel. I chose the Stable channel since I am running Windows 10. If you are doing this on Windows Server 2016, choose Edge.
      2. Docker for Windows requires Hyper-V. If it is not already installed, you will be prompted to do so (requiring a reboot):


      3. Check to confirm the docker icon is running in your System Tray to verify installation. You could also open the Command Prompt and type ‘docker ps -a’. This should produce an empty list of containers.

Step Two – Create the Ansible Controller image

      1. Create the Ansible image using Windows command line. Step one here is selecting the Linux kernel you will use for your Ansible Controller. Because the reference article used CentOS7.2, I did the same.
        docker search centos

        I selected the official CentOS build. Reference the official docker repository here for the correct image version.

        docker run -it centos:7.2.1511
      2. Install software prerequisites (within container).
        yum update -y
        yum install -y python-devel openssl-devel git gcc epel-release
        yum install -y ansible python-pip
        pip install --upgrade pip

        Install Azure Python SDK. At the time of this writing, the latest supported version is 2.0.0rc5. With this version, the package msrestazure needs to be installed independently. Additionally, we will install the package DNS Python so that we can do DNS checks in Ansible playbooks (to make sure that DNS names are not taken)

        pip install azure==2.0.0rc5
        pip install msrestazure
        pip install dnspython

        The last thing you’ll want to install is the Azure CLI. This isn’t used for Ansible, however, you will need to create a Service Principal for rights to manage Azure and the CLI is a great way to do this. Plus it doesn’t hurt to have it installed for additional future use.

        curl --silent –location\_4.x | bash -
        yum install -y nodejs
        npm install azure-cli -g

        The next thing you will need to do is create an admin account to manage Ansible. From my experience some things do not work properly when managing Ansible as user root, so it’s best to create an admin account to work from.

        adduser ansibleadmin
        usermod -aG wheel ansibleadmin
        passwd ansibleadmin
        su ansibleadmin
      3. Configure Azure Service Principal – This step uses Azure CLI to create a Service Principal in Azure Active Directory. This Service Principal is used to grant Ansible the permissions required to manage resources within the Azure Subscription.
        azure login

        Follow the instructions to login using your Azure Admin credentials.

        azure account set TartgetSubscription

        Replace ‘Target Subscription’ with the Subscription you plan to manage.

        Create the Azure Service Principal.

        azure ad sp create -n ansiblecontroller -p ThisIsTheAppPassword
        info:    Executing command ad sp create
        + Creating application ansiblelab
        + Creating service principal for application 11111111-1111-1111-1111-111111111111
        data:    Object Id:               44444444-4444-4444-4444-444444444444
        data:    Display Name:            ansiblelab
        data:    Service Principal Names:
        data:                             11111111-1111-1111-1111-111111111111
        data:                             http://ansiblelab
        info:    ad sp create command OK

        Record the Application ID, Object ID and value used in place of ‘ThisIsTheAppPassword’. They will be needed later.

        Find and record the Subscription ID and Tenant ID.

        azure account show
        info:    Executing command account show
        data:    Name                        : Your Subscription Name
        data:    ID                          : 22222222-2222-2222-2222-222222222222
        data:    State                       : Enabled
        data:    Tenant ID                   : 33333333-3333-3333-3333-333333333333
        data:    Is Default                  : true
        data:    Environment                 : AzureCloud
        data:    Has Certificate             : No
        data:    Has Access Token            : Yes
        data:    User name                   :
        info:    account show command OK

        Grant the Service Principal Contributor rights to the Azure Subscription.

        azure role assignment create --objectId  44444444-4444-4444-4444-444444444444 -roleName Contributor -c /subscriptions/22222222-2222-2222-2222-222222222222/
        info:    Executing command role assignment create
        + Finding role with specified name
        data:    RoleAssignmentId     : /subscriptions/22222222-2222-2222-2222-222222222222/providers/Microsoft.Authorization/roleAssignments/86e6bcd4-8061-41d1-8a7f-74219a268d51
        data:    RoleDefinitionName   : Contributor
        data:    RoleDefinitionId     : b24988ac-6180-42a0-ab88-20f7382dd24c
        data:    Scope                : /subscriptions/22222222-2222-2222-2222-222222222222
        data:    Display Name         : ansiblelab
        data:    SignInName           : undefined
        data:    ObjectId             : 44444444-4444-4444-4444-444444444444
        data:    ObjectType           : ServicePrincipal
        info:    role assignment create command OK
      4. Create a file to store the Azure Service Principal environment variables.
        cd $HOME
        mkdir ~/.azure
        touch ~/.azure/credentials

        Run the command below, replacing the generic inputs with the ones recorded in the previous step.

        cat <<EOF > ~/.azure/credentials
      5. Create a private/public key pair, and install the public key in the local machine to test the correct operation of Ansible. When generating the RSA key, select an empty passphrase.
        ssh-keygen -t rsa
        chmod 755 ~/.ssh
      6. Finally, clone the GitHub repository for the Ansible source code (which includes the dynamic inventory files such as azure\
        cd $Home
        git clone git:// –-recursive

        Test that Ansible is running and is authenticated to Azure by running the dynamic inventory script, executing it with the parameter –list. This should show JSON text containing information about all the VMs in your subscription.

        python ./ansible/contrib/inventory/azure\ --list
      7. At this point, your Ansible Controller image is ready to begin managing Azure. My next step will be to perform a few test builds. If you would like to skip these steps, go to step 4 and commit the Docker image before completing.

Step Three – Test Managing Resources in Azure

      1. Before you continue, you will need an Azure Resource Group, Virtual Network and Subnet to deploy to. You could do this through a number of means; Ansible, CLI, PowerShell, ARM Templates, the Portal, the list goes on. For expedience, I’ve created them using Azure CLI and provided the commands below.

        NOTE: I am still logged into my Azure Subscription from a previous step. If you are not, please rerun the first two commands from Step 2.3 before moving on.

        azure group create Demo-Ansible eastus2
        azure network vnet create -n AnsibleNet -g Demo-Ansible -l eastus2 -a
        azure network vnet subnet create -a -n Default -g Demo-Ansible -e AnsibleNet
      2. In order to perform these steps, you will need some Playbooks to test deployment with. For this, I’ve again reference this article but with a few key differences. Rather than work from erjosito‘s repository, I’ve forked it to my GitHub account and will work from that copy. This gives me the ability to do any customization that I need. If you have existing Playbooks, you can skip this step and use those.

            1. From a browser window, navigate to the source Repository and click ‘Fork’ in the upper right hand corner.


            2. Select the account where you would like the Repository forked.

      3. Next, you will need to clone this Repository to your Docker Ansible Controller image.

        NOTE: Before doing this, I highly recommend cloning this Repository onto your local PC so you can edit the YAML files in the text editor of your choice. To do this you will need GitHub installed on your PC. If you do not already have it installed, please reference this link for the steps. Once completed you should see both Git Shell and GitHub Desktop installed and listed under ‘GitHub, Inc’ in your Start Menu.
      4. Open the Git Shell and run the following commands to clone your Repository.

        cd ~\Documents\GitHub

        Replace my GitHub Repository with the forked Repository you created in the previous step.

        git clone
        cd .\ansible-azure-lab\
      5. At this point, open File Explorer and navigate to the folder you just cloned. You should see a copy of all the files and folders in the ansible-azure-lab Repository.
      6. Open the YAML file ‘new_vm_web.yml’ in the document editor of your choice.

        Once in the file, you can make whatever modification you need. For example, I replaced the hard-coded ‘region’ and ‘publickey’ values with parameters that could be passed in at runtime. Please feel free to check out my updated file here for reference.

        NOTE: Parameters for {{ region }} and {{ publickey }} have been added.

      7. Save your chances and return to the Git Shell
      8. Run the following commands in Git Shell to commit the changes to your GitHub Repository

        git add .
        git commit -m "Add comments detailing changes"
        git push
      9. Return to the Ansible Controller Container and run the following command to clone the updated Repository.

        NOTE: Replace my Repository with the one created in step 3.2.

        git clone

        Display the public key data and copy everything in red below. You will need to pass this in as a parameter in the next step.

        cat ~/.ssh/id\
        ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA12345678901234567890+S0KZd25Q94ZycE8qz00CEN7foFUUagpUlMNFbk4Nk/mHv9NdAVvjrFAINXbpFroMU6CcIHzuxO36xh+0P1zPwjMQeodpMhTpfkeG7lueH4f7N+X4SeUiafMKgA8LJO7N5uXecl/BxWD8pq6LWGUY1mdV7Rw9cpUvEV55C8eacDNuUUX4LBcwi29PwdsrgCryYojiz4eJf5PhmL8pC7TEDITEDANDNOLONGERVALIDeY+5n5bKvsuMc3boRQ8Cabcdefghijklmnopqrstuvwxyz+jz3Wip ansibleadmin@040a99387c76
      10. Finally, run the following command to deploy the new_vm_web.yml Playbook to the Virtual Network created in step 3.1.

        ansible-playbook ~/ansible-azure-lab/new_vm_web.yml --extra-vars '/
        vmname=< Web Server Name> /
        resgrp=<Resource Group Name> /
        vnet=<Virtual Network Name> /
        subnet=<Subnet Name> /
        region=<Azure Region> /
        publickey=<"Public Key"> /

        Your command should look something like this:

        ansible-playbook ~/ansible-azure-lab/new_vm_web.yml --extra-vars '/
        vmname=ansibleweb01 /
        resgrp=Demo-Ansible /
        vnet=AnsibleNet /
        subnet=Default /
        publickey="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA12345678901234567890+S0KZd25Q94ZycE8qz00CEN7foFUUagpUlMNFbk4Nk/mHv9NdAVvjrFAINXbpFroMU6CcIHzuxO36xh+0P1zPwjMQeodpMhTpfkeG7lueH4f7N+X4SeUiafMKgA8LJO7N5uXecl/BxWD8pq6LWGUY1mdV7Rw9cpUvEV55C8eacDNuUUX4LBcwi29PwdsrgCryYojiz4eJf5PhmL8pC7TEDITEDANDNOLONGERVALIDeY+5n5bKvsuMc3boRQ8Cabcdefghijklmnopqrstuvwxyz+jz3Wip" /
      11. Once you’ve validated the successful deployment of your New Web VM, you can now exit the container.


Step Four – Commit changes to your new Ansible Controller image.

      1. Copy the container ID of the container you just created.

        docker ps -a
      2. Create a new image from the container.

        docker commit <Container ID> my_ansible_controller

And there you have it folks. An Ansible Controller running in Docker for Windows built to manage Azure deployments. Have a good day and Go Azure!

Comments (0)

Skip to main content