Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: container not registered after restart #5

Merged
merged 4 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 17 additions & 43 deletions bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"strconv"
"strings"
"sync"
"time"

dockerapi "github.com/fsouza/go-dockerclient"
)
Expand All @@ -20,12 +19,11 @@ var serviceIDPattern = regexp.MustCompile(`^(.+?):([a-zA-Z0-9][a-zA-Z0-9_.-]+):[

type Bridge struct {
sync.Mutex
registry RegistryAdapter
docker *dockerapi.Client
services map[string][]*Service
deadContainers map[string]*DeadContainer
dyingContainers map[string]time.Time
config Config
registry RegistryAdapter
docker *dockerapi.Client
services map[string][]*Service
deadContainers map[string]*DeadContainer
config Config
}

func New(docker *dockerapi.Client, adapterUri string, config Config) (*Bridge, error) {
Expand All @@ -40,12 +38,11 @@ func New(docker *dockerapi.Client, adapterUri string, config Config) (*Bridge, e

log.Println("Using", uri.Scheme, "adapter:", uri)
return &Bridge{
docker: docker,
config: config,
registry: factory.New(uri),
services: make(map[string][]*Service),
deadContainers: make(map[string]*DeadContainer),
dyingContainers: make(map[string]time.Time),
docker: docker,
config: config,
registry: factory.New(uri),
services: make(map[string][]*Service),
deadContainers: make(map[string]*DeadContainer),
}, nil
}

Expand Down Expand Up @@ -94,18 +91,19 @@ func (b *Bridge) Sync(quiet bool) {
b.Lock()
defer b.Unlock()

containers, err := b.docker.ListContainers(dockerapi.ListContainersOptions{})
filters := map[string][]string{"status": {"running", "restarting"}}
runningContainers, err := b.docker.ListContainers(dockerapi.ListContainersOptions{Filters: filters})
if err != nil && quiet {
log.Println("error listing containers, skipping sync")
log.Println("skipping sync, listing containers failed:", err)
return
} else if err != nil && !quiet {
log.Fatal(err)
}

log.Printf("Syncing services on %d containers", len(containers))
log.Printf("Syncing services on %d running containers", len(runningContainers))

// NOTE: This assumes reregistering will do the right thing, i.e. nothing..
for _, listing := range containers {
for _, listing := range runningContainers {
services := b.services[listing.ID]
if services == nil {
b.add(listing.ID, quiet)
Expand All @@ -124,23 +122,17 @@ func (b *Bridge) Sync(quiet bool) {
if b.config.Cleanup {
// Remove services if its corresponding container is not running
log.Println("Listing non-exited containers")
filters := map[string][]string{"status": {"created", "restarting", "running", "paused"}}
nonExitedContainers, err := b.docker.ListContainers(dockerapi.ListContainersOptions{Filters: filters})
if err != nil {
log.Println("error listing nonExitedContainers, skipping sync", err)
return
}
for listingId := range b.services {
found := false
for _, container := range nonExitedContainers {
for _, container := range runningContainers {
if listingId == container.ID {
found = true
break
}
}
// This is a container that does not exist
if !found {
log.Printf("stale: Removing service %s because it does not exist", listingId)
log.Printf("stale: Removing service %s because it's container is not running ", listingId)
go b.RemoveOnExit(listingId)
}
}
Expand Down Expand Up @@ -184,11 +176,6 @@ func (b *Bridge) Sync(quiet bool) {
}

func (b *Bridge) add(containerId string, quiet bool) {
if _, ok := b.dyingContainers[containerId]; ok {
log.Println("container, ", containerId[:12], ", is dying, ignoring")
return
}

if d := b.deadContainers[containerId]; d != nil {
b.services[containerId] = d.Services
delete(b.deadContainers, containerId)
Expand Down Expand Up @@ -389,7 +376,6 @@ func (b *Bridge) remove(containerId string, deregister bool) {
b.deadContainers[containerId] = &DeadContainer{b.config.RefreshTtl, b.services[containerId]}
}
delete(b.services, containerId)
b.markContainerAsDying(containerId)
}

// bit set on ExitCode if it represents an exit via a signal
Expand Down Expand Up @@ -423,18 +409,6 @@ func (b *Bridge) shouldRemove(containerId string) bool {
return false
}

func (b *Bridge) markContainerAsDying(containerId string) {
// cleanup after CleanupDyingTtl
for containerId, t := range b.dyingContainers {
if time.Since(t) >= time.Millisecond*time.Duration(b.config.CleanupDyingTtl) {
delete(b.dyingContainers, containerId)
}
}

// mark container as "dying"
b.dyingContainers[containerId] = time.Now()
}

var Hostname string

func init() {
Expand Down
1 change: 0 additions & 1 deletion bridge/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ type Config struct {
RefreshInterval int
DeregisterCheck string
Cleanup bool
CleanupDyingTtl int
}

type Service struct {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.23.2

require (
github.com/coreos/go-etcd v2.0.0+incompatible
github.com/docker/docker v27.3.1+incompatible
github.com/fsouza/go-dockerclient v1.12.0
github.com/gliderlabs/pkg v0.0.0-20161206023812-36f28d47ec7a
github.com/hashicorp/consul/api v1.29.5
Expand All @@ -19,7 +20,6 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/docker v27.3.1+incompatible // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/fatih/color v1.16.0 // indirect
Expand Down
13 changes: 6 additions & 7 deletions registrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"time"

dockerevents "github.com/docker/docker/api/types/events"
dockerapi "github.com/fsouza/go-dockerclient"
"github.com/gliderlabs/pkg/usage"
"github.com/simplesurance/registrator/bridge"
Expand All @@ -33,7 +34,6 @@ var (
retryAttempts = flag.Int("retry-attempts", 0, "Max retry attempts to establish a connection with the backend. Use -1 for infinite retries")
retryInterval = flag.Int("retry-interval", 2000, "Interval (in millisecond) between retry-attempts.")
cleanup = flag.Bool("cleanup", false, "Remove dangling services")
cleanupDyingTtl = flag.Int("ttl-dying-cleanup", 60000, "TTL (in millisecond) for cleaning dying containers cache")
)

func assert(err error) {
Expand Down Expand Up @@ -109,7 +109,6 @@ func main() {
RefreshInterval: *refreshInterval,
DeregisterCheck: *deregister,
Cleanup: *cleanup,
CleanupDyingTtl: *cleanupDyingTtl,
})

assert(err)
Expand All @@ -132,7 +131,7 @@ func main() {
}

// Start event listener before listing containers to avoid missing anything
events := make(chan *dockerapi.APIEvents)
events := make(chan *dockerapi.APIEvents, 128)
assert(docker.AddEventListener(events))
log.Println("Listening for Docker events ...")

Expand Down Expand Up @@ -174,12 +173,12 @@ func main() {

// Process Docker events
for msg := range events {
switch msg.Status {
case "start":
switch dockerevents.Action(msg.Action) {
case dockerevents.ActionStart, dockerevents.ActionUnPause:
go b.Add(msg.ID)
case "die":
case dockerevents.ActionDie:
go b.RemoveOnExit(msg.ID)
case "kill":
case dockerevents.ActionKill:
if *deregisterOnStop {
go b.RemoveOnExit(msg.ID)
}
Expand Down
Loading