I'm trying to set up a Docker container running React on the frontend, Django on the backend and Neo4j as the database. At the moment all three components are running correctly, but I just can't get Django to connect to the Neo4j database. I've probably read all the tutorials on the internet and tried all the things but it always comes up with some error and the database is unreachable or denies access. I have also worked through this tutorial and created the models accordingly. However, I always get an error when I run "python manage.py install_labels".
The error is: neobolt.exceptions.SecurityError: Failed to establish secure connection to 'EOF occurred in violation of protocol (_ssl.c:997)'
Has anyone of you ever set up a similar environment or can help me? Maybe Django is just not that suitable for it .... Basically I just want a React frontend and a Python backend working with a Neo4j database. And the whole thing please in a Docker image. Are there any better alternatives for the backend?
Thanks in advance for your help!
In the following you can see all of my files that are important in my opinion.
My Dockerfiles look like this:
# Django Dockerfile
FROM python:3
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /myapp
COPY /myapp/django_backend/requirements.txt /myapp/
RUN pip install --no-cache-dir -r requirements.txt
COPY /myapp/django_backend /myapp/
# React Dockerfile
FROM node:17-alpine3.14
WORKDIR /myapp
COPY /myapp/react_frontend /myapp
RUN npm install
CMD ["npm", "start"]
My docker-compose file:
version: '3.8'
services:
react:
image: react_frontend:latest
restart: unless-stopped
volumes:
- ./myapp/react_frontend/public:/myapp/public
- ./myapp/react_frontend/src:/myapp/src
ports:
- 3000:3000
django:
image: django_backend:latest
command: python manage.py runserver 0.0.0.0:8000
volumes:
- ./myapp/django_backend:/myapp
ports:
- 8000:8000
expose:
- 8000
depends_on:
- neo4j
links:
- neo4j
neo4j:
image: neo4j:4.4.3
restart: unless-stopped
ports:
- 7474:7474
- 7687:7687
volumes:
- neo4j_data:/neo4j/data
environment:
- NEO4J_AUTH=none
- encrypted=False
volumes:
neo4j_data:
My requirements.txt:
Django
djangorestframework
django-cors-headers
psycopg2
# neo4j and django connection
django-neomodel
neomodel
neo4j-driver
And the settings.py from the Django backend:
from neomodel import config
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(_file_).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-+b-r19ofy)&x20j57qzv1f_zn(*6gld6!&bg&g@8=m=hz)8@as'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# for api
'rest_framework',
'corsheaders',
# for connection with database
'django_neomodel',
'techstack'
]
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',
'corsheaders.middleware.CorsMiddleware',
]
CORS_ORIGIN_ALLOW_ALL = True
ROOT_URLCONF = 'django_backend.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 = 'django_backend.wsgi.application'
config.DATABASE_URL = 'bolt://neo4j:neo4j@neo4j:7687'
config.ENCRYPTED_CONNECTION = False
# Password validation
# https://docs.djangoproject.com/en/4.0/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/4.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
I also tried to see if I could reach the database via the GraphDatabase.driver and that worked. The following test.py file is on the top level of my container and I can run it directly from the terminal and the database object is created successfully. Only the command 'python manage.py install_labels' still does not work and aborts with the error 'neobolt.exceptions.SecurityError: Failed to establish secure connection to 'EOF occurred in violation of protocol (_ssl.c:997)'.
# test.py:
from neo4j import GraphDatabase
class HelloWorldExample:
def __init__(self, uri, user, password):
self.driver = GraphDatabase.driver(uri, auth=(user, password), encrypted=False)
def close(self):
self.driver.close()
def print_greeting(self, message):
with self.driver.session() as session:
greeting = session.write_transaction(self._create_and_return_greeting, message)
print(greeting)
@staticmethod
def _create_and_return_greeting(tx, message):
result = tx.run("CREATE (a:Greeting) "
"SET a.message = $message "
"RETURN a.message + ', from node ' + id(a)", message=message)
return result.single()[0]
# if name == "main":
greeter = HelloWorldExample("bolt://neo4j:7687", "", "")
greeter.print_greeting("hello, world")
greeter.close()