Reputation: 507
I have the following python code, where I have written a simple HTTP server by extending HTTPBaseServer:
class ApiError(Exception):
def __init__(self, code, msg=None, desc=None):
self.code = code
self.msg = msg
self.desc = desc
def __str__(self):
return f"ApiError({self.code}, {self.msg})"
def ApiRoute(path):
def outer(func):
if not hasattr(func, "_routes"):
setattr(func, "_routes", [])
func._routes += [path]
return func
return outer
class ApiServer(HTTPServer):
def __init__(self, addr, port):
server_address = (addr, port)
self.__addr = addr
class handler_class(ApiHandler):
pass
self.handler_class = handler_class
# routed methods map into handler
for meth in type(self).__dict__.values():
if hasattr(meth, "_routes"):
for route in meth._routes:
self.add_route(route, meth)
super().__init__(server_address, handler_class)
def add_route(self, path, meth):
self.handler_class._routes[path] = meth
def port(self):
"Get my port"
sa = self.socket.getsockname()
return sa[1]
def address(self):
"Get my ip address"
sa = self.socket.getsockname()
return sa[0]
def uri(self, path):
"Make a URI pointing at myself"
if path[0] == "/":
path = path[1:]
return "http://"+self.__addr + ":"+ str(self.port()) + "/" + path
def shutdown(self):
super().shutdown()
self.socket.close()
class ApiHandler(BaseHTTPRequestHandler):
_routes={}
def do_GET(self):
self.do_XXX()
def do_XXX(self, info={}):
url=urlparse.urlparse(self.path)
handler = self._routes.get(url.path)
if handler:
response=handler(info)
self.send_response(200)
response = json.dumps(response)
response = bytes(str(response),"utf-8")
self.send_header("Content-Length", len(response))
self.end_headers()
self.wfile.write(response)
class MyServer(ApiServer):
@ApiRoute("/popup")
def popup(req):
return "HERE"
httpd = MyServer('127.0.0.1', 5000)
print("serving on ", httpd.address(), httpd.port())
threading.Thread(target=httpd.serve_forever).start()
The above works perfectly when I do,
python serv.py
on the terminal.
However, I want to run this in a docker container. The Dockerfile looks like this:
FROM python:3.6-alpine3.7
COPY . /serv
WORKDIR /serv
ENTRYPOINT ["python"]
CMD ["serv.py"]
Then I build the Docker Image using:
docker build . -t custom-serv
And run it as container using:
docker run --rm -p 5000:5000 custom-serv
I do get the log message indicating successful start of server, however the curl on the url returns the following:
curl: (56) Recv failure: Connection reset by peer
I realise that, there are many frameworks available to make life simpler, however this is more of an experiment I was doing and it'll be great if someone could point me in the right direction!
Upvotes: 1
Views: 1257
Reputation: 14210
Your server listens on localhost and does not respond to any other connections, but from localhost. If you were to connect to your server from within the container, it would have worked. But to connect from the outside, you need to designate for your server to listen for all connections from all available places.
Therefore, you need to change
httpd = MyServer('127.0.0.1', 5000)
to
httpd = MyServer('0.0.0.0', 5000)
Upvotes: 1
Reputation: 22561
Change that line:
httpd = MyServer('127.0.0.1', 5000)
to:
httpd = MyServer('0.0.0.0', 5000)
About difference: https://www.howtogeek.com/225487/what-is-the-difference-between-127.0.0.1-and-0.0.0.0/
Upvotes: 4