Your Docker Containers Are Eating RAM While Doing Nothing — Here’s the Fix #
You’ve got 10, maybe 15 Docker containers running on your VPS. Maybe it’s a Raspberry Pi. Maybe it’s a mini PC tucked behind your router. Maybe it’s the cheapest VPS you could find. Either way, you know the pain: half those containers sit idle 90% of the time, yet they’re still chewing through precious RAM.
Uptime monitors pinging every 30 seconds. A dashboard you check twice a day. An internal tool nobody’s opened in a week. They’re all running. All consuming memory. All doing nothing useful.
What if those containers could sleep until someone actually needs them?
That’s exactly what Sablier does. It’s a free, open-source tool that integrates with Traefik to start containers on-demand and shut them down after a period of inactivity. Think of it as scale-to-zero for your self-hosted stack.
What Is Sablier? #
Sablier is a lightweight middleware that manages the lifecycle of your Docker containers. When a request comes in for a sleeping container, Sablier wakes it up. When the container has been idle for a configurable amount of time, Sablier puts it back to sleep.
It works with:
- Docker (standalone)
- Docker Swarm
- Kubernetes
And it integrates with popular reverse proxies including Traefik, Caddy, and Nginx.
The setup has two parts:
- Sablier server — the backend that talks to Docker via
docker.sockto start/stop containers - Sablier plugin for Traefik — middleware that intercepts incoming requests and coordinates with the server
Two Strategies: Dynamic vs Blocking #
Sablier offers two strategies for handling the wake-up process. Choosing the right one depends on what your container serves.
Dynamic Strategy (Best for Web Apps) #
The Dynamic strategy shows a loading page to the visitor while the container boots up in the background. Once the container is healthy, Sablier redirects to the actual app.
This works great for:
- Web dashboards (Homepage, Dashy, etc.)
- Internal tools with simple UIs
- Any app where a 5-10 second loading screen is acceptable
Blocking Strategy (Best for APIs) #
The Blocking strategy holds the incoming request until the container is fully ready, then forwards it. The visitor sees a brief delay but never sees a loading page.
Use this for:
- REST APIs
- Anything that can’t render an HTML loading page
- Services where a clean response matters more than speed
Note for Safari/iOS users: The Dynamic strategy has known issues on Safari for iOS. If your users access your services from iPhones or iPads, use the Blocking strategy as a fallback.
Prerequisites #
Before starting, make sure you have:
- Docker and Docker Compose installed
- Traefik v3.6.0 or newer (config via Docker labels is supported from this version)
- A running Traefik instance with the Docker provider enabled
- Basic familiarity with Docker labels and Traefik configuration
Step 1: Register the Sablier Plugin in Traefik #
First, you need to tell Traefik about the Sablier plugin. Add it to your traefik.yml under the experimental section:
experimental:
plugins:
sablier:
moduleName: "github.com/acouvreur/sablier"
version: "v1.8.0"If you’re running Traefik via Docker Compose, make sure this config is mounted correctly.
Step 2: Deploy the Sablier Server #
The Sablier server needs access to docker.sock so it can start and stop containers. Here’s a minimal Docker Compose service:
services:
sablier:
image: acouvreur/sablier:latest
container_name: sablier
ports:
- "10000:10000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command:
- start
- --provider.name=docker
restart: unless-stoppedThe server listens on port 10000 by default. Traefik will communicate with it there.
Pro Tip: Start All Containers in Sleep Mode #
If you want Sablier to manage all your containers from the start (rather than them being running initially), use this flag:
command:
- start
- --provider.name=docker
- --provider.auto-stop-on-startupThis tells Sablier to immediately stop any container it’s configured to manage, so everything starts in sleep mode.
Step 3: Configure the Sablier Middleware #
Create a dynamic configuration file (or add it to your existing Traefik dynamic config) to define the Sablier middleware:
http:
middlewares:
sablier:
plugin:
sablierUrl: "http://sablier:10000"
group: "my-apps"
sessionDuration: "5m"
theme: "hacker-terminal"Here’s what each parameter does:
| Parameter | Description |
|---|---|
sablierUrl |
URL of the Sablier server |
group |
Docker label group that Sablier manages |
sessionDuration |
How long a container stays alive after the last request (e.g., 5m, 30m, 1h) |
theme |
Loading page theme for Dynamic strategy |
Available Themes #
Sablier ships with a few built-in themes for the Dynamic strategy loading page:
hacker-terminal— green-on-black terminal aestheticghost— clean, minimal dark themeshuffle— animated loading screen
Pick whichever fits your vibe. It’s a small detail, but it makes the loading experience feel intentional instead of broken.
Step 4: Add Labels to Your Target Containers #
Now for the part that ties everything together. Add these labels to any Docker container you want Sablier to manage:
services:
my-app:
image: my-app:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.my-app.rule=Host(`app.zynji.my.id`)"
- "traefik.http.routers.my-app.middlewares=sablier@docker"
- "sablier.enable=true"
- "sablier.group=my-apps"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10sThe key labels are:
sablier.enable=true— tells Sablier to manage this containersablier.group=my-apps— must match the group name in your middleware configtraefik.http.routers.my-app.middlewares=sablier@docker— attaches the Sablier middleware to the router
Step 5: Add Health Checks #
This is critical. Sablier needs to know when your container is actually ready to serve traffic. Without a health check, Sablier might redirect the user to a container that’s still initializing.
Add a healthcheck block to every container managed by Sablier:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10sAdjust the test command to match whatever health endpoint your app exposes. If your app doesn’t have a health endpoint, you can use a simple TCP check or a command that verifies the process is running.
Step 6: Test It Out #
- Restart Traefik to load the plugin.
- Start your containers.
- Visit the app URL in your browser.
- You should see the loading page (Dynamic strategy) while the container boots.
- After the container is healthy, you’ll be redirected to the app.
- Wait for the
sessionDurationto expire and check that the container stops.
You can verify the container stopped with:
docker ps --filter "name=my-app"It should disappear from the running list after the session duration elapses.
Preventing Uptime Monitors from Waking Containers #
Here’s a gotcha: if you use Uptime Kuma, UptimeRobot, or any HTTP monitor to check your services, those pings will wake up your sleeping containers — defeating the whole purpose.
Sablier solves this with the ignoreUserAgent parameter. Add it to your middleware config:
http:
middlewares:
sablier:
plugin:
sablierUrl: "http://sablier:10000"
group: "my-apps"
sessionDuration: "5m"
theme: "hacker-terminal"
ignoreUserAgent:
- "curl"
- "UptimeKuma"Any request with a matching User-Agent string will pass through without waking the container. Your uptime monitor gets a response (from Sablier itself), but your app stays asleep.
When Scale‑to‑Zero Makes Sense (And When It Doesn’t) #
This setup is ideal for:
- Low‑RAM servers (Raspberry Pi, budget VPS with 1‑2GB RAM)
- Internal tools that aren’t accessed constantly
- Demo/staging environments that only need to be up when someone’s looking
- Side projects where you want zero cost when nobody’s using them
It’s NOT ideal for:
- Production services that need instant response times
- Containers that take 30+ seconds to boot (the delay becomes noticeable)
- Services with WebSocket connections that need to stay alive
- Databases (don’t put your database behind Sablier — that’s a disaster waiting to happen)
FAQ #
Does Sablier work with Docker Compose? #
Yes. The label‑based configuration works directly with Docker‑Compose.
What happens if the Sablier server goes down? #
Traefik will return an error for routes using the Sablier middleware; containers that are already running will continue to work.
Can I use different session durations for different containers? #
The duration is set at the middleware level. To have different durations, create multiple middleware configurations with different sessionDuration values and assign them to different routers.
Is Sablier free? #
Fully open‑source, no paid tiers.
How much RAM can I actually save? #
If each idle container consumes 50‑100 MB, turning off 10 containers can save 500 MB‑1 GB. On a 2 GB RAM device, that’s a huge improvement.
Word count: ~1,450 | Reading time: ~6 min