lunemec/nanny

config.Addr does not work properly in a containerized Nanny instance

Closed this issue · 4 comments

The configuration of the environment variable NANNY_ADDR=0.0.0.0:8080 does not seem to work properly when Nanny is running inside a container:

$ podman run -d -e "LOGXI=*" -e "NANNY_ADDR=0.0.0.0:8080" -p "8080:8080" --pull never docker.io/library/nanny:0.4.2
dcac117170426a83abfcea4d498e5f24dead81b2637a7e4f49704d4ba83cf413
$ podman ps -a
CONTAINER ID  IMAGE                          COMMAND     CREATED             STATUS                         PORTS                   NAMES
dcac11717042  docker.io/library/nanny:0.4.2  /opt/nanny  5 seconds ago       Exited (2) 5 seconds ago       0.0.0.0:8080->8080/tcp  laughing_brattain
$ podman logs -f laughing_brattain
{"_t":"2021-02-15T20:59:08+0000", "_p":"1", "_l":"WRN", "_n":"~", "_m":"Config not found, using default stderr notifier."}
{"_t":"2021-02-15T20:59:08+0000", "_p":"1", "_l":"INF", "_n":"~", "_m":"Nanny listening", "addr":""}
{"_t":"2021-02-15T20:59:08+0000", "_p":"1", "_l":"FTL", "_n":"~", "_m":"Unable to start API server", "err":"listen tcp :80: bind: permission denied", "_c":["nanny/cmd.runAPI() /go/src/nanny/cmd/root.go:189","nanny/cmd.run() /go/src/nanny/cmd/root.go:111","github.com/spf13/cobra.(*Command).execute() /go/src/nanny/vendor/github.com/spf13/cobra/command.go:766","github.com/spf13/cobra.(*Command).ExecuteC() /go/src/nanny/vendor/github.com/spf13/cobra/command.go:852","github.com/spf13/cobra.(*Command).Execute() /go/src/nanny/vendor/github.com/spf13/cobra/command.go:800","nanny/cmd.Execute() /go/src/nanny/cmd/root.go:273","main.main() /go/src/nanny/main.go:6","runtime.main() /usr/local/go/src/runtime/proc.go:204","runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:1374"]}
panic: listen tcp :80: bind: permission denied

goroutine 1 [running]:
github.com/mgutz/logxi.(*DefaultLogger).Fatal(0xc000091640, 0xc4281d, 0x1a, 0xc000365080, 0x2, 0x2)
        /go/src/nanny/vendor/github.com/mgutz/logxi/defaultLogger.go:133 +0xf4
github.com/mgutz/logxi.Fatal(...)
        /go/src/nanny/vendor/github.com/mgutz/logxi/methods.go:30
nanny/cmd.runAPI()
        /go/src/nanny/cmd/root.go:189 +0x6b3
nanny/cmd.run(0x10aa940, 0x11301b0, 0x0, 0x0)
        /go/src/nanny/cmd/root.go:111 +0x2c
github.com/spf13/cobra.(*Command).execute(0x10aa940, 0xc0000a0200, 0x0, 0x0, 0x10aa940, 0xc0000a0200)
        /go/src/nanny/vendor/github.com/spf13/cobra/command.go:766 +0x2c2
github.com/spf13/cobra.(*Command).ExecuteC(0x10aa940, 0x44710a, 0x10b6420, 0xc000000180)
        /go/src/nanny/vendor/github.com/spf13/cobra/command.go:852 +0x2fe
github.com/spf13/cobra.(*Command).Execute(...)
        /go/src/nanny/vendor/github.com/spf13/cobra/command.go:800
nanny/cmd.Execute()
        /go/src/nanny/cmd/root.go:273 +0x31
main.main()
        /go/src/nanny/main.go:6 +0x25

Root-less Podman then fails since the container is started with a port < 1024. Nevertheless, it works just fine when Nanny is started directly on the dev notebook:

NANNY_ADDR=0.0.0.0:8080 make run             # Works

Inside a containerized Nanny instance, it automatically takes :80 which is the default from the Server struct:

	// Addr optionally specifies the TCP address for the server to listen on,
	// in the form "host:port". If empty, ":http" (port 80) is used.
	// The service names are defined in RFC 6335 and assigned by IANA.
	// See net.Dial for details of the address format.

