Skip to content

Commit 35500a7

Browse files
authored
Corrected docker/swarm discovery from previous refactoring (#446)
1 parent 4055f39 commit 35500a7

File tree

9 files changed

+96
-48
lines changed

9 files changed

+96
-48
lines changed

.devcontainer/devcontainer.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
2+
// README at: https://github.com/devcontainers/templates/tree/main/src/go
3+
{
4+
"name": "Go",
5+
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
6+
"image": "golang:1.24-bookworm",
7+
// Features to add to the dev container. More info: https://containers.dev/features.
8+
"features": {
9+
// For in-docker discovery testing
10+
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
11+
},
12+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
13+
"forwardPorts": [
14+
25565
15+
],
16+
17+
containerEnv: {
18+
"GOROOT": "/usr/local/go"
19+
},
20+
21+
// Configure tool-specific properties.
22+
"customizations": {
23+
"jetbrains": {
24+
"backend": "IntelliJ",
25+
"plugins": [
26+
"org.jetbrains.plugins.go"
27+
]
28+
},
29+
"vscode": {
30+
"extensions": [
31+
"golang.go"
32+
]
33+
}
34+
}
35+
}

DEVELOPMENT.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## Developing Docker discovery on non-Linux
2+
3+
This works best with the included devcontaner setup, which includes attaching the host's docker socket to the dev container at `/var/run/docker.sock`.
4+
5+
On Windows, can create the devcontainer using:
6+
7+
![image.png](docs/create-dev-container.png)
8+

README.md

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ The [multi-architecture image published at Docker Hub](https://hub.docker.com/re
103103
The diagram below shows how this `docker-compose.yml` configures two Minecraft server services named `vanilla` and `forge`, which also become the internal network aliases. _Notice those services don't need their ports exposed since the internal networking allows for the inter-container access._
104104

105105
```yaml
106-
version: "3.8"
107-
108106
services:
109107
vanilla:
110108
image: itzg/minecraft-server
@@ -141,20 +139,21 @@ To test out this example, add these two entries to my "hosts" file:
141139

142140
### Using Docker auto-discovery
143141

144-
When running `mc-router` in a Docker environment you can pass the `--in-docker` or `--in-docker-swarm`
145-
command-line argument and it will poll the Docker API periodically to find all the running
146-
containers/services for Minecraft instances. To enable discovery you have to set the `mc-router.host`
147-
label on the container. These are the labels scanned:
148-
149-
- `mc-router.host`: Used to configure the hostname the Minecraft clients would use to
150-
connect to the server. The container/service endpoint will be used as the routed backend. You can
151-
use more than one hostname by splitting it with a comma.
152-
- `mc-router.port`: This value must be set to the port the Minecraft server is listening on.
153-
The default value is 25565.
154-
- `mc-router.default`: Set this to a truthy value to make this server the default backend.
155-
Please note that `mc-router.host` is still required to be set.
156-
- `mc-router.network`: Specify the network you are using for the router if multiple are
157-
present in the container/service. You can either use the network ID, it's full name or an alias.
142+
When running `mc-router` in a Docker environment you can pass the `--in-docker` or `--in-docker-swarm` command-line argument or set the environment variables `IN_DOCKER` or `IN_DOCKER_SWARM` to "true". With that, it will poll the Docker API periodically to find all the running containers/services for Minecraft instances. To enable discovery, you have to set the `mc-router.host` label on the container.
143+
144+
When using in Docker, make sure to volume mount the Docker socket into the container, such as
145+
146+
```yaml
147+
volumes:
148+
- /var/run/docker.sock:/var/run/docker.sock:ro
149+
```
150+
151+
These are the labels scanned:
152+
153+
- `mc-router.host`: Used to configure the hostname the Minecraft clients would use to connect to the server. The container/service endpoint will be used as the routed backend. You can use more than one hostname by splitting it with a comma.
154+
- `mc-router.port`: This value must be set to the port the Minecraft server is listening on. The default value is 25565.
155+
- `mc-router.default`: Set this to a truthy value to make this server the default backend. Please note that `mc-router.host` is still required to be set.
156+
- `mc-router.network`: Specify the network you are using for the router if multiple are present in the container/service. You can either use the network ID, it's full name or an alias.
158157

159158
#### Example Docker deployment
160159

cmd/mc-router/main.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ func showVersion() {
2424
type CliConfig struct {
2525
Version bool `usage:"Output version and exit"`
2626
Debug bool `usage:"Enable debug logs"`
27+
Trace bool `usage:"Enable trace logs"`
2728

2829
ServerConfig server.Config `flatten:"true"`
2930
}
@@ -40,7 +41,10 @@ func main() {
4041
os.Exit(0)
4142
}
4243

43-
if cliConfig.Debug {
44+
if cliConfig.Trace {
45+
logrus.SetLevel(logrus.TraceLevel)
46+
logrus.Trace("Trace logs enabled")
47+
} else if cliConfig.Debug {
4448
logrus.SetLevel(logrus.DebugLevel)
4549
logrus.Debug("Debug logs enabled")
4650
}

docs/create-dev-container.png

175 KB
Loading
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
services:
2+
router:
3+
image: itzg/mc-router
4+
environment:
5+
IN_DOCKER: true
6+
ports:
7+
- "25565:25565"
8+
volumes:
9+
- /var/run/docker.sock:/var/run/docker.sock:ro
10+
vanilla:
11+
image: itzg/minecraft-server
12+
environment:
13+
EULA: "TRUE"
14+
labels:
15+
mc-router.host: "vanilla.example.com"
16+
paper:
17+
image: itzg/minecraft-server
18+
environment:
19+
EULA: "TRUE"
20+
TYPE: PAPER
21+
labels:
22+
mc-router.host: "paper.example.com"
23+

server/docker.go

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ import (
1515
)
1616

1717
type IDockerWatcher interface {
18-
Start(socket string, timeoutSeconds int, refreshIntervalSeconds int, autoScaleUp bool, autoScaleDown bool) error
19-
Stop()
18+
Start(ctx context.Context, socket string, timeoutSeconds int, refreshIntervalSeconds int, autoScaleUp bool, autoScaleDown bool) error
2019
}
2120

2221
const (
@@ -34,7 +33,6 @@ type dockerWatcherImpl struct {
3433
autoScaleUp bool
3534
autoScaleDown bool
3635
client *client.Client
37-
contextCancel context.CancelFunc
3836
}
3937

4038
func (w *dockerWatcherImpl) makeWakerFunc(_ *routableContainer) ScalerFunc {
@@ -57,7 +55,7 @@ func (w *dockerWatcherImpl) makeSleeperFunc(_ *routableContainer) ScalerFunc {
5755
}
5856
}
5957

60-
func (w *dockerWatcherImpl) Start(socket string, timeoutSeconds int, refreshIntervalSeconds int, autoScaleUp bool, autoScaleDown bool) error {
58+
func (w *dockerWatcherImpl) Start(ctx context.Context, socket string, timeoutSeconds int, refreshIntervalSeconds int, autoScaleUp bool, autoScaleDown bool) error {
6159
var err error
6260

6361
w.autoScaleUp = autoScaleUp
@@ -83,9 +81,7 @@ func (w *dockerWatcherImpl) Start(socket string, timeoutSeconds int, refreshInte
8381
ticker := time.NewTicker(refreshInterval)
8482
containerMap := map[string]*routableContainer{}
8583

86-
var ctx context.Context
87-
ctx, w.contextCancel = context.WithCancel(context.Background())
88-
84+
logrus.Trace("Performing initial listing of Docker containers")
8985
initialContainers, err := w.listContainers(ctx)
9086
if err != nil {
9187
return err
@@ -104,6 +100,7 @@ func (w *dockerWatcherImpl) Start(socket string, timeoutSeconds int, refreshInte
104100
for {
105101
select {
106102
case <-ticker.C:
103+
logrus.Trace("Listing Docker containers")
107104
containers, err := w.listContainers(ctx)
108105
if err != nil {
109106
logrus.WithError(err).Error("Docker failed to list containers")
@@ -145,6 +142,7 @@ func (w *dockerWatcherImpl) Start(socket string, timeoutSeconds int, refreshInte
145142
}
146143

147144
case <-ctx.Done():
145+
logrus.Debug("Stopping Docker monitoring")
148146
ticker.Stop()
149147
return
150148
}
@@ -303,12 +301,6 @@ func (w *dockerWatcherImpl) parseContainerData(container *dockertypes.Container)
303301
return
304302
}
305303

306-
func (w *dockerWatcherImpl) Stop() {
307-
if w.contextCancel != nil {
308-
w.contextCancel()
309-
}
310-
}
311-
312304
type routableContainer struct {
313305
externalContainerName string
314306
containerEndpoint string

server/docker_swarm.go

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ type dockerSwarmWatcherImpl struct {
2626
autoScaleUp bool
2727
autoScaleDown bool
2828
client *client.Client
29-
contextCancel context.CancelFunc
3029
}
3130

3231
func (w *dockerSwarmWatcherImpl) makeWakerFunc(_ *routableService) ScalerFunc {
@@ -49,7 +48,7 @@ func (w *dockerSwarmWatcherImpl) makeSleeperFunc(_ *routableService) ScalerFunc
4948
}
5049
}
5150

52-
func (w *dockerSwarmWatcherImpl) Start(socket string, timeoutSeconds int, refreshIntervalSeconds int, autoScaleUp bool, autoScaleDown bool) error {
51+
func (w *dockerSwarmWatcherImpl) Start(ctx context.Context, socket string, timeoutSeconds int, refreshIntervalSeconds int, autoScaleUp bool, autoScaleDown bool) error {
5352
var err error
5453

5554
w.autoScaleUp = autoScaleUp
@@ -75,9 +74,7 @@ func (w *dockerSwarmWatcherImpl) Start(socket string, timeoutSeconds int, refres
7574
ticker := time.NewTicker(refreshInterval)
7675
serviceMap := map[string]*routableService{}
7776

78-
var ctx context.Context
79-
ctx, w.contextCancel = context.WithCancel(context.Background())
80-
77+
logrus.Trace("Performing initial listing of Docker containers")
8178
initialServices, err := w.listServices(ctx)
8279
if err != nil {
8380
return err
@@ -99,7 +96,7 @@ func (w *dockerSwarmWatcherImpl) Start(socket string, timeoutSeconds int, refres
9996
services, err := w.listServices(ctx)
10097
if err != nil {
10198
logrus.WithError(err).Error("Docker failed to list services")
102-
return
99+
continue
103100
}
104101

105102
visited := map[string]struct{}{}
@@ -332,9 +329,3 @@ func (w *dockerSwarmWatcherImpl) parseServiceData(service *swarm.Service, networ
332329
ok = true
333330
return
334331
}
335-
336-
func (w *dockerSwarmWatcherImpl) Stop() {
337-
if w.contextCancel != nil {
338-
w.contextCancel()
339-
}
340-
}

server/server.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,21 +142,17 @@ func NewServer(ctx context.Context, config *Config) (*Server, error) {
142142

143143
// TODO convert to RouteFinder
144144
if config.InDocker {
145-
err = DockerWatcher.Start(config.DockerSocket, config.DockerTimeout, config.DockerRefreshInterval, config.AutoScale.Up, config.AutoScale.Down)
145+
err = DockerWatcher.Start(ctx, config.DockerSocket, config.DockerTimeout, config.DockerRefreshInterval, config.AutoScale.Up, config.AutoScale.Down)
146146
if err != nil {
147147
return nil, fmt.Errorf("could not start docker integration: %w", err)
148-
} else {
149-
defer DockerWatcher.Stop()
150148
}
151149
}
152150

153151
// TODO convert to RouteFinder
154152
if config.InDockerSwarm {
155-
err = DockerSwarmWatcher.Start(config.DockerSocket, config.DockerTimeout, config.DockerRefreshInterval, config.AutoScale.Up, config.AutoScale.Down)
153+
err = DockerSwarmWatcher.Start(ctx, config.DockerSocket, config.DockerTimeout, config.DockerRefreshInterval, config.AutoScale.Up, config.AutoScale.Down)
156154
if err != nil {
157155
return nil, fmt.Errorf("could not start docker swarm integration: %w", err)
158-
} else {
159-
defer DockerSwarmWatcher.Stop()
160156
}
161157
}
162158

0 commit comments

Comments
 (0)