mirror of
https://github.com/zix99/traefik-lazyload.git
synced 2025-12-21 21:33:09 +01:00
Some docs and cleanup
This commit is contained in:
96
README.md
96
README.md
@@ -1,12 +1,104 @@
|
||||
# traefik-lazyloader
|
||||
|
||||
Takes advantage of traefik's router priority to proxy to this small application that will manage
|
||||
starting/stopping containers to save resources.
|
||||
This small app will automatically start and stop docker containers based on access, for instance,
|
||||
via traefik.
|
||||
|
||||
## How it Works
|
||||
|
||||
It works by acting as the fallback-route for the containers. For instance, if you have
|
||||
`example.com` as a container you want to lazy-load, you would add the container, as well
|
||||
as this lazyloader that would act as a lower-priority router for the same domain. If the
|
||||
host is accessed, the lazyloader will work to boot up the container and redirect the user
|
||||
as soon as it's up.
|
||||
|
||||
It then monitors the container's network interface. If the network is idle for X minutes, it
|
||||
will stop the container.
|
||||
|
||||
## Quick-Start
|
||||
|
||||
### docker-compose
|
||||
```yaml
|
||||
version: '3.5'
|
||||
|
||||
services:
|
||||
reverse-proxy:
|
||||
image: traefik:v2.4
|
||||
command:
|
||||
- --api.insecure
|
||||
- --providers.docker
|
||||
- --providers.docker.defaultRule=Host(`{{.Name}}.example.com`)
|
||||
- --entryPoints.web.address=:80
|
||||
- --entryPoints.web.forwardedHeaders.insecure
|
||||
- --providers.docker.exposedByDefault=false
|
||||
restart: always
|
||||
ports:
|
||||
- "80:80" # The HTTP port
|
||||
- "8080:8080" # The Web UI (enabled by --api)
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events
|
||||
|
||||
lazyloader:
|
||||
build: .
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- "traefik.http.routers.lazyload.priority=-100" # Lower router priority. Would only be hit if the app isn't running
|
||||
- "traefik.http.routers.lazyload.rule=Host(`whoami.example.com`, `lazyloader.example.com`)"
|
||||
environment:
|
||||
TLL_STOPATBOOT: true # Stop all lazyloaded containers at boot (great for an example)
|
||||
TLL_STATUSHOST: lazyloader.example.com # This hostname will display a status page. Disabled by default
|
||||
networks:
|
||||
- traefik-bridge
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock # Must access docker
|
||||
|
||||
whoami:
|
||||
image: containous/whoami
|
||||
networks:
|
||||
- traefik-bridge
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- "traefik.http.routers.lazywhoami.rule=Host(`whoami.example.com`)"
|
||||
- lazyloader=true
|
||||
- lazyloader.stopdelay=30s # Overrides the default
|
||||
|
||||
networks:
|
||||
traefik-bridge:
|
||||
external: true
|
||||
name: traefik-bridge
|
||||
```
|
||||
|
||||
You can run `docker-compose up` on the above for a quick-start. You will need to alter the domains as needed.
|
||||
|
||||
## Config
|
||||
|
||||
Configuration uses [viper]() and can be specified by either overwriting the `config.yaml` file or
|
||||
via environment variables with the `TLL_` prefix (Traefik lazy loader)
|
||||
|
||||
```yaml
|
||||
# What port to listen on
|
||||
listen: :8080
|
||||
|
||||
# If set, when access via this hostname, will display status page
|
||||
statushost: ""
|
||||
|
||||
# Enable debug logging
|
||||
verbose: false
|
||||
|
||||
# if true, will stop all running tagged containers when the lazyloader starts
|
||||
stopatboot: false
|
||||
|
||||
# which splash-page asset to use
|
||||
splash: splash.html
|
||||
|
||||
# Container defaults
|
||||
stopdelay: 5m # How long to wait before stopping container
|
||||
pollfreq: 10s # How often to check
|
||||
|
||||
# This will be the label-prefix to look at settings on a container
|
||||
# usually won't need to change (only if running multiple instances)
|
||||
labelprefix: lazyloader
|
||||
```
|
||||
|
||||
## Labels
|
||||
|
||||
* `lazyloader=true` -- (Required) Add to containers that should be managed
|
||||
|
||||
21
config.yaml
21
config.yaml
@@ -1,11 +1,22 @@
|
||||
# What port to listen on
|
||||
listen: :8080
|
||||
|
||||
stopatboot: false
|
||||
splash: splash.html
|
||||
|
||||
stopdelay: 5m
|
||||
pollfreq: 10s
|
||||
# If set, when access via this hostname, will display status page
|
||||
statushost: ""
|
||||
|
||||
# Enable debug logging
|
||||
verbose: false
|
||||
|
||||
# if true, will stop all running tagged containers when the lazyloader starts
|
||||
stopatboot: false
|
||||
|
||||
# which splash-page asset to use
|
||||
splash: splash.html
|
||||
|
||||
# Container defaults
|
||||
stopdelay: 5m # How long to wait before stopping container
|
||||
pollfreq: 10s # How often to check
|
||||
|
||||
# This will be the label-prefix to look at settings on a container
|
||||
# usually won't need to change (only if running multiple instances)
|
||||
labelprefix: lazyloader
|
||||
2
main.go
2
main.go
@@ -94,7 +94,7 @@ func StatusHandler(w http.ResponseWriter, r *http.Request) {
|
||||
runtime.ReadMemStats(&stats)
|
||||
statusPageTemplate.Execute(w, StatusPageModel{
|
||||
Active: core.ActiveContainers(),
|
||||
Qualifying: core.QualifyingContainers(),
|
||||
Qualifying: core.QualifyingContainers(r.Context()),
|
||||
RuntimeMetrics: fmt.Sprintf("Heap=%d, InUse=%d, Total=%d, Sys=%d, NumGC=%d", stats.HeapAlloc, stats.HeapInuse, stats.TotalAlloc, stats.Sys, stats.NumGC),
|
||||
})
|
||||
default:
|
||||
|
||||
@@ -74,7 +74,6 @@ func (s *Core) StartHost(hostname string) (*StartResult, error) {
|
||||
}
|
||||
|
||||
if ets, exists := s.active[ct.ID]; exists {
|
||||
// TODO: Handle case we think it's active, but not? (eg. crash? slow boot?)
|
||||
logrus.Debugf("Asked to start host, but we already think it's started: %s", ets.name)
|
||||
return &StartResult{
|
||||
WaitForCode: ets.waitForCode,
|
||||
@@ -265,6 +264,7 @@ func (s *Core) findAllLazyloadContainers(ctx context.Context, includeStopped boo
|
||||
})
|
||||
}
|
||||
|
||||
// Returns all actively managed containers
|
||||
func (s *Core) ActiveContainers() []*ContainerState {
|
||||
s.mux.Lock()
|
||||
defer s.mux.Unlock()
|
||||
@@ -279,8 +279,9 @@ func (s *Core) ActiveContainers() []*ContainerState {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *Core) QualifyingContainers() []string {
|
||||
ct, err := s.findAllLazyloadContainers(context.Background(), true)
|
||||
// Return all containers that qualify to be load-managed (eg. have the tag)
|
||||
func (s *Core) QualifyingContainers(ctx context.Context) []string {
|
||||
ct, err := s.findAllLazyloadContainers(ctx, true)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"traefik-lazyload/pkg/config"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
@@ -22,7 +23,7 @@ func labelOrDefault(ct *types.Container, sublabel, dflt string) (string, bool) {
|
||||
return dflt, false
|
||||
}
|
||||
|
||||
func short(id string) string {
|
||||
func shortId(id string) string {
|
||||
const SLEN = 8
|
||||
if len(id) <= SLEN {
|
||||
return id
|
||||
@@ -33,11 +34,18 @@ func short(id string) string {
|
||||
func containerShort(c *types.Container) string {
|
||||
var name string
|
||||
if len(c.Names) > 0 {
|
||||
name = c.Names[0]
|
||||
name = trimRootPath(c.Names[0])
|
||||
} else {
|
||||
name = c.Image
|
||||
}
|
||||
return fmt.Sprintf("%s(%s)", name, short(c.ID))
|
||||
return fmt.Sprintf("%s(%s)", name, shortId(c.ID))
|
||||
}
|
||||
|
||||
func trimRootPath(s string) string {
|
||||
if strings.HasPrefix(s, "/") {
|
||||
return s[1:]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func isRunning(c *types.Container) bool {
|
||||
|
||||
Reference in New Issue
Block a user