Home > Net >  Redis and flask app, web container does not want to start IndexError: pop from empty list
Redis and flask app, web container does not want to start IndexError: pop from empty list

Time:09-28

I am trying to solve a college assignment run an application written in flask redis. I have to use a docker for this. Using docker-compose up redis starts correctly however the flask application throws errors and I don't really know why.

Some code of the flask application If I understand this correctly, I need to declare environment variables in the Dockefile because it is from these that the application will get the ip address and port of Redis

app = Flask(__name__)
redis = redis.Redis(host=os.environ.get('REDIS_HOST'),
                    password=None,
                    port=os.environ.get('REDIS_PORT'),
                    db=0)

My Dockerfile

ARG PYTHON_VERSION=3.7-alpine

FROM python:${PYTHON_VERSION}

ENV REDIS_HOST 127.0.0.1 \
    REDIS_PORT 6379

COPY requirements.txt .

RUN pip install -r requirements.txt

COPY . .

CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "main:app"]

And docker-compose

version: "3"

services:
  web:
    build: .
    container_name: "python_app"
    ports:
      - "8000:8000"
    depends_on:
      - redis
  
  redis:
    image: "redis:alpine"
    container_name: "redis"
    ports: 
      - "6379:6379"

docker-compose build

Creating network "tt_default" with the default driver
Pulling redis (redis:alpine)...
alpine: Pulling from library/redis
Digest: sha256:fa785f9bd167b94a6b30210ae32422469f4b0f805f4df12733c2f177f500d1ba
Status: Downloaded newer image for redis:alpine
Building web
Sending build context to Docker daemon  10.75kB
Step 1/7 : ARG PYTHON_VERSION=3.7-alpine
Step 2/7 : FROM python:${PYTHON_VERSION}
 ---> a436fb2c575c
Step 3/7 : ENV REDIS_HOST 127.0.0.1     REDIS_PORT 6379
 ---> Running in ad3a17ce15e9
Removing intermediate container ad3a17ce15e9
 ---> 937330185f34
Step 4/7 : COPY requirements.txt .
 ---> d81cbb22f113
Step 5/7 : RUN pip install -r requirements.txt
 ---> Running in 1c0bac282a92
Collecting Flask==1.1.2
  Downloading Flask-1.1.2-py2.py3-none-any.whl (94 kB)
Collecting redis==3.4.1
  Downloading redis-3.4.1-py2.py3-none-any.whl (71 kB)
Collecting gunicorn<20,>=19
  Downloading gunicorn-19.10.0-py2.py3-none-any.whl (113 kB)
Collecting itsdangerous>=0.24
  Downloading itsdangerous-2.0.1-py3-none-any.whl (18 kB)
Collecting click>=5.1
  Downloading click-8.0.1-py3-none-any.whl (97 kB)
Collecting Jinja2>=2.10.1
  Downloading Jinja2-3.0.1-py3-none-any.whl (133 kB)
Collecting Werkzeug>=0.15
  Downloading Werkzeug-2.0.1-py3-none-any.whl (288 kB)
Collecting importlib-metadata
  Downloading importlib_metadata-4.8.1-py3-none-any.whl (17 kB)
Collecting MarkupSafe>=2.0
  Downloading MarkupSafe-2.0.1.tar.gz (18 kB)
Collecting typing-extensions>=3.6.4
  Downloading typing_extensions-3.10.0.2-py3-none-any.whl (26 kB)
Collecting zipp>=0.5
  Downloading zipp-3.5.0-py3-none-any.whl (5.7 kB)
Building wheels for collected packages: MarkupSafe
  Building wheel for MarkupSafe (setup.py): started
  Building wheel for MarkupSafe (setup.py): finished with status 'done'
  Created wheel for MarkupSafe: filename=MarkupSafe-2.0.1-py3-none-any.whl size=9761 sha256=43b5e0d8ef8bcbadc8e8d6845f85b770ad2b918760d7541b8c3f9c403ab04b14
  Stored in directory: /root/.cache/pip/wheels/1a/18/04/e3b5bd888f000c2716bccc94a565239f9defc47ef93d9e7bea
