====== 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.