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!