diff --git a/docs/guide/swarm-mode.md b/docs/guide/swarm-mode.md index 826c4017..ef464825 100644 --- a/docs/guide/swarm-mode.md +++ b/docs/guide/swarm-mode.md @@ -38,7 +38,7 @@ networks: Note that the `DOZZLE_MODE` environment variable is set to `swarm`. This tells Dozzle to automatically discover other Dozzle instances in the swarm. The `overlay` network is used to create the mesh network between the different Dozzle instances. > [!NOTE] -> Due to implementation details, the name for the service must be exactly `dozzle`. This is because Dozzle uses the service name to discover other Dozzle instances in the swarm. In the future, it would make sense to query the Docker API for all services with the current container ID. +> Due to implementation details, the name for the service must be exactly `dozzle`. This is no longer required starting with version `v8.2`. You can name the service anything you want. The service name is automatically detected by Dozzle using `com.docker.swarm.service.name` label. ## Setting up simple authentication in Swarm Mode diff --git a/examples/docker.swarm.yml b/examples/docker.swarm.yml index fe63d4c5..2d68601b 100644 --- a/examples/docker.swarm.yml +++ b/examples/docker.swarm.yml @@ -1,6 +1,6 @@ services: - dozzle: - image: amir20/dozzle:latest + my-dozzle-service: + image: amir20/dozzle:local-test environment: - DOZZLE_LEVEL=debug - DOZZLE_MODE=swarm diff --git a/internal/support/docker/swarm_client_manager.go b/internal/support/docker/swarm_client_manager.go index 573ae9af..080b19e7 100644 --- a/internal/support/docker/swarm_client_manager.go +++ b/internal/support/docker/swarm_client_manager.go @@ -5,6 +5,7 @@ import ( "crypto/tls" "fmt" "net" + "os" "sync" "github.com/amir20/dozzle/internal/agent" @@ -23,6 +24,7 @@ type SwarmClientManager struct { subscribers *xsync.MapOf[context.Context, chan<- docker.Host] localClient docker.Client localIPs []string + name string } func localIPs() []string { @@ -47,12 +49,27 @@ func NewSwarmClientManager(localClient docker.Client, certs tls.Certificate) *Sw localService := NewDockerClientService(localClient) clientMap[localClient.Host().ID] = localService + id, ok := os.LookupEnv("HOSTNAME") + if !ok { + log.Fatal("HOSTNAME environment variable not set when looking for swarm service name") + } + + container, err := localClient.FindContainer(id) + if err != nil { + log.Fatalf("error finding container %s: %v", id, err) + } + + serviceName := container.Labels["com.docker.swarm.service.name"] + + log.Debugf("found swarm internal service name: %s", serviceName) + return &SwarmClientManager{ localClient: localClient, clients: clientMap, certs: certs, subscribers: xsync.NewMapOf[context.Context, chan<- docker.Host](), localIPs: localIPs(), + name: serviceName, } } @@ -67,13 +84,15 @@ func (m *SwarmClientManager) Subscribe(ctx context.Context, channel chan<- docke func (m *SwarmClientManager) RetryAndList() ([]ClientService, []error) { m.mu.Lock() + + log.Debugf("looking up swarm services: tasks.%s", m.name) + ips, err := net.LookupIP(fmt.Sprintf("tasks.%s", m.name)) + errors := make([]error, 0) - - ips, err := net.LookupIP("tasks.dozzle") - if err != nil { log.Fatalf("error looking up swarm services: %v", err) errors = append(errors, err) + m.mu.Unlock() return m.List(), errors }