Aaron
Aaron

Reputation: 81

cannot connect to redis container from app container

I follow the django channels tutorial to build a simple chat app. https://channels.readthedocs.io/en/latest/tutorial/part_1.html , it can work on my local machine with redis without docker.

then now i want to put it into docker containers by docker compose file, but seems app cannot connect to redis container, i already try and google for two days, but seems all methods cannot work.

so want to ask for help here

folder structure

my_project
  - mysite(django app)
     - ... somefolder and files
  - docker-compose.yml
  - Dockfile
  - requirements.txt

docker-compose.yml

version: '3'

services:
  app:
    build:
      # current directory
      context: .
    ports:
      #host to image
      - "8000:8000"
    volumes:
      # map directory to image, which means if something changed in
      # current directory, it will automatically reflect on image,
      # don't need to restart docker to get the changes into effect
      - ./mysite:/mysiteRoot/mysite
    command: >
      sh -c "
             python3 manage.py makemigrations &&
             python3 manage.py migrate &&
             python3 manage.py runserver 0.0.0.0:8000"

    depends_on:
      - redis

  redis:
    image: redis:5.0.5-alpine
    ports:
      #host to image
      - "6379:6379"

Dockfile

FROM python:3.7-alpine
MAINTAINER Aaron Wei.

ENV PYTHONUNBUFFERED 1

EXPOSE 8000

# Setup directory structure
RUN mkdir /mysiteRoot
WORKDIR /mysiteRoot/mysite/

# Install dependencies
COPY ./requirements.txt /mysiteRoot/requirements.txt
RUN apk add --update --no-cache postgresql-client
RUN apk add --update --no-cache --virtual .tmp-build-deps \
      gcc libc-dev linux-headers postgresql-dev
RUN apk add build-base python-dev py-pip jpeg-dev zlib-dev
ENV LIBRARY_PATH=/lib:/usr/lib
RUN pip install -r /mysiteRoot/requirements.txt
RUN apk del .tmp-build-deps

# Copy application
COPY ./mysite/ /mysiteRoot/mysite/

RUN adduser -D user
USER user

Django settings file

"""
Django settings for mysite project.

Generated by 'django-admin startproject' using Django 2.2.2.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 's0d^&2@s^126#6dsm7u4-t9pg03)if$dq##xxouht)#%#=o)r0'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['0.0.0.0']


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'channels',
    'chat',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'mysite.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'mysite.wsgi.application'
ASGI_APPLICATION = 'mysite.routing.application'

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('0.0.0.0', 6379)],
        },
    },
}

# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'

docker ps

CONTAINER ID        IMAGE                COMMAND                   CREATED             STATUS              PORTS                    NAMES
7966fe4962f7        tourmama_copy_app    "sh -c '\n       pyth…"   21 minutes ago      Up 20 minutes       0.0.0.0:8000->8000/tcp   tourmama_copy_app_1
61446d04c4b2        redis:5.0.5-alpine   "docker-entrypoint.s…"    27 minutes ago      Up 20 minutes       0.0.0.0:6379->6379/tcp   tourmama_copy_redis_1

Then the error in console shows :

app_1    | HTTP GET /chat/dadas/ 200 [0.01, 172.19.0.1:39468]
app_1    | WebSocket HANDSHAKING /ws/chat/dadas/ [172.19.0.1:39470]
app_1    | Exception inside application: [Errno 111] Connect call failed ('0.0.0.0', 6379)
app_1    |   File "/usr/local/lib/python3.7/site-packages/channels/sessions.py", line 179, in __call__
app_1    |     return await self.inner(receive, self.send)
app_1    |   File "/usr/local/lib/python3.7/site-packages/channels/middleware.py", line 41, in coroutine_call
app_1    |     await inner_instance(receive, send)
app_1    |   File "/usr/local/lib/python3.7/site-packages/channels/consumer.py", line 59, in __call__
app_1    |     [receive, self.channel_receive], self.dispatch
app_1    |   File "/usr/local/lib/python3.7/site-packages/channels/utils.py", line 59, in await_many_dispatch
app_1    |     await task
app_1    |   File "/usr/local/lib/python3.7/site-packages/channels_redis/core.py", line 425, in receive
app_1    |     real_channel
app_1    |   File "/usr/local/lib/python3.7/site-packages/channels_redis/core.py", line 477, in receive_single
app_1    |     index, channel_key, timeout=self.brpop_timeout
app_1    |   File "/usr/local/lib/python3.7/site-packages/channels_redis/core.py", line 324, in _brpop_with_clean
app_1    |     async with self.connection(index) as connection:
app_1    |   File "/usr/local/lib/python3.7/site-packages/channels_redis/core.py", line 813, in __aenter__
app_1    |     self.conn = await self.pool.pop()
app_1    |   File "/usr/local/lib/python3.7/site-packages/channels_redis/core.py", line 70, in pop
app_1    |     conns.append(await aioredis.create_redis(**self.host, loop=loop))
app_1    |   File "/usr/local/lib/python3.7/site-packages/aioredis/commands/__init__.py", line 178, in create_redis
app_1    |     loop=loop)
app_1    |   File "/usr/local/lib/python3.7/site-packages/aioredis/connection.py", line 108, in create_connection
app_1    |     timeout, loop=loop)
app_1    |   File "/usr/local/lib/python3.7/asyncio/tasks.py", line 388, in wait_for
app_1    |     return await fut
app_1    |   File "/usr/local/lib/python3.7/site-packages/aioredis/stream.py", line 19, in open_connection
app_1    |     lambda: protocol, host, port, **kwds)
app_1    |   File "/usr/local/lib/python3.7/asyncio/base_events.py", line 959, in create_connection
app_1    |     raise exceptions[0]
app_1    |   File "/usr/local/lib/python3.7/asyncio/base_events.py", line 946, in create_connection
app_1    |     await self.sock_connect(sock, address)
app_1    |   File "/usr/local/lib/python3.7/asyncio/selector_events.py", line 464, in sock_connect
app_1    |     return await fut
app_1    |   File "/usr/local/lib/python3.7/asyncio/selector_events.py", line 494, in _sock_connect_cb
app_1    |     raise OSError(err, f'Connect call failed {address}')
app_1    |   [Errno 111] Connect call failed ('0.0.0.0', 6379)
app_1    | WebSocket DISCONNECT /ws/chat/dadas/ [172.19.0.1:39470]


is anyone has any idea how to connect to redis container from app? thank you !

Upvotes: 4

Views: 1196

Answers (1)

Michał Krzywański
Michał Krzywański

Reputation: 16930

You should change :

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('0.0.0.0', 6379)],
        },
    },
}

to

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('redis', 6379)],
        },
    },
}

in your Django settings file.

When you set up containers from compose they are all connected to the default network created by compose. redis is in this case the DNS name of redis container and will be resolved to container ip automatically

Upvotes: 5

Related Questions