When I manually set Addr to "0.0.0.0:8080" it works just fine (https://github.com/lunemec/nanny/blob/master/cmd/root.go#L169).

Needs further troubleshooting...

It looks like nanny does not care about environment variables:

$ podman run -it -e NANNY_ADDR=0.0.0.0:8080 -p 8080:8080 --pull never docker.io/library/nanny:0.4.2 /bin/sh
/opt $ printenv
HOSTNAME=5fa45984edf0
SHLVL=1
HOME=/home/nanny
container=podman
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NANNY_ADDR=0.0.0.0:8080
PWD=/opt
/opt $ ./nanny
22:37:29.954595 WRN ~ Config not found, using default stderr notifier.
   in cmd.initConfig() ../go/src/nanny/cmd/root.go:311
22:37:29.957488 FTL ~ Unable to start API server
   err: listen tcp :80: bind: permission denied
   in cmd.runAPI() ../go/src/nanny/cmd/root.go:187
   in cmd.run() ../go/src/nanny/cmd/root.go:111
   in cobra.(*Command).execute() ../go/src/nanny/vendor/github.com/spf13/cobra/command.go:766
   in cobra.(*Command).ExecuteC() ../go/src/nanny/vendor/github.com/spf13/cobra/command.go:852
   in cobra.(*Command).Execute() ../go/src/nanny/vendor/github.com/spf13/cobra/command.go:800
   in cmd.Execute() ../go/src/nanny/cmd/root.go:271
   in main.main() ../go/src/nanny/main.go:6
panic: listen tcp :80: bind: permission denied

goroutine 1 [running]:
github.com/mgutz/logxi.(*DefaultLogger).Fatal(0xc0000c3600, 0xc4180b, 0x1a, 0xc0003651a0, 0x2, 0x2)
        /go/src/nanny/vendor/github.com/mgutz/logxi/defaultLogger.go:133 +0xf4
github.com/mgutz/logxi.Fatal(...)
        /go/src/nanny/vendor/github.com/mgutz/logxi/methods.go:30
nanny/cmd.runAPI()
        /go/src/nanny/cmd/root.go:187 +0x5f3
nanny/cmd.run(0x10a9940, 0x112f1b0, 0x0, 0x0)
        /go/src/nanny/cmd/root.go:111 +0x2c
github.com/spf13/cobra.(*Command).execute(0x10a9940, 0xc000098200, 0x0, 0x0, 0x10a9940, 0xc000098200)
        /go/src/nanny/vendor/github.com/spf13/cobra/command.go:766 +0x2c2
github.com/spf13/cobra.(*Command).ExecuteC(0x10a9940, 0x44710a, 0x10b5420, 0xc000000180)
        /go/src/nanny/vendor/github.com/spf13/cobra/command.go:852 +0x2fe
github.com/spf13/cobra.(*Command).Execute(...)
        /go/src/nanny/vendor/github.com/spf13/cobra/command.go:800
nanny/cmd.Execute()
        /go/src/nanny/cmd/root.go:271 +0x31
main.main()
        /go/src/nanny/main.go:6 +0x25

Relevant code snippet:

nanny/cmd/root.go

Lines 300 to 301 in de0ff48

viper.SetEnvPrefix("nanny") // prefix ENV variables with NANNY_
viper.AutomaticEnv() // read in environment variables that match

This is a blocker for #30

@PhilipSchmid I see you fixed the issue by adding the missing configfile inside the container. It is strange the ENV does not work without the file, but I guess that is how cobra works.
I tried without the config file:

 λ NANNY_ADDR="localhost:9090" make run
LOGXI=* go run -race main.go
09:53:35.434048 WRN ~ Config not found, using default stderr notifier.  <<-- at least it prints this
   in cmd.initConfig() cmd/root.go:311
09:53:35.439358 INF ~ Nanny listening addr:

And with:

λ NANNY_ADDR="localhost:9090" make run
LOGXI=* go run -race main.go
09:51:01.420243 INF ~ Using config file
   path: /Users/lulu/Documents/git/Go/src/nanny/nanny.toml
09:51:01.489810 INF ~ Nanny listening addr: localhost:9090
^C09:51:02.937315 INF ~ Nanny shutting down.
make: *** [run] Error 1

Please create PR from your fix and we can merge it.