Search code examples
dockerflaskconnection

Flask Docker - 2 Containers Communication - ConnectionError: HTTPConnectionPool: Max retries exceeded with url:


So... I'm testing the communication between 2 flask apps in 2 containers. The idea is to have a WebApp to send a GET request to a DataService app and show me the result. I'm running both services from independent containers.

I'm getting an error: "ConnectionError: HTTPConnectionPool: Max retries exceeded with url" when I access my WebApp Route.

See below the relevant code:

App 1: Data Service

from flask import Flask, json

app = Flask(__name__)

@app.route("/data")
def index():
    data = {"id": "testID", "value": "testValue"}
    return json.dumps(data)

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

App2: Web Service

from flask import Flask
import requests

app = Flask(__name__)

@app.route('/app')
def index():
    r = requests.get('http://0.0.0.0:5001/data')
    return r.text

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

I dont use docker-compose, so I'm building the 2 containers independently.

App1 and App2 Dockerfile are exactly the same:

FROM ubuntu:16.04
MAINTAINER me "my@email.com"
RUN apt-get update -y && \
    apt-get install -y python-pip python-dev
COPY ./requirements.txt /app/requirements.txt
WORKDIR /app
RUN pip install -r requirements.txt
COPY . /app
ENTRYPOINT ["python"]
CMD ["main.py"]

I run the containers and assign the WebService to port 5000 and DataService to port 5001.

sudo docker run -d -p 5000:5000 web
sudo docker run -d -p 5001:5000 data

If I go to my DataService route directly from my browser (http://0.0.0.0:5001/data) I get the expected result, but when I try to access it from the WebApp route (http://0.0.0.0:5000/app) I get the error below:

ConnectionError: HTTPConnectionPool(host='0.0.0.0', port=5001): Max retries exceeded with url: /data (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f20d55aeb90>: Failed to establish a new connection: [Errno 111] Connection refused',))

I tried using the container name in my request URL from the webapp service, but got the same error. Like this:

def index():
    r = requests.get('http://data_service_container_name:5001/data')
    return r.text

Any ideas?

Thanks in advance!


Solution

  • The way you started your two containers (docker run -d -p 5000:5000 ...) will attach both containers to the default bridge network.

    If you issue a docker network inspect bridge command, then you'll find the 2 containers under the containers section.

    On the default bridge network containers can see each other by container IP. Which means that if you put the container IP into your request URL, then your request should go through. You can get the container IP of the data container if you docker container inspect <container_name> the running container.

    A better option is to create your own user defined network. Just simply issue docker network create mynetwork and you will see a new network in docker network ls.

    On a user defined network containers can see each other by container name (and IP). So this time if you start your containers with a command like docker run -d -p 5000:5000 --network mynetwork ... then you can use the container name in the request URL.

    You can even define the container name with a command like docker run -d -p 5000:5000 --network mynetwork --name data_container ... for the data container.

    In order to make this more Docker like, I'd suggest to use Compose. In this case you don't need to define the container name, because containers started by compose can access each other by service name. Compose will create a custom bridge network automatically, but you can also define your own.