'Can't connect to Go Server in Docker container
I am trying to run a an HTTP Server written in Golang inside of a docker container and I keep getting connection refused. Everything is being run inside of an Ubuntu 20.04 Server VM running on my Windows 10 machine.
The Go server code:
package main
import "github.com/lkelly93/scheduler/internal/server"
func main() {
server := server.NewHTTPServer()
server.Start(3000)
}
package server
import (
"context"
"fmt"
"net/http"
)
type HTTPServer interface {
Start(port int) error
Stop() error
}
func NewHTTPServer() HTTPServer {
return &httpServer{}
}
type httpServer struct {
server *http.Server
}
func (server *httpServer) Start(port int) error {
serveMux := newServeMux()
server.server = &http.Server {
Addr: fmt.Sprintf(":%d", port),
Handler: serveMux,
}
return server.server.ListenAndServe()
}
func (server *httpServer) Stop() error {
return server.server.Shutdown(context.Background())
}
My Dockerfile:
FROM ubuntu:20.04
RUN apt-get update -y
#Install needed packages
RUN apt-get install software-properties-common -y
RUN apt-get install python3 -y
RUN apt-get update -y
RUN apt-get install python3-pip -y
RUN apt-get install default-jre -y
#Install language dependacies
#Python
RUN pip3 install numpy
#Reduce VM size
# RUN rm -rf /var/lib/apt/lists/*
#Setup working DIRs
RUN mkdir secure
RUN mkdir secure/runner_files
COPY scheduler /secure
WORKDIR /secure
EXPOSE 3000
CMD ["./scheduler"] <-- The go server is compiled into a binary called scheduler
I build the given Dockerfile and then run:
docker run -d --name scheduler -p 3000:3000 scheduler:latest
Then I grab the container's address with:
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' scheduler
->172.17.0.2
Finally I use cURL to send an http request:
curl http://172.17.0.2:3000/execute/python --data '{"Code":"print(\"Hello\")"}'
I am getting
curl: (7) Failed to connect to 172.17.0.2 port 3000: Connection refused
but should be getting
{"Stdout":"Hello\n"}%
If I run the Go server on the Ubuntu VM I have no issues calling it from my Win10 machine but I can't seem to call the Go server when it exists inside of a docker container from the Ubuntu machine.
The Go code is more complicated then just that but it's too much to post everything here, feel free to look at the whole repo at https://github.com/lkelly93/scheduler.
Eventually it will be the backend to a website I want to make that runs code. Something like LeetCode or Repl.it.
Thanks!
Edit:
docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a56a973040f scheduler:latest "./scheduler" 37 seconds ago Up 36 seconds 0.0.0.0:3000->3000/tcp scheduler
docker container logs 2a56a973040f gave no output.
Edit 2:
docker run -it --net container:2a56a973040f nicolaka/netshoot ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 4096 *:3000 *:*
Edit 3:
After reading through the man pages I found that if I had the tag --network=host to my image and then run.
curl http://localhost:3000/execute/python --data '{"Code":"print(\"Hello\")"}'
I get the correct output. While this works, I would like to have multiple docker images running side by side. So I would prefer to use IP address to address them all. So I don't think this is a permanent fix.
Solution 1:[1]
After doing more googling I followed this guide and created my own "user-defined bridge network".
If I launch my container and attach it to this network then it works! I would love it if someone could explain why though!
Solution 2:[2]
You've published the port, which forwards the port from the docker host to the container. Therefore you want to connect to http://localhost:3000. Connecting to container IP may fail with desktop installs since docker runs inside of a VM and those private IP's are only visible in the VM.
If you happen to be running docker-machine
(this is the case with older docker toolbox installs), then you'll need to get the IP of the VM. Run echo $DOCKER_HOST
to see the IP address and adjust the port to port 3000.
Solution 3:[3]
To fix this on my server I set the IP address to 0.0.0.0:4000. I'm using gin so the example would look lik:
r := gin.Default()
r.run("0.0.0.0:4000")
After this I was finally able to access it through my browser.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Luke Kelly |
Solution 2 | BMitch |
Solution 3 | Tj Gienger |