0

I built a reverse proxy to handle requests from my frontend and redirect them to backend microservices based on an appended string in the URL. It works when I run the app normally in vs code on localhost (the frontend microservice can send the request to the reverse proxy, which forwards it to the backend and returns the response to the frontend), but won't work when I build a docker image from it and run it. I'm really stumped. I'm inclined to think the problem lies with the Dockerfile but honestly I am not sure.

from flask import request
from flask import Response
from flask import Flask
from flask_cors import CORS
import requests
 
app = Flask(__name__)
CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
 
#App settings ---
SITE_NAME_1 = 'http://localhost:90/'
APP_NAME_1 = 'maxmin'
SITE_NAME_2 = 'http://localhost:100/'
APP_NAME_2 = 'sort'
 
@app.route('/',methods=['GET','POST'])
def proxy():
    input_text = request.args.get('input_text')
    global SITE_NAME_1
    global APP_NAME_1
    global SITE_NAME_2
    global APP_NAME_2
    SITE_NAME = ''
    APP_NAME = ''
 
    # Deciding between the apps..
    if input_text.split('-')[1] == 'maxmin':
        SITE_NAME = SITE_NAME_1
        APP_NAME = APP_NAME_1
    elif input_text.split('-')[1] == 'sort':
        SITE_NAME = SITE_NAME_2
        APP_NAME = APP_NAME_2
    input_text = input_text.split('-')[0]

  # sending request to backend and awaiting response
    if request.method=='GET':
        args = {'input_text': input_text}
        url = SITE_NAME
        resp = requests.get(url, params=args)
        # resp = requests.get(f'{SITE_NAME}{APP_NAME}', params=args)
        excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
        headers = [(name, value) for (name, value) in  resp.raw.headers.items() if name.lower() not in excluded_headers]
        response = Response(resp.content, resp.status_code, headers)
        return response
 
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000)
    # app.run(host="localhost",port=5000)

Dockerfile: (tried two different ones, hence why one half is commented out)

# FROM python:3.6.1-alpine
# WORKDIR /app
# ADD . /app
# RUN pip install --upgrade pip
# RUN pip install -r requirements.txt
# EXPOSE 5003
# ENTRYPOINT ["python3"]
# CMD ["src/proxy.py"]
 
FROM ubuntu:18.04
 
RUN apt-get update -y && apt-get install -y  python3-pip python3
 
COPY ./requirements.txt /app/requirements.txt
WORKDIR /app
RUN pip3 install -r requirements.txt
 
COPY ./src /app
 
EXPOSE 5000
 
ENTRYPOINT ["python3"]
CMD ["proxy.py"]

Error Log:

[2022-08-22 01:07:36,878] ERROR in app: Exception on / [GET]
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connection.py", line 137, in _new_conn
    (self.host, self.port), self.timeout, **extra_kw)
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/util/connection.py", line 91, in create_connection
    raise err
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/util/connection.py", line 81, in create_connection
    sock.connect(sa)
OSError: [Errno 99] Cannot assign requested address
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connectionpool.py", line 559, in urlopen
    body=body, headers=headers)
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connectionpool.py", line 353, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/lib/python3.6/http/client.py", line 1285, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.6/http/client.py", line 1331, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.6/http/client.py", line 1280, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.6/http/client.py", line 1046, in _send_output
    self.send(msg)
  File "/usr/lib/python3.6/http/client.py", line 984, in send
    self.connect()
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connection.py", line 162, in connect
    conn = self._new_conn()
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connection.py", line 146, in _new_conn
    self, "Failed to establish a new connection: %s" % e)
requests.packages.urllib3.exceptions.NewConnectionError: <requests.packages.urllib3.connection.HTTPConnection object at 0x7f6346cec128>: Failed to establish a new connection: [Errno 99] Cannot assign requested address
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/requests/adapters.py", line 376, in send
    timeout=timeout
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connectionpool.py", line 609, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/util/retry.py", line 273, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
requests.packages.urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=90): Max retries exceeded with url: /?input_text=DB%2C70newlinePG%2C90 (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x7f6346cec128>: Failed to establish a new connection: [Errno 99] Cannot assign requested address',))
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.6/dist-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/dist-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "proxy.py", line 41, in proxy
    resp = requests.get(url, params=args)
  File "/usr/local/lib/python3.6/dist-packages/requests/api.py", line 67, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/requests/api.py", line 53, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/requests/sessions.py", line 468, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.6/dist-packages/requests/sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/requests/adapters.py", line 437, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=90): Max retries exceeded with url: /?input_text=DB%2C70newlinePG%2C90 (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x7f6346cec128>: Failed to establish a new connection: [Errno 99] Cannot assign requested address',))
172.17.0.1 - - [22/Aug/2022 01:07:36] "GET /?input_text=DB,70newlinePG,90-maxmin HTTP/1.1" 500 -
[2022-08-22 01:07:36,878] ERROR in app: Exception on / [GET]
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connection.py", line 137, in _new_conn
    (self.host, self.port), self.timeout, **extra_kw)
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/util/connection.py", line 91, in create_connection
    raise err
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/util/connection.py", line 81, in create_connection
    sock.connect(sa)
