====== Building New Docker Services with Traefik (for Portainer) ======
This guide provides a standardized process for adding new applications to your existing Docker environment, using **Docker Compose Stacks** managed by **Portainer** and automatically routing traffic through the **Traefik** reverse proxy.
----
===== 🚀 Overview of the Process =====
To integrate a new service (e.g., a new app, a database, etc.) into your environment, you'll create a new, dedicated ''`docker-compose.yml`'' file.
- **Create Service Containers:** Define the application and its dependencies (like a database) in the ''`services`'' section.
- **Define Traefik Labels:** Apply specific Docker labels to the **application container** so Traefik knows how to route incoming traffic (e.g., which hostname to listen for and which port to forward to).
- **Use Dedicated Networks:** Containers must be on a private, isolated network for internal communication (e.g., app ⇔ DB) and connect to the existing **Traefik Network** for external access.
- **Deploy via Portainer:** Paste the Compose file into a new Stack in Portainer.
----
===== 📝 New Service Template (docker-compose.newapp.yml) =====
Use this template as the basis for any new service you want to expose via Traefik. Replace all placeholders (''`<...>`'' and ''`${...}`'') with your service's specific details.
version: '3.7'
services:
# 1. The Application Service (The one that Traefik connects to)
new-app:
image: :
container_name: new-app
restart: unless-stopped
# Environment variables for your app (e.g., database connection)
environment:
DB_HOST: new-app-db # Use the internal service name
DB_USER: ${NEW_APP_DB_USER}
DB_PASSWORD: ${NEW_APP_DB_PASSWORD}
# ... other app settings ...
# Connect to the private network for internal comms and Traefik's network for external exposure
networks:
- new-app-internal
- traefik-proxy # MUST be the name of your external Traefik network
# Traefik Labels (REQUIRED for routing)
labels:
# Enable Traefik for this service
- "traefik.enable=true"
# 1. Router Definition (Listens for incoming connections)
- "traefik.http.routers.new-app.rule=Host(`${NEW_APP_HOSTNAME}`)"
- "traefik.http.routers.new-app.entrypoints=websecure"
- "traefik.http.routers.new-app.tls=true"
- "traefik.http.routers.new-app.tls.certresolver=letsencrypt" # IMPORTANT: Match your Traefik resolver name (e.g., 'le')
# 2. Service Definition (Where to send the traffic inside the container)
# Port is the internal port the application listens on (e.g., 80, 3000, 8080)
- "traefik.http.services.new-app-service.loadbalancer.server.port="
# Optional: Add any desired middleware (e.g., for security or redirects)
# - "traefik.http.routers.new-app.middlewares=@docker"
volumes:
- new-app-data:/app/data
depends_on:
- new-app-db
# 2. The Database Service (or any other dependency)
new-app-db:
image: postgres:15-alpine # Example database
container_name: new-app-db
restart: unless-stopped
environment:
POSTGRES_USER: ${NEW_APP_DB_USER}
POSTGRES_PASSWORD: ${NEW_APP_DB_PASSWORD}
POSTGRES_DB: ${NEW_APP_DB_NAME}
volumes:
- new-app-db-data:/var/lib/postgresql/data
networks:
- new-app-internal # Database MUST be on the isolated internal network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${NEW_APP_DB_USER}"]
interval: 10s
timeout: 5s
retries: 5
networks:
# 1. Isolated Internal Bridge Network (For App <-> DB communication)
new-app-internal:
driver: bridge
# 2. External Traefik Network (For Traefik access to the App)
traefik-proxy:
external: true
# IMPORTANT: The 'name' must match the network Traefik is running on.
# In your environment, this might be 'default', 'web', or 'traefik-proxy'.
name: traefik-proxy
volumes:
new-app-data:
new-app-db-data:
----
===== 🛠️ Step-by-Step Portainer Deployment =====
==== 1. Prepare Environment Variables (.env) ====
Before deploying, you need to define the variables used in the compose file.
Create an ''`.env`'' file (or prepare to enter these variables directly into Portainer's environment variables section):
NEW_APP_HOSTNAME=newapp.yourdomain.com
NEW_APP_DB_USER=secureuser
NEW_APP_DB_PASSWORD=SuperSecretDBPassword!
NEW_APP_DB_NAME=newapp_production
==== 2. Configure DNS ====
Go to your DNS provider and create an **A record** that points your chosen hostname to the public IP address of the server running Traefik:
| Type | Name (Host) | Value (Points To) |
| ---- | ---- | ---- |
| **A** | ''`newapp.yourdomain.com`'' | ''``'' |
==== 3. Deploy the Stack in Portainer ====
- Log in to Portainer and navigate to **Stacks**.
- Click **+ Add stack**.
- Enter a descriptive **Name** for your stack (e.g., ''`new-app-stack`'').
- In the **Web Editor**, paste the content of the ''`docker-compose.newapp.yml`'' template, with all placeholders filled in.
- If you have an ''`.env`'' file, use the "Upload environment file" option. Otherwise, scroll down to **Environment variables** and manually add the variables defined in Step 1.
- Click **Deploy the stack**.
Traefik will detect the new container, read the labels, and automatically start the process of obtaining an SSL certificate for ''`newapp.yourdomain.com`''. Your service should be accessible via HTTPS within a few minutes.