Successfully built MarkupSafe
Installing collected packages: zipp, typing-extensions, MarkupSafe, importlib-metadata, Werkzeug, Jinja2, itsdangerous, click, redis, gunicorn, Flask
Successfully installed Flask-1.1.2 Jinja2-3.0.1 MarkupSafe-2.0.1 Werkzeug-2.0.1 click-8.0.1 gunicorn-19.10.0 importlib-metadata-4.8.1 itsdangerous-2.0.1 redis-3.4.1 typing-extensions-3.10.0.2 zipp-3.5.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
Removing intermediate container 1c0bac282a92
 ---> 6dddf2a4ad27
Step 6/7 : COPY . .
 ---> 37bd8f541844
Step 7/7 : CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "main:app"]
 ---> Running in f19c3226fff2
Removing intermediate container f19c3226fff2
 ---> 861a5c53a545
Successfully built 861a5c53a545
Successfully tagged tt_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating redis ... done
Creating python_app ... done
Attaching to redis, python_app

Part of the logs which I get after using docker-compose up

 Attaching to redis, python_app
    redis    | 1:C 27 Sep 2021 14:36:16.063 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
    redis    | 1:C 27 Sep 2021 14:36:16.063 # Redis version=6.2.5, bits=64, commit=00000000, modified=0, pid=1, just started
    redis    | 1:C 27 Sep 2021 14:36:16.063 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
    redis    | 1:M 27 Sep 2021 14:36:16.064 * monotonic clock: POSIX clock_gettime
    redis    | 1:M 27 Sep 2021 14:36:16.065 * Running mode=standalone, port=6379.
    redis    | 1:M 27 Sep 2021 14:36:16.065 # Server initialized
    redis    | 1:M 27 Sep 2021 14:36:16.065 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
    redis    | 1:M 27 Sep 2021 14:36:16.065 * Ready to accept connections
    python_app | [2021-09-27 14:36:16  0000] [1] [INFO] Starting gunicorn 19.10.0
    python_app | [2021-09-27 14:36:16  0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
    python_app | [2021-09-27 14:36:16  0000] [1] [INFO] Using worker: sync
    python_app | [2021-09-27 14:36:16  0000] [8] [INFO] Booting worker with pid: 8
    python_app | [2021-09-27 14:36:16  0000] [9] [INFO] Booting worker with pid: 9
    python_app | [2021-09-27 14:36:16  0000] [8] [ERROR] Exception in worker process
    python_app | Traceback (most recent call last):
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 1179, in get_connection
    python_app |     connection = self._available_connections.pop()
    python_app | IndexError: pop from empty list
    python_app | 
    python_app | During handling of the above exception, another exception occurred:
    python_app | 
    python_app | Traceback (most recent call last):
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 586, in spawn_worker
    python_app |     worker.init_process()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/base.py", line 135, in init_process
    python_app |     self.load_wsgi()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi
    python_app |     self.wsgi = self.app.wsgi()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
    python_app |     self.callable = self.load()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 52, in load
    python_app |     return self.load_wsgiapp()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp
    python_app |     return util.import_app(self.app_uri)
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/util.py", line 350, in import_app
    python_app |     __import__(module)
    python_app |   File "/main.py", line 21, in <module>
    python_app |     redis.set('sessionvisitors', 0)
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/client.py", line 1766, in set
    python_app |     return self.execute_command('SET', *pieces)
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/client.py", line 875, in execute_command
    python_app |     conn = self.connection or pool.get_connection(command_name, **options)
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 1181, in get_connection
    python_app |     connection = self.make_connection()
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 1220, in make_connection
    python_app |     return self.connection_class(**self.connection_kwargs)
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 502, in __init__
    python_app |     self.port = int(port)
    python_app | TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
    python_app | [2021-09-27 14:36:16  0000] [8] [INFO] Worker exiting (pid: 8)
    python_app | [2021-09-27 14:36:16  0000] [10] [INFO] Booting worker with pid: 10
    python_app | [2021-09-27 14:36:16  0000] [9] [ERROR] Exception in worker process
    python_app | Traceback (most recent call last):
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 1179, in get_connection
    python_app |     connection = self._available_connections.pop()
    python_app | IndexError: pop from empty list
    python_app | 
    python_app | During handling of the above exception, another exception occurred:
    python_app | 
    python_app | Traceback (most recent call last):
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 586, in spawn_worker
    python_app |     worker.init_process()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/base.py", line 135, in init_process
    python_app |     self.load_wsgi()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi
    python_app |     self.wsgi = self.app.wsgi()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
    python_app |     self.callable = self.load()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 52, in load
    python_app |     return self.load_wsgiapp()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp
    python_app |     return util.import_app(self.app_uri)
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/util.py", line 350, in import_app
    python_app |     __import__(module)
    python_app |   File "/main.py", line 21, in <module>
    python_app |     redis.set('sessionvisitors', 0)
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/client.py", line 1766, in set
    python_app |     return self.execute_command('SET', *pieces)
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/client.py", line 875, in execute_command
    python_app |     conn = self.connection or pool.get_connection(command_name, **options)
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 1181, in get_connection
    python_app |     connection = self.make_connection()
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 1220, in make_connection
    python_app |     return self.connection_class(**self.connection_kwargs)
    python_app |   File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 502, in __init__
    python_app |     self.port = int(port)
    python_app | TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
    python_app | [2021-09-27 14:36:16  0000] [9] [INFO] Worker exiting (pid: 9)
    python_app | Traceback (most recent call last):
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 203, in run
    python_app |     self.manage_workers()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 548, in manage_workers
    python_app |     self.spawn_workers()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 620, in spawn_workers
    python_app |     time.sleep(0.1 * random.random())
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 245, in handle_chld
    python_app |     self.reap_workers()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 528, in reap_workers
    python_app |     raise HaltServer(reason, self.WORKER_BOOT_ERROR)
    python_app | gunicorn.errors.HaltServer: <HaltServer 'Worker failed to boot.' 3>
    python_app | 
    python_app | During handling of the above exception, another exception occurred:
    python_app | 
    python_app | Traceback (most recent call last):
    python_app |   File "/usr/local/bin/gunicorn", line 8, in <module>
    python_app |     sys.exit(run())
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 61, in run
    python_app |     WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/app/base.py", line 223, in run
    python_app |     super(Application, self).run()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/app/base.py", line 72, in run
    python_app |     Arbiter(self).run()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 232, in run
    python_app |     self.halt(reason=inst.reason, exit_status=inst.exit_status)
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 345, in halt
    python_app |     self.stop()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 396, in stop
    python_app |     time.sleep(0.1)
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 245, in handle_chld
    python_app |     self.reap_workers()
    python_app |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 528, in reap_workers
    python_app |     raise HaltServer(reason, self.WORKER_BOOT_ERROR)
    python_app | gunicorn.errors.HaltServer: <HaltServer 'Worker failed to boot.' 3>

CodePudding user response:

The app error you're seeing is because the Redis connection is failing to open, if you look at the stack trace closely. The reason for the failed connection is that REDIS_HOST is set incorrectly to 127.0.0.1 inside your Dockerfile. To fix this, the values for REDIS_HOST and REDIS_PORT should actually be passed into your app container by docker-compose, since that's the layer that actually knows where Redis lives. Your Dockerfile is just for your app container, which depends on Redis but doesn't have a clue where it might be running.

Since compose makes services available at hostnames equal to the service name by default, Redis should be reachable at just tcp://redis:6379, so I would give these values a shot to start with:

  web:
    build: .
    container_name: "python_app"
    ports:
      - "8000:8000"
    depends_on:
      - redis
    environment:
      REDIS_HOST: redis
      REDIS_PORT: 6379
  • Related