Managing Multi-Container Applications with Portainer Stacks
Learn how to use Portainer Stacks to deploy multi-container applications using Docker Compose, including Git synchronization and avoiding common volume path errors.
06 Aug 2026, 23:09 UTC

Solving the Orchestration Gap in Portainer
Deploying individual containers via a GUI is efficient for simple tools, but complex applications require multiple interdependent services—such as a web frontend, an API, and a database—to share a network and lifecycle. The solution is Stacks, Portainer's implementation of Docker Compose. Stacks allow you to define your entire application architecture in a single YAML file, ensuring that services are deployed in the correct order and with the necessary networking constraints.
How Stacks Translate YAML to Infrastructure
When you deploy a Stack, Portainer does not simply run a shell command. It parses the Docker Compose specification and communicates with the Docker API to create the required resources. This process ensures that volumes are initialized and virtual networks are established before the containers attempt to start.
Worked Example: Deploying a Redis-backed Web App
To deploy a multi-container application, navigate to Stacks > Add stack. Select the Web editor and use the following configuration. This example demonstrates service linking and environment variable usage.
version: '3.8'
services:
web-app:
image: nginx:latest
ports:
- "8080:80"
environment:
- REDIS_HOST=cache-service
depends_on:
- cache-service
cache-service:
image: redis:alpine
networks:
- backend-net
networks:
backend-net:
driver: bridge
Deployment Steps:
- Input: Paste the YAML above into the Portainer Web editor.
- Permissions: Ensure the Portainer agent has
rootordockergroup permissions on the target node to create networks and volumes. - Execution: Click Deploy the stack.
- Verification: Navigate to the Containers list. You should see two containers running, both associated with the same Stack name.
Git-Based Synchronization and Version Control
For production environments, pasting YAML into a browser is a risk. Portainer supports Git Repository deployments, which treat your repository as the single source of truth. This enables two critical workflows:
- Polling: Portainer checks the repository at a defined interval (e.g., every 5 minutes) and automatically redeploys the stack if the
docker-compose.ymlfile changes. - Webhooks: You can configure a webhook URL in Portainer and add it to your GitHub/GitLab repository. When you push a commit, the repository notifies Portainer to trigger an immediate update.
Critical Limitations and Common Failures
While Stacks simplify deployment, certain configurations can cause silent failures or deployment timeouts.
The Relative Path Trap
A common mistake is using relative paths for volume mounts, such as - ./data:/var/lib/mysql. When deploying via the Portainer UI or Git, the "current directory" is the Portainer agent's working directory, not the folder where your Git repo lives or where you expect the data to be on the host. Always use absolute paths (e.g., - /home/user/app/data:/var/lib/mysql) or named Docker volumes to ensure persistence.
Environment Variable Persistence
Variables defined within the Compose file are static. For secrets or environment-specific configs, use the Environment variables section in the Portainer Stack creation screen. These are injected into the containers at runtime and are easier to manage than editing the YAML file for every environment change.
API Timeout Limits
Extremely large Compose files (dozens of services) may trigger API timeouts during the initial deployment phase. If a stack hangs at "Deploying," check the Portainer logs. You may need to split the application into smaller, logically separated stacks that communicate via an external shared network.
Verification and Rollback
To verify the result of a deployment, run the following command on the host node to ensure the network was created correctly:
docker network ls | grep [stack-name]
Rollback: Because Stacks change the state of the Docker engine (creating networks and volumes), the only way to fully revert is to use the Remove button within the Stack menu. This stops all associated containers and deletes the virtual network created for that stack. Note that volumes marked as external: true will not be deleted.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.