This guide provides a Ansible playbook to deploy Canvas LMS with Docker Compose on Debian 10+, Ubuntu LTS, and RHEL 9+ compatible hosts. This approach enables infrastructure-as-code practices for consistent, reproducible deployments.
---
- name: Deploy Canvas LMS with Docker
hosts: canvas-lms
become: true
vars:
app_root: /opt/canvas-lms
app_port: 8080
canvas_domain: "canvas.example.com"
canvas_admin_email: "admin@example.com"
postgres_user: "canvas"
postgres_db: "canvas_production"
postgres_password: "change_me_to_secure_password"
secret_key_base: "change_me_to_secure_random_string"
tasks:
- name: Update package cache (Debian/Ubuntu)
apt:
update_cache: yes
when: ansible_os_family == "Debian"
- name: Update package cache (RHEL/CentOS)
dnf:
update_cache: yes
when: ansible_os_family == "RedHat"
- name: Install Docker on Debian/Ubuntu
apt:
name:
- docker.io
- docker-compose-plugin
state: present
when: ansible_os_family == "Debian"
- name: Install Docker on RHEL family
dnf:
name:
- docker
- docker-compose-plugin
state: present
when: ansible_os_family == "RedHat"
- name: Enable and start Docker service
service:
name: docker
state: started
enabled: true
- name: Add ansible user to docker group
user:
name: "{{ ansible_user }}"
groups: docker
append: yes
- name: Create application directory
file:
path: "{{ app_root }}"
state: directory
owner: "{{ ansible_user }}"
mode: "0755"
- name: Create Docker Compose file
template:
src: canvas-lms-compose.yml.j2
dest: "{{ app_root }}/docker-compose.yml"
owner: "{{ ansible_user }}"
mode: "0644"
- name: Create environment file
template:
src: canvas-lms.env.j2
dest: "{{ app_root }}/.env"
owner: "{{ ansible_user }}"
mode: "0600"
- name: Pull Docker images
docker_compose:
project_src: "{{ app_root }}"
state: present
pull: yes
- name: Start Canvas LMS stack
docker_compose:
project_src: "{{ app_root }}"
state: present
notify: restart canvas-lms
handlers:
- name: restart canvas-lms
docker_compose:
project_src: "{{ app_root }}"
state: present
Create the following Jinja2 template files in your Ansible roles directory:
templates/canvas-lms-compose.yml.j2version: '3.8'
services:
postgres:
image: postgres:13
restart: unless-stopped
environment:
POSTGRES_USER: {{ postgres_user }}
POSTGRES_DB: {{ postgres_db }}
POSTGRES_PASSWORD: {{ postgres_password }}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- canvas_network
redis:
image: redis:6-alpine
restart: unless-stopped
volumes:
- redis_data:/data
networks:
- canvas_network
canvas-lms:
image: ghcr.io/canvas-lms/canvas-lms:stable
restart: unless-stopped
ports:
- "{{ app_port }}:3000"
environment:
CANVAS_LMS_DOMAIN: {{ canvas_domain }}
CANVAS_LMS_ADMIN_EMAIL: {{ canvas_admin_email }}
DATABASE_HOST: postgres
DATABASE_NAME: {{ postgres_db }}
DATABASE_USERNAME: {{ postgres_user }}
DATABASE_PASSWORD: {{ postgres_password }}
REDIS_URL: redis://redis:6379/0
SECRET_KEY_BASE: {{ secret_key_base }}
volumes:
- canvas_files:/canvas/files
depends_on:
- postgres
- redis
networks:
- canvas_network
volumes:
postgres_data:
redis_data:
canvas_files:
networks:
canvas_network:
driver: bridge
templates/canvas-lms.env.j2CANVAS_LMS_DOMAIN={{ canvas_domain }}
CANVAS_LMS_ADMIN_EMAIL={{ canvas_admin_email }}
POSTGRES_USER={{ postgres_user }}
POSTGRES_DB={{ postgres_db }}
POSTGRES_PASSWORD={{ postgres_password }}
SECRET_KEY_BASE={{ secret_key_base }}
Create an inventory file named inventory.yml:
all:
children:
canvas-lms:
hosts:
canvas-server:
ansible_host: your-server-ip-or-hostname
ansible_user: your-ssh-user
ansible-galaxy collection install community.docker
ansible-playbook -i inventory.yml canvas-lms-playbook.yml
Store sensitive information in Ansible Vault:
ansible-vault encrypt_string --name='postgres_password' 'your_secure_password'
ansible-vault encrypt_string --name='secret_key_base' 'your_very_long_secret_key'
Include these in a vault file and reference them in your playbook.
Create separate inventory files for different environments:
inventory/development.ymlinventory/staging.ymlinventory/production.ymlThen run with specific inventory:
ansible-playbook -i inventory/production.yml canvas-lms-playbook.yml
# Check running containers
docker ps -a
# View logs
docker logs canvas-lms-canvas-lms-1
# Execute commands inside container
docker exec -it canvas-lms-canvas-lms-1 bash
# Check service status
docker-compose -f /opt/canvas-lms/docker-compose.yml ps
ghcr.io/canvas-lms/canvas-lms:stable for production instead of latestAny questions?
Feel free to contact us. Find all contact information on our contact page.