diff --git a/README.md b/README.md index ad0fb27..2e949d2 100644 --- a/README.md +++ b/README.md @@ -71,18 +71,39 @@ The [multi-architecture image published at Docker Hub](https://hub.docker.com/re ## Docker Compose Usage -The following diagram shows how [the example docker-compose.yml](docs/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._ +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._ -The `router` service is only one of the services that needs to exposed on the external -network. The `--mapping` declares how the hostname users will enter into their Minecraft client -will map to the internal services. +```yaml +version: "3.8" + +services: + vanilla: + image: itzg/minecraft-server + environment: + EULA: "TRUE" + forge: + image: itzg/minecraft-server + environment: + EULA: "TRUE" + TYPE: FORGE + router: + image: ${MC_ROUTER_IMAGE:-itzg/mc-router} + depends_on: + - forge + - vanilla + environment: + MAPPING: | + vanilla.example.com=vanilla:25565 + forge.example.com=forge:25565 + ports: + - "25565:25565" +``` + +The `router` service is only one of the services that needs to exposed on the external network. The `MAPPING` declares how the hostname users will enter into their Minecraft client will map to the internal services. ![](docs/compose-diagram.png) -To test out this example, I added these two entries to my "hosts" file: +To test out this example, add these two entries to my "hosts" file: ``` 127.0.0.1 vanilla.example.com diff --git a/cmd/mc-router/main.go b/cmd/mc-router/main.go index fbda6ef..8591381 100644 --- a/cmd/mc-router/main.go +++ b/cmd/mc-router/main.go @@ -8,7 +8,6 @@ import ( "os/signal" "runtime/pprof" "strconv" - "strings" "syscall" "time" @@ -30,22 +29,22 @@ type MetricsBackendConfig struct { } type Config struct { - Port int `default:"25565" usage:"The [port] bound to listen for Minecraft client connections"` - Default string `usage:"host:port of a default Minecraft server to use when mapping not found"` - Mapping []string `usage:"Comma-separated or repeated mappings of externalHostname=host:port"` - ApiBinding string `usage:"The [host:port] bound for servicing API requests"` - Version bool `usage:"Output version and exit"` - CpuProfile string `usage:"Enables CPU profiling and writes to given path"` - Debug bool `usage:"Enable debug logs"` - ConnectionRateLimit int `default:"1" usage:"Max number of connections to allow per second"` - InKubeCluster bool `usage:"Use in-cluster Kubernetes config"` - KubeConfig string `usage:"The path to a Kubernetes configuration file"` - AutoScaleUp bool `usage:"Increase Kubernetes StatefulSet Replicas (only) from 0 to 1 on respective backend servers when accessed"` - InDockerSwarm bool `usage:"Use in-swarm Docker config"` - DockerTimeout int `default:"0" usage:"Timeout configuration in seconds for the Docker Swarm integration"` - DockerRefreshInterval int `default:"15" usage:"Refresh interval in seconds for the Docker Swarm integration"` - MetricsBackend string `default:"discard" usage:"Backend to use for metrics exposure/publishing: discard,expvar,influxdb"` - UseProxyProtocol bool `default:"false" usage:"Send PROXY protocol to backend servers"` + Port int `default:"25565" usage:"The [port] bound to listen for Minecraft client connections"` + Default string `usage:"host:port of a default Minecraft server to use when mapping not found"` + Mapping map[string]string `usage:"Comma or newline delimited or repeated mappings of externalHostname=host:port"` + ApiBinding string `usage:"The [host:port] bound for servicing API requests"` + Version bool `usage:"Output version and exit"` + CpuProfile string `usage:"Enables CPU profiling and writes to given path"` + Debug bool `usage:"Enable debug logs"` + ConnectionRateLimit int `default:"1" usage:"Max number of connections to allow per second"` + InKubeCluster bool `usage:"Use in-cluster Kubernetes config"` + KubeConfig string `usage:"The path to a Kubernetes configuration file"` + AutoScaleUp bool `usage:"Increase Kubernetes StatefulSet Replicas (only) from 0 to 1 on respective backend servers when accessed"` + InDockerSwarm bool `usage:"Use in-swarm Docker config"` + DockerTimeout int `default:"0" usage:"Timeout configuration in seconds for the Docker Swarm integration"` + DockerRefreshInterval int `default:"15" usage:"Refresh interval in seconds for the Docker Swarm integration"` + MetricsBackend string `default:"discard" usage:"Backend to use for metrics exposure/publishing: discard,expvar,influxdb"` + UseProxyProtocol bool `default:"false" usage:"Send PROXY protocol to backend servers"` MetricsBackendConfig MetricsBackendConfig RoutesConfig string `usage:"Name or full path to routes config file"` NgrokToken string `usage:"If set, an ngrok tunnel will be established. It is HIGHLY recommended to pass as an environment variable."` @@ -110,7 +109,7 @@ func main() { } } - server.Routes.RegisterAll(parseMappings(config.Mapping)) + server.Routes.RegisterAll(config.Mapping) if config.Default != "" { server.Routes.SetDefaultRoute(config.Default) } @@ -173,17 +172,3 @@ func main() { connector.WaitForConnections() logrus.Info("Stopped") } - -func parseMappings(vals []string) map[string]string { - result := make(map[string]string) - for _, part := range vals { - keyValue := strings.Split(part, "=") - if len(keyValue) == 2 { - result[keyValue[0]] = keyValue[1] - } else { - logrus.WithField("part", part).Fatal("Invalid part of mapping") - } - } - - return result -} diff --git a/docs/docker-compose.yml b/docs/docker-compose.yml index 08bde9b..884542f 100644 --- a/docs/docker-compose.yml +++ b/docs/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.4' +version: "3.8" services: vanilla: @@ -18,9 +18,12 @@ services: environment: # enable API API_BINDING: ":25564" + DEBUG: true + MAPPING: | + vanilla.example.com=vanilla:25565 + forge.example.com=forge:25565 ports: - - 25565:25565 + - "25565:25565" # bind the API port to only loopback to avoid external exposure - - 127.0.0.1:25564:25564 - command: --mapping=vanilla.example.com=vanilla:25565,forge.example.com=forge:25565 + - "127.0.0.1:25564:25564" diff --git a/go.mod b/go.mod index 41f0512..27028f2 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/go-kit/kit v0.13.0 github.com/gorilla/mux v1.8.0 github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c - github.com/itzg/go-flagsfiller v1.12.0 + github.com/itzg/go-flagsfiller v1.13.1 github.com/juju/ratelimit v1.0.2 github.com/pires/go-proxyproto v0.7.0 github.com/pkg/errors v0.9.1 @@ -59,7 +59,7 @@ require ( github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/iancoleman/strcase v0.2.0 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect github.com/imdario/mergo v0.3.7 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect diff --git a/go.sum b/go.sum index 68a4f77..dcf4084 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/log15 v3.0.0-testing.3+incompatible h1:zaX5fYT98jX5j4UhO/WbfY8T1HkgVrydiDMC9PWqGCo= @@ -69,8 +69,8 @@ github.com/inconshreveable/log15/v3 v3.0.0-testing.5 h1:h4e0f3kjgg+RJBlKOabrohjH github.com/inconshreveable/log15/v3 v3.0.0-testing.5/go.mod h1:3GQg1SVrLoWGfRv/kAZMsdyU5cp8eFc1P3cw+Wwku94= github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/itzg/go-flagsfiller v1.12.0 h1:LSwSUGxzZqueprm0D8FBCAG0JMgwAkkh2UjtwreNgAg= -github.com/itzg/go-flagsfiller v1.12.0/go.mod h1:47WeO9fl+QyS48AdRHfarhF3rKBh0enbe90tTko03gg= +github.com/itzg/go-flagsfiller v1.13.1 h1:MpFWtK12dkz8JwBD3oABoXuxnJ9kdOtXFlW4bC1EpO0= +github.com/itzg/go-flagsfiller v1.13.1/go.mod h1:vSclFjMCgjtH6SB0tCkVyX/OwO/aaInbKmX6H8iJ54Y= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=