Cape Town to London

A blog about tech, ethics & startups

Use Ansible to Deploy a Docker Container

Deploying Environment

Deploying containers to a remote server can be rather tedious. Sometimes all you need is to deploy your container on a remote server.
Sometime budget and time constraints don't allow you to setup a full Kubernetes cluster. But for a prototype or landing page simplicity is best.
Whenever I'm faced with a task that is tedious and repetitive, I see it as an opportunity to automate. Docker + Ansible

I decided to try use Ansible to deploy my Docker containers.

Requirements

To follow this guide you need:
  • Remote host with ssh access
  • Docker installed on the remote host
  • Python Docker SDK docker-py installed on the remote host
  • Container registry with an image ready to deploy
Setting up the registry and pushing the image will be covered in a future post.

Ansible Environment

The majority of my projects involve some form of Python so I just install with pip
$ pip install --upgrade ansible

Ops Folder

For a small project I like to keep all my devops related stuff in an .ops directory on the root of my project.
.ops
├── deploy_staging.yml
└── hosts

Ansible Inventory File

I like to store a list of servers in a hosts file.
[staging]
staging.jforte.me  ansible_host=45.32.235.197

[prod] jforte.me

Ansible docs provide a list of inventory parameters

Testing the connection

To test Ansible can connect to the server use the ping module
$ ansible -i hosts staging -m ping
staging.jforte.me | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
If you are using certificates you will be prompted to enter a password.

Simple Deployment Playbook

Deployment procedure is defined in a playbook called deploy_staging.yml:
---
- hosts: staging
  tasks:
    - name: login to container registry
      docker_login:
        registry: registry.gitlab.com
        username: JasonForte
        password: passwordortoken
        reauthorize: yes
    - name: start a new container for web
      docker_container:
        name: web
        image: registry.gitlab.com/jasonforte/jforte.me:web.1702.001-dev
        pull: true
        restart: yes
        state: started
        ports:
          - "8003:80"

Here I've defined the tasks to first login to the remote registry and then pull and start the new container. This is for my staging servers only.

Ansible has a number of builtin modules for the playbooks.

Running the playbook

Running the playbook requires referencing the hosts file.

$ ansible-playbook -i hosts deploy_staging.yml
If this is successful you should see a new container running on the remote server.

What's next?

The next step would be to write a task to reconfigure / restart your web server (nginx / HAProxy etc).

Once I'm happy with the playbook I will usually add it to a Makefile for easy access.


deploy:
    ansible-playbook -i .ops/hosts .ops/deploy_staging.yml

I will tackle some of these next steps in future posts.