Search code examples
dockerrediscontainers

How do I connect to redis in a container from a flask app?


I have a Flask application running on my Ubuntu desktop (as the first phase of a more detailed development). I have Redis running in a container (official redis docker image), which I created as below:

docker run --name redis --network host -d redis

Now when I run Python on my desktop in a terminal, import redis, and run the usual commands, I am able to connect perfectly well to Redis and do what is required.

import redis
r=redis.Redis(host="128.224.2.97",port=6397)
r.hgetall('1')

However, when I do the same from within my Flask app, with exactly the same commands, I get a connection error as below:

Traceback (most recent call last):
  File "/home/ssharma3/.local/share/virtualenvs/cos-dir-QPdremXL/lib/python3.8/site-packages/redis/connection.py", line 276, in connect
    sock = self.retry.call_with_retry(
  File "/home/ssharma3/.local/share/virtualenvs/cos-dir-QPdremXL/lib/python3.8/site-packages/redis/retry.py", line 46, in call_with_retry
    return do()
  File "/home/ssharma3/.local/share/virtualenvs/cos-dir-QPdremXL/lib/python3.8/site-packages/redis/connection.py", line 277, in <lambda>
    lambda: self._connect(), lambda error: self.disconnect(error)
  File "/home/ssharma3/.local/share/virtualenvs/cos-dir-QPdremXL/lib/python3.8/site-packages/redis/connection.py", line 639, in _connect
    raise err
  File "/home/ssharma3/.local/share/virtualenvs/cos-dir-QPdremXL/lib/python3.8/site-packages/redis/connection.py", line 627, in _connect
    sock.connect(socket_address)
ConnectionRefusedError: [Errno 111] Connection refused

What is the right way to handle this?

Connection should have succeeded.


Solution

  • I'd suggest using a Docker Compose stack rather than host networking.

    I don't know what your Flask app looks like, so I created a minimal app.py (see below) which includes the connection to Redis.

    🗎 docker-compose.yml

    version: '3.1'
    services:
      redis:
        image: redis:latest
        restart: always
        container_name: redis
        ports:
         - '6379:6379'
    
      flask:
        container_name: flask
        build:
          context: .
        depends_on:
          - redis
    

    🗎 Dockerfile

    FROM python:3.11.4
    
    COPY requirements.txt .
    
    RUN pip3 install -r requirements.txt
    
    COPY app.py .
    
    CMD python3 app.py
    

    🗎 requirements.txt (Change versions as required and add whatever other Python packages are required.)

    redis==5.0.3
    Flask==3.0.2
    

    🗎 app.py (A simple Flask app. As mentioned in the question this makes a connection to Redis and runs a couple of commands. Look carefully at screenshot below to check that these commands run successfully. The benefit of using Docker Compose is that when you connect to the Redis service you simply use the service name, redis, and don't need to worry about an explicit IP address.)

    from flask import Flask
    import redis
    
    r = redis.Redis(host='redis', port=6379, db=0, decode_responses=True)
    
    print("🚨 Check for connection to Redis:")
    print(r.hgetall("1"))
    r.set('test', '123')
    print(r.get('test'))
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        return 'Hello, World!'
    
    if __name__ == '__main__':
        app.run(debug=False)
    

    enter image description here