Running a home server can be an excellent way to self-host various web services, but it often comes with the challenge of resource management. While we want our services to be readily available, keeping them running continuously isn’t always necessary or efficient, especially for services we only access occasionally. This article explores how to implement an intelligent container management solution using Treafik and Sablier.
Background
When setting up a home server with Docker containers, we typically configure a reverse proxy (like Traefik) to route traffic to our various services. However, this traditional setup keeps containers running permanently, consuming resources even during periods of inactivity. By introducing Sablier into this architecture, we can create a more efficient “scale-to-zero” system that automatically manages container lifecycles based on actual usage.
Understanding Sablier
Sablier is a powerful plugin that integrates with popular proxy servers, particularly Traefik. Its primary function is to monitor traffic to your services and manage their container lifecycle accordingly. When a service receives no traffic for a specified period, Sablier will automatically shut it down. When new traffic arrives, Sablier can restart the service, either showing a loading screen or waiting for the service to become available.
Implementation Guide
1. Setting Up the Sablier Container
First, we need to add the Sablier service to our Docker Compose configuration:
services:
traefik:
container_name: traefik
image: traefik:v3
ports:
- "80:80"
- "443:443"
- "8080:8080"
environment:
- CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
- TZ=Europe/Bratislava
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./config/traefik.yaml:/etc/traefik/traefik.yaml:ro
- ./config/dynamic:/etc/traefik/dynamic:ro
- ./config/certs:/var/traefik/certs:rw
- ./logs:/etc/traefik/log:rw
networks:
- traefik
restart: unless-stopped
sablier:
container_name: trefik-sablier
image: sablierapp/sablier:1.8.1
command:
- start
- --provider.name=docker
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- traefik
restart: unless-stopped
networks:
traefik:
name: traefik
external: trueThis configuration:
- User the Treafik configuration from the article Traefik - Configuring a Secure Docker Proxy
- Uses the official Sablier image
- Provides access to the Docker socket for container management
- Connects to the Traefik network
- Ensures the service restarts automatically if it stops unexpectedly
2. Configuring Traefik Integration
Next, we need to register Sablier as a plugin in our Traefik configuration (traefik.yaml):
# ...
################################################################
# Configuration providers
################################################################
providers:
docker:
endpoint: unix:///var/run/docker.sock
exposedByDefault: false
network: traefik
file:
directory: /etc/traefik/dynamic/
watch: true
# ...
################################################################
# Plugins
################################################################
experimental:
plugins:
sablier:
moduleName: "github.com/sablierapp/sablier"
version: "v1.8.1"3. Implementing Dynamic Service Configuration
Instead of using container labels, we’ll use dynamic configuration to set up our service routing and Sablier integration:
http:
services:
blog-service:
loadBalancer:
servers:
- url: http://blog:8080
routers:
blog-http-router:
rule: "Host(`blog.zloutek1.com`) || Host(`blog.epicartificials.com`)"
service: blog-service
middlewares:
- blog-sablier@file
entryPoints:
- http
blog-https-router:
rule: "Host(`blog.zloutek1.com`) || Host(`blog.epicartificials.com`)"
service: blog-service
middlewares:
- blog-sablier@file
entryPoints:
- https
tls:
certResolver: cloudflare
middlewares:
blog-sablier:
plugin:
sablier:
sablierUrl: http://sablier:10000
sessionDuration: 30m
names: blog
dynamic:
displayName: blog
refreshFrequency: 3s
showDetails: true
theme: ghostThis configuration implements several important features:
- Sets up both HTTP and HTTPS routing for the blog service
- Configures Sablier middleware with a 30-minute session duration
- Implements a dynamic strategy with the “ghost” theme for loading screens
- Enables automatic container management based on traffic patterns
How It Works
When this configuration is active, the system operates as follows:
- When a user accesses http://blog.zloutek1.com, Traefik receives the request
- If the blog container is stopped, Sablier intercepts the request
- Sablier starts the blog container
- During startup, users see the ghost theme loading screen
- Once the container is ready, traffic is forwarded to the blog service
- After 30 minutes of inactivity, Sablier automatically stops the container
This approach provides several benefits:
- Reduces resource usage during inactive periods
- Maintains service availability when needed
- Provides a smooth user experience during container startup
- Automatically manages container lifecycle without manual intervention
Configuration Options
Sablier offers two main strategies for handling requests during container startup:
- Dynamic Strategy: Shows a loading screen (like the ghost theme used above)
- Blocking Strategy: Waits for the service to start before responding
Choose the strategy that best fits your service’s needs and user experience requirements.
Further Reading
For more detailed information about implementing scale-to-zero solutions with Docker, see the article Docker Scale-to-Zero with Traefik and Sablier which provides additional configuration examples and best practices.