OSError: [Errno 99] Cannot assign requested address
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connectionpool.py", line 559, in urlopen
    body=body, headers=headers)
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connectionpool.py", line 353, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/lib/python3.6/http/client.py", line 1285, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.6/http/client.py", line 1331, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.6/http/client.py", line 1280, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.6/http/client.py", line 1046, in _send_output
    self.send(msg)
  File "/usr/lib/python3.6/http/client.py", line 984, in send
    self.connect()
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connection.py", line 162, in connect
    conn = self._new_conn()
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connection.py", line 146, in _new_conn
    self, "Failed to establish a new connection: %s" % e)
requests.packages.urllib3.exceptions.NewConnectionError: <requests.packages.urllib3.connection.HTTPConnection object at 0x7f6346cec128>: Failed to establish a new connection: [Errno 99] Cannot assign requested address
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/requests/adapters.py", line 376, in send
    timeout=timeout
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/connectionpool.py", line 609, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "/usr/local/lib/python3.6/dist-packages/requests/packages/urllib3/util/retry.py", line 273, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
requests.packages.urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=90): Max retries exceeded with url: /?input_text=DB%2C70newlinePG%2C90 (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x7f6346cec128>: Failed to establish a new connection: [Errno 99] Cannot assign requested address',))
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.6/dist-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/dist-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "proxy.py", line 41, in proxy
    resp = requests.get(url, params=args)
  File "/usr/local/lib/python3.6/dist-packages/requests/api.py", line 67, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/requests/api.py", line 53, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/requests/sessions.py", line 468, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.6/dist-packages/requests/sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/requests/adapters.py", line 437, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=90): Max retries exceeded with url: /?input_text=DB%2C70newlinePG%2C90 (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x7f6346cec128>: Failed to establish a new connection: [Errno 99] Cannot assign requested address',))
172.17.0.1 - - [22/Aug/2022 01:07:36] "GET /?input_text=DB,70newlinePG,90-maxmin HTTP/1.1" 500 -

A little more contextual info. I am using port mapping from the host to the containers. The frontend was able to seamlessly send the requests directly to the backend(s) and receive the responses. It was also able to route the request through this proxy router (when it was running locally, uncontainerized) and receive the responses. The backend service in question sits on localhost 90 and maps to container port 80. The run commands I used are:

docker run -d --name=fronend-app -p 80:80 frontend-image
docker run -d --name=back-app-1 -p 90:80 backend-image-1
docker run -d --name=back-app-2 -p 100:80 backend-image-2
docker run -d --name=proxy-app -p 5000:5000 proxy-image

Does this shed any more light?

Sorry for the long post, wanted to get everything in. Grateful for any assistance.

AliasDan
  • 3
  • 3
  • Looks like you're attempting to send a http request to localhost:90, which isn't listening, resulting in a ConnectionError. If this works running locally, but not in docker, I'd guess that whatever your "backend" is is listening on your actual computer, but isn't available in your docker container. If you want to connect to something on your local machine from within your docker container, check out docker's host networking mode. – Danielle M. Aug 22 '22 at 01:30
  • what is in your run command. – whitespace Aug 22 '22 at 01:52
  • If your problem is as @DanielleM. suggests and the back-end services are outside containers, [From inside of a Docker container, how do I connect to the localhost of the machine?](https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach) discusses this situation more fully. (I would not recommend host networking, which generally disables Docker's network layer and doesn't work on Docker Desktop or VM-based setups.) – David Maze Aug 22 '22 at 09:52
  • Hi thanks for the responses guys, I added the commands and some contextual info above. Would this shed any light on the matter? – AliasDan Aug 22 '22 at 11:48

0 Answers0