Skip to main content

Stacks and templates


Chapter objectives

  • Deploy Docker Compose stacks
  • Use application templates
  • Create custom templates
  • Manage deployments

1 - What is a Stack?

Definition

A stack in Portainer is a set of services deployed together, defined by a Docker Compose file.

┌─────────────────────────────────────────────────────────────────┐
│ Stack "wordpress" │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ wordpress │ ────▶ │ mysql │ │
│ │ :8080 │ │ :3306 │ │
│ └─────────────┘ └─────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ Volume │ │
│ │ mysql_data │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

Advantages

AdvantageDescription
SimplicityOne deployment = multiple containers
ConsistencyVersion-controlled compose file
ManagementStart/stop everything together
ReproducibilitySame configuration every time

2 - Create a stack

Creation interface

┌─────────────────────────────────────────────────────────────────┐
│ + Add Stack │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Name: [my-wordpress ] │
│ │
│ Build method: │
│ (•) Web editor │
│ ( ) Upload │
│ ( ) Repository │
│ ( ) Custom template │
│ │
└─────────────────────────────────────────────────────────────────┘

Creation methods

MethodDescription
Web editorWrite the compose directly
UploadUpload a .yml file
RepositoryClone from Git
Custom templateUse an existing template

Stack editor

┌─────────────────────────────────────────────────────────────────┐
│ Web editor │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ version: "3.9" │ │
│ │ │ │
│ │ services: │ │
│ │ wordpress: │ │
│ │ image: wordpress:latest │ │
│ │ ports: │ │
│ │ - "8080:80" │ │
│ │ environment: │ │
│ │ WORDPRESS_DB_HOST: db │ │
│ │ WORDPRESS_DB_USER: wordpress │ │
│ │ WORDPRESS_DB_PASSWORD: ${DB_PASSWORD} │ │
│ │ WORDPRESS_DB_NAME: wordpress │ │
│ │ depends_on: │ │
│ │ - db │ │
│ │ │ │
│ │ db: │ │
│ │ image: mysql:8 │ │
│ │ environment: │ │
│ │ MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} │ │
│ │ MYSQL_DATABASE: wordpress │ │
│ │ MYSQL_USER: wordpress │ │
│ │ MYSQL_PASSWORD: ${DB_PASSWORD} │ │
│ │ volumes: │ │
│ │ - db_data:/var/lib/mysql │ │
│ │ │ │
│ │ volumes: │ │
│ │ db_data: │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Environment variables: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ [DB_PASSWORD ] = [secret123 ] [+ Add] │ │
│ │ [DB_ROOT_PASSWORD] = [rootsecret ] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ [Deploy the stack] │
│ │
└─────────────────────────────────────────────────────────────────┘

3 - Manage stacks

List of stacks

┌─────────────────────────────────────────────────────────────────┐
│ 📚 Stacks [+ Add stack] │
├─────────────────────────────────────────────────────────────────┤
│ Name Type Status Services Controls │
│ ──────────────────────────────────────────────────────────────│
│ wordpress Compose ✅ Active 2/2 [⚙️] │
│ monitoring Compose ✅ Active 3/3 [⚙️] │
│ dev-tools Compose ⏸️ Stopped 0/2 [⚙️] │
│ │
└─────────────────────────────────────────────────────────────────┘

Actions on a stack

ActionDescription
StartStart all services
StopStop all services
DeleteDelete the stack
EditModify the compose
DuplicateCreate a copy
MigrateMigrate to another environment

Details of a stack

┌─────────────────────────────────────────────────────────────────┐
│ 📚 wordpress │
├─────────────────────────────────────────────────────────────────┤
│ Tabs: [Services] [Editor] [Environment variables] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Services: │
│ ─────────────────────────────────────────────────────────────│
│ │
│ □ Service Image Status Replicas │
│ ──────────────────────────────────────────────────────────────│
│ □ wordpress wordpress:latest 🟢 1/1 │
│ □ db mysql:8 🟢 1/1 │
│ │
│ Resources: │
│ ─────────────────────────────────────────────────────────────│
│ Networks: wordpress_default │
│ Volumes: wordpress_db_data │
│ │
└─────────────────────────────────────────────────────────────────┘

4 - Stacks from Git

Git configuration

┌─────────────────────────────────────────────────────────────────┐
│ Repository │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Repository URL: [https://github.com/user/myapp ] │
│ │
│ Reference: [main ] │
│ │
│ Compose path: [docker-compose.yml ] │
│ │
│ Authentication: │
│ ☑ Enable authentication │
│ Username: [myuser ] │
│ Personal access token: [ghp_xxxxx ] │
│ │
│ Automatic updates: │
│ ☑ Enable GitOps updates │
│ Mechanism: ( ) Polling (•) Webhook │
│ Interval: [5 minutes ▼] │
│ │
└─────────────────────────────────────────────────────────────────┘

GitOps with Portainer

Portainer can automatically redeploy the stack when the Git repo changes:

┌─────────────────────────────────────────────────────────────────┐
│ GitOps Workflow │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Developer GitHub Portainer │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ git push│ ────▶ │ Repo │ ────▶ │ Poll/ │ │
│ │ │ │ updated │ │ Webhook │ │
│ └─────────┘ └─────────┘ └────┬────┘ │
│ │ │
│ ▼ │
│ ┌─────────┐ │
│ │Redeploy │ │
│ │ Stack │ │
│ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

5 - Application templates

Access the templates

┌─────────────────────────────────────────────────────────────────┐
│ 📋 App Templates │
├─────────────────────────────────────────────────────────────────┤
│ Filter: [All categories ▼] [🔍 Search... ] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ Nginx │ │ WordPress │ │ PostgreSQL │ │
│ │ 🌐 │ │ 📝 │ │ 🐘 │ │
│ │ Web server │ │ Blog/CMS │ │ Database │ │
│ │ [Deploy] │ │ [Deploy] │ │ [Deploy] │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ MySQL │ │ Redis │ │ MongoDB │ │
│ │ 🐬 │ │ 📕 │ │ 🍃 │ │
│ │ Database │ │ Cache │ │ NoSQL DB │ │
│ │ [Deploy] │ │ [Deploy] │ │ [Deploy] │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

Deploy a template

┌─────────────────────────────────────────────────────────────────┐
│ Deploy: WordPress │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Configuration: │
│ ─────────────────────────────────────────────────────────────│
│ Name: [my-wordpress ] │
│ │
│ Environment variables: │
│ ─────────────────────────────────────────────────────────────│
│ Database password: [mysecretpassword ] │
│ WordPress admin user: [admin ] │
│ WordPress admin pass: [adminpassword ] │
│ │
│ Network: [bridge ▼] │
│ │
│ Access control: │
│ (•) Administrators only │
│ ( ) Restricted │
│ │
│ [Deploy container] │
│ │
└─────────────────────────────────────────────────────────────────┘

6 - Create custom templates

Types of templates

TypeDescription
ContainerTemplate for a single container
StackTemplate for a compose stack

Create a Stack template

Settings > App Templates > + Add template

┌─────────────────────────────────────────────────────────────────┐
│ Create template │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Type: ( ) Container (•) Stack │
│ │
│ Title: [My Custom App ] │
│ Description: [Complete LAMP stack ] │
│ Logo: [https://example.com/logo.png] │
│ Platform: [linux ▼] │
│ │
│ Categories: [Webserver, Database ] │
│ │
│ Repository URL: [https://github.com/user/template ] │
│ Compose path: [docker-compose.yml ] │
│ │
│ OR Web editor: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ version: "3.9" │ │
│ │ services: │ │
│ │ ... │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Environment variables (user-configurable): │
│ ─────────────────────────────────────────────────────────────│
│ [DB_PASSWORD ] Label: [Database password ] Default: [] │
│ [ADMIN_EMAIL ] Label: [Admin email ] Default: [] │
│ [+ Add] │
│ │
│ [Create template] │
│ │
└─────────────────────────────────────────────────────────────────┘

Template from an external URL

You can also load templates from a URL:

┌─────────────────────────────────────────────────────────────────┐
│ Settings > App Templates │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Template source: │
│ URL: [https://raw.githubusercontent.com/.../templates.json] │
│ │
│ [Save settings] │
│ │
└─────────────────────────────────────────────────────────────────┘

7 - Webhooks

Trigger a redeployment

Portainer provides webhooks to automate redeployments:

┌─────────────────────────────────────────────────────────────────┐
│ Stack Webhook │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Webhook URL: │
│ https://portainer.example.com/api/stacks/webhook/abc123xyz │
│ │
│ Usage: │
│ curl -X POST https://portainer.example.com/api/.../abc123xyz │
│ │
│ ☑ Enable webhook │
│ │
└─────────────────────────────────────────────────────────────────┘

CI/CD integration

# GitHub Actions
- name: Redeploy stack
run: |
curl -X POST ${{ secrets.PORTAINER_WEBHOOK_URL }}

# GitLab CI
deploy:
script:
- curl -X POST $PORTAINER_WEBHOOK_URL

8 - Stack examples

Development stack

version: "3.9"

services:
app:
build: .
ports:
- "3000:3000"
volumes:
- ./src:/app/src
environment:
- NODE_ENV=development
depends_on:
- db
- redis

db:
image: postgres:15
environment:
POSTGRES_PASSWORD: devpassword
volumes:
- pg_data:/var/lib/postgresql/data

redis:
image: redis:7-alpine

adminer:
image: adminer
ports:
- "8080:8080"

volumes:
pg_data:

Monitoring stack

version: "3.9"

services:
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus

grafana:
image: grafana/grafana
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}

volumes:
prometheus_data:
grafana_data:

Summary

FeatureDescription
StacksDocker Compose deployment
TemplatesPredefined applications
Git integrationStacks from repositories
GitOpsAutomatic redeployment
WebhooksCI/CD integration
Key points
  • Stacks simplify multi-container deployment
  • Templates speed up setting up applications
  • Git integration enables GitOps
  • Webhooks automate deployments

Practical exercises

  1. Deploy a WordPress stack through the web editor
  2. Create a custom template
  3. Configure a stack from a Git repo
  4. Test the redeployment webhook

← Volumes and networks | Users and RBAC →