Swiftorial Logo
Home
Swift Lessons
Tutorials
Learn More
Career
Resources

Docker with Ansible

Ansible allows you to automate the deployment and management of Docker containers, making it easier to manage your infrastructure as code. This guide covers key concepts, steps to use Ansible with Docker, examples, and best practices for deploying Dockerized Express.js applications with Ansible.

Key Concepts of Docker with Ansible

  • Playbooks: Ansible playbooks are YAML files that define a set of tasks to automate processes.
  • Roles: Ansible roles allow you to organize tasks, variables, and files in a structured way.
  • Modules: Ansible modules are reusable scripts that perform specific tasks, such as managing Docker containers and images.
  • Inventory: Ansible inventory files define the hosts and groups of hosts on which tasks will be executed.
  • Handlers: Handlers are tasks that run when notified by other tasks, often used to restart services.

Setting Up the Project

Initialize a new Express.js project and create a Dockerfile:

// Initialize a new project
// npm init -y

// Install Express
// npm install express

// Create the project structure
// mkdir src
// touch src/index.js Dockerfile .dockerignore .gitignore

// .gitignore
node_modules
.env

// .dockerignore
node_modules
npm-debug.log

Creating an Express Application

Create a simple Express application:

Example: index.js

// src/index.js
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
    res.send('Hello, Docker with Ansible!');
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}/`);
});

Creating a Dockerfile

Create a Dockerfile to containerize your Express application:

Example: Dockerfile

// Dockerfile
FROM node:14

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
COPY package*.json ./
RUN npm install

# Bundle app source
COPY . .

# Expose port 3000 to the outside world
EXPOSE 3000

# Run app when the container launches
CMD ["node", "src/index.js"]

Building and Running the Docker Container

Build and run the Docker container for your Express application:

// Build the Docker image
docker build -t my-express-app .

// Run the Docker container
docker run -d -p 3000:3000 --name my-express-app my-express-app

// Open http://localhost:3000 in your browser to see the application running

Setting Up Ansible

Install Ansible and create an inventory file:

Install Ansible

// On a Linux or macOS system
sudo apt-get install ansible

// On a macOS system with Homebrew
brew install ansible

Create an Inventory File

// inventory.ini
[local]
localhost ansible_connection=local

Creating an Ansible Playbook

Create a playbook to automate the deployment of your Dockerized Express application:

Example: playbook.yml

// playbook.yml
---
- name: Deploy Dockerized Express Application
  hosts: local
  tasks:
    - name: Ensure Docker is installed
      apt:
        name: docker.io
        state: present
      become: yes

    - name: Ensure Docker service is running
      service:
        name: docker
        state: started
        enabled: yes
      become: yes

    - name: Build the Docker image
      command: docker build -t my-express-app .
      args:
        chdir: /path/to/your/project

    - name: Run the Docker container
      docker_container:
        name: my-express-app
        image: my-express-app
        state: started
        ports:
          - "3000:3000"

Running the Ansible Playbook

Execute the playbook to deploy your Dockerized Express application:

// Run the playbook
ansible-playbook -i inventory.ini playbook.yml

Using Ansible Roles

Organize tasks, variables, and files using Ansible roles:

Example: Directory Structure

// Directory structure
roles/
  express-app/
    tasks/
      main.yml
    files/
      Dockerfile
      src/
        index.js
    vars/
      main.yml

// roles/express-app/tasks/main.yml
---
- name: Ensure Docker is installed
  apt:
    name: docker.io
    state: present
  become: yes

- name: Ensure Docker service is running
  service:
    name: docker
    state: started
    enabled: yes
  become: yes

- name: Build the Docker image
  command: docker build -t my-express-app .
  args:
    chdir: "{{ playbook_dir }}/roles/express-app/files"

- name: Run the Docker container
  docker_container:
    name: my-express-app
    image: my-express-app
    state: started
    ports:
      - "3000:3000"

// roles/express-app/vars/main.yml
---
docker_image: my-express-app
docker_container_name: my-express-app
docker_ports:
  - "3000:3000"

// playbook.yml
---
- name: Deploy Dockerized Express Application
  hosts: local
  roles:
    - express-app

Best Practices for Docker with Ansible

  • Use Roles: Organize your playbooks using roles to make them reusable and maintainable.
  • Idempotency: Ensure that your playbooks are idempotent, meaning they can be run multiple times without causing unintended side effects.
  • Version Control: Store your playbooks and roles in version control systems like Git to track changes and collaborate with others.
  • Documentation: Document your playbooks and roles to make it easier for others to understand and use them.
  • Testing: Test your playbooks and roles in a staging environment before deploying them to production.

Testing Docker with Ansible

Test your Ansible playbooks and roles to ensure they work correctly:

Example: Testing with Molecule

// Install Molecule and dependencies
// pip install molecule docker

// Initialize a new role with Molecule
molecule init role express-app

// Edit the Molecule configuration to use Docker
// molecule/default/molecule.yml
---
dependency:
  name: galaxy
driver:
  name: docker
platforms:
  - name: instance
    image: geerlingguy/docker-ubuntu1804-ansible
    pre_build_image: true
provisioner:
  name: ansible
  lint: |
    set -e
    ansible-lint
verifier:
  name: ansible

// Add test scenarios
// molecule/default/tests/test_default.yml
---
- name: Verify Docker container is running
  hosts: all
  tasks:
    - name: Check if Docker container is running
      command: docker ps
      register: result

    - name: Ensure container is running
      assert:
        that: "'my-express-app' in result.stdout"

// Run Molecule tests
molecule test

Key Points

  • Playbooks: Ansible playbooks are YAML files that define a set of tasks to automate processes.
  • Roles: Ansible roles allow you to organize tasks, variables, and files in a structured way.
  • Modules: Ansible modules are reusable scripts that perform specific tasks, such as managing Docker containers and images.
  • Inventory: Ansible inventory files define the hosts and groups of hosts on which tasks will be executed.
  • Handlers: Handlers are tasks that run when notified by other tasks, often used to restart services.
  • Follow best practices for Docker with Ansible, such as using roles, ensuring idempotency, using version control, documenting your playbooks, and testing in a staging environment.

Conclusion

Ansible allows you to automate the deployment and management of Docker containers, making it easier to manage your infrastructure as code. By understanding and implementing the key concepts, steps, examples, and best practices covered in this guide, you can effectively deploy Dockerized Express.js applications with Ansible. Happy coding!