Published by bobo on May 5, 2025
If you love the simplicity of Docker Swarm but want a UI-driven way to manage it, Portainer Business Edition (BE) is your best friend. With Portainer BE, you can deploy stacks, manage secrets/configs, label nodes, and monitor everything — all from your browser.
In this post, we’ll walk through Swarm best practices using Portainer BE for:
✅ Environment configs
✅ Secret management
✅ Clean stack deployments
✅ Labeling nodes and services
Let’s turn that CLI workload into a well-managed, GUI-powered orchestration setup.
What You’ll Need
- Docker Swarm cluster (init using docker swarm init)
- Portainer Business Edition installed (check portainer.io)
- Portainer agent deployed to all nodes
- Admin access to Portainer UI
1. Managing Configs with Portainer
- Config in portainer only works if you are deploying via CLI or within portainer editor. This will not work for repository deployments from places like GitHub. in that scene configs can be stored via environment section of the stack, you will need to create for each stack you create.
Instead of hardcoding environment variables or editing containers manually, Portainer lets you centrally manage and reuse configuration files through its Configs feature.
This is super handy for things like:
- Time zone settings
- Paths for persistent storage
- App behavior toggles
✅ Example 1: Define a Global Time Zone
You can standardize your container time zone across stacks.
- In Portainer, go to Configs > + Add Config
- Name it tz_config
- Add content:
TZ=America/Toronto
- In your docker-compose.yml:
configs:
- source: tz_config
target: /etc/config/tz_env
services:
app:
image: myapp
env_file: /etc/config/tz_env
Your app now reads the TZ from the mounted config.
✅ Example 2: Storage Path for Volume Mounting
Set a common storage path used across stacks — especially useful when your host paths vary per environment.
- Add a new config:Name: storage_config
DATA_PATH=/mnt/swarm_storage/data
- Reference it in your container as a sourced environment file:
services:
app:
image: myapp
configs:
- source: storage_config
target: /etc/config/storage_env
volumes:
- ${DATA_PATH}/app:/var/lib/app
env_file: /etc/config/storage_env
This keeps your deployment logic clean and environment-aware without baking paths into your compose file.
✅ Best Practice: Use configs for anything you would normally keep in a .env file — but manage it securely and centrally in Portainer. This helps enforce consistency across environments (dev, staging, prod) while staying stateless and declarative.
Would you like me to add a diagram showing how these configs integrate into a container deployment via Portainer? centralized and version-controlled inside Portainer. It improves reusability and keeps your containers stateless.
2. Manage Secrets Securely in Portainer
Secrets should never live in .env files. Portainer BE lets you create and attach secrets directly in the UI with role-based access control.
*note: you can use the secrets method described below but need to add at the bottom pf the yaml file
secrets:
external
✅ Steps in Portainer:
- Navigate to Secrets > + Add Secret.
- Name it db_password and paste your secret securely.
- In your stack file:
secrets:
- db_password
services:
db:
image: postgres
secrets:
- source: db_password
target: db_password
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
Secrets are mounted as read-only files at runtime — safe, elegant, and portable.
✅ Best Practice: Rotate secrets regularly and restrict access to teams/groups via Portainer RBAC.
3. Deploy Stacks the Smart Way
Using Portainer’s Stacks feature is a clean, versioned, and rollback-friendly way to deploy containers in Swarm mode.
✅ Steps to Deploy:
- Go to Stacks > + Add Stack.
- enter repository deployment type and enter access credentials for your GitHub repo.
- Set stack name: my_stack.
- Click Deploy Stack.
✅ Best Practices:
- Always use the “deploy” key to control update strategy:
deploy:
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
- Enable healthchecks to catch failing services early:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000"]
interval: 30s
retries: 3
4. Use Labels for Structure and Placement
Portainer lets you manage labels on both nodes and services, which is essential for organizing workloads.
✅ Node Labels
- Go to Nodes > select a node.
- Click + Add Label, e.g., role=backend.
In your stack:
deploy:
placement:
constraints:
- node.labels.role == backend
✅ Service Labels
- In your docker-compose.yml, add:
labels:
com.example.stack: "api"
traefik.enable: "true"
These help with service discovery, Traefik config, and UI filtering in Portainer.
✅ Best Practice: Use a consistent label naming scheme across your team.
Bonus: Prune and Monitor
Portainer BE includes:
- Service health monitoring
- Container logs and metrics
- One-click cleanup tools for unused volumes, images, and stopped containers
Stay lean by regularly reviewing Volumes, Networks, and Stacks in Portainer’s dashboards.
Summary Table
Feature | Portainer Best Practice |
---|---|
Environment | Use Configs for static env vars instead of .env files |
Secrets | Manage and mount via Portainer Secrets with _FILE support |
Deployments | Use Stacks with rolling update configs and health checks |
Labels | Use Node/Service labels for scheduling and monitoring |
Maintenance | Use Portainer’s UI for cleanups, monitoring, and access logs |
Wrapping Up
Docker Swarm gets a bad rep for being “too simple,” but with Portainer Business Edition, you unlock enterprise-level control with almost no effort. It’s GUI-driven DevOps that still respects the CLI roots.
If you’re managing a homelab, dev cluster, or even staging environments — this combo gives you the flexibility of Swarm with the usability of a control panel.