dev-resources.site
for different kinds of informations.
Building a Real-Time Flask and Next.js Application with Redis, Socket.IO, and Docker Compose
Published at
12/21/2024
Categories
flask
docker
redis
socketio
Author
aixart
Author
6 person written this
aixart
open
In this blog, we’ll walk through the process of integrating WebSocket functionality using Socket.IO, adding caching support with Redis, and hosting a full-stack application built with Flask and Next.js using Docker Compose. By the end, you’ll have a scalable, real-time web application architecture ready to deploy.
Tech Stack Overview
- Backend: Flask with extensions like Flask-SocketIO for real-time communication, Flask-Session for session management, and SQLAlchemy for database interactions.
- Frontend: Next.js with client-side Socket.IO for real-time content synchronization.
- Database: PostgreSQL for persistent data storage.
- Cache: Redis for caching and quick data access.
- Hosting: Docker Compose for containerized deployment.
Step 1: Backend Setup with Flask and Redis
Flask Backend Structure
Here’s the structure of our Flask backend:
- Initialize Flask and Extensions:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_socketio import SocketIO
from flask_session import Session
import redis, os
app = Flask(__name__)
app.config["SECRET_KEY"] = "your_secret_key"
app.config["SQLALCHEMY_DATABASE_URI"] = "postgresql://username:password@postgres:5432/dbname"
app.config["SESSION_TYPE"] = "redis"
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_USE_SIGNER"] = True
app.config["SESSION_KEY_PREFIX"] = "session:"
app.config["SESSION_REDIS"] = redis.StrictRedis(host=os.getenv('REDIS_HOST', 'redis'), port=6379, db=0)
# Initialize extensions
socketio = SocketIO(app, cors_allowed_origins="*")
db = SQLAlchemy(app)
Session(app)
- Add Real-Time WebSocket Functionality:
from flask_socketio import emit, join_room, leave_room
@socketio.on('join_room')
def handle_join_room(data):
room = data.get('contentId')
join_room(room)
emit('user_joined', {'msg': 'A new user has joined the room'}, to=room)
@socketio.on('edit_content')
def handle_edit_content(data):
content_id = data.get('contentId')
content = data.get('content')
emit('content_update', {'content': content}, to=content_id, skip_sid=request.sid)
@socketio.on('leave_room')
def handle_leave_room(data):
room = data.get('contentId')
leave_room(room)
emit('user_left', {'msg': 'A user has left the room'}, to=room)
- Session and Redis Configuration:
import redis
cache = redis.StrictRedis(host=os.getenv('REDIS_HOST', 'redis'), port=6379, db=0)
- Environment Configuration (.env file):
SECRET_KEY=your_secret_key
SQLALCHEMY_DATABASE_URI=postgresql://postgres:postgres@postgres:5432/postgres
SQLALCHEMY_TRACK_MODIFICATIONS=False
APP_URL=AWS EC2 IP address
HOST=redis
Step 2: Frontend Setup with Next.js and Socket.IO
Client-Side Socket.IO Setup
- Install Socket.IO Client:
npm install socket.io-client
- Create a Socket Instance:
// socket.js
import { io } from "socket.io-client";
const SOCKET_URL = process.env.NEXT_PUBLIC_SOCKET_URL;
const socket = io(SOCKET_URL, {
autoConnect: false,
});
export default socket;
- Integrate TipTap Editor with Real-Time Updates:
"use client";
import socket from "@/shared/socket";
import { useEditor, EditorContent } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import { useEffect, useState } from "react";
const Tiptap = ({ content = "", contentId }) => {
const [isSaving, setIsSaving] = useState(false);
const editor = useEditor({
extensions: [StarterKit],
content,
onUpdate: ({ editor }) => {
const updatedContent = editor.getHTML();
if (contentId) {
setIsSaving(true);
socket.emit("edit_content", { contentId, content: updatedContent });
setTimeout(() => setIsSaving(false), 1000);
}
},
});
useEffect(() => {
if (contentId) {
if (!socket.connected) socket.connect();
socket.emit("join_room", { contentId });
socket.on("content_update", (data) => {
if (editor && data.content !== editor.getHTML()) {
editor.commands.setContent(data.content);
}
});
return () => {
socket.emit("leave_room", { contentId });
socket.off("content_update");
};
}
}, [contentId, editor]);
return <EditorContent editor={editor} />;
};
export default Tiptap;
- Environment Configuration (.env file):
NEXT_PUBLIC_API_URL=http://localhost:5000/api
NEXT_PUBLIC_SOCKET_URL=http://localhost:5000
DATABASE_NAME=postgres
DATABASE_USER=postgres
DATABASE_PASSWORD=postgres
Step 3: Docker Compose for Deployment
-
\
** Configuration**:
version: "3.8"
services:
nginx:
image: nginx:alpine
container_name: nginx_proxy
ports:
- "443:443"
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
depends_on:
- backend
- website
networks:
- app-network
website:
build:
context: ./website
dockerfile: Dockerfile
args:
NEXT_PUBLIC_SOCKET_URL: ${NEXT_PUBLIC_SOCKET_URL}
container_name: website
environment:
- NEXT_PUBLIC_SOCKET_URL=${NEXT_PUBLIC_SOCKET_URL}
expose:
- "3000"
networks:
- app-network
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: backend
expose:
- "5000"
networks:
- app-network
redis:
image: redis:alpine
container_name: redis
expose:
- "6379"
networks:
- app-network
postgres:
image: postgres:14-alpine
container_name: postgres
environment:
- POSTGRES_DB=${DATABASE_NAME}
- POSTGRES_USER=${DATABASE_USER}
- POSTGRES_PASSWORD=${DATABASE_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
postgres_data:
- Nginx Configuration for Proxy:
server {
listen 80;
server_name _;
location / {
proxy_pass http://website:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /api/ {
proxy_pass http://backend:5000;
proxy_set_header Host $host;
}
location /socket.io/ {
proxy_pass http://backend:5000/socket.io/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Step 4: Running the Application
- Build and start the services:
docker-compose up --build
- Access the application:
-
Frontend:
http://localhost
-
Backend API:
http://localhost/api
-
Frontend:
**GitHub : https://github.com/aixart12/colobrate-editor
flask Article's
30 articles in total
Deploy your Flask API on GCP Cloud Run 🚀
read article
RESTful GET and POST Requests: A Beginners Guide
read article
Flask Routes vs Flask-RESTful Routes
read article
Bringing Together Containers & SQL
read article
Creating a Local Environment to Operate GCS Emulator from Flask
read article
Optimising Flask Dockerfiles: Best Practices for DevOps and Developers
read article
A beginners guide to Constraints and Validations in Flask, SQLAlchemy
read article
Deploying Flask-based Microservices on AWS with ECS Service Connect
read article
FastAPI + Uvicorn = Blazing Speed: The Tech Behind the Hype
read article
CRUD With Flask And MySql #2 Prepare
read article
CRUD With Flask And MySql #1 Introduction
read article
Building an Anemia Detection System Using Machine Learning đźš‘
read article
Como usar WebSockets em Flask (How to use WebSockets in Flask)
read article
Setup Celery Worker with Supervisord on elastic beanstalk via .ebextensions
read article
How to create a simple Flask application
read article
Flask
read article
Building and Testing the Gemini API with CI/CD Pipeline
read article
Crossing the Line before the Finish Line. Also the line before that.
read article
Mastering Python Async IO with FastAPI
read article
Webinar Sobre Python e InteligĂŞncia Artificial Gratuito da Ebac
read article
Is Flask Dead? Is FastAPI the Future?
read article
422 Error with @jwt_required() in Flask App Deployed on VPS with Nginx
read article
WSGI vs ASGI: The Crucial Decision Shaping Your Web App’s Future in 2025
read article
Building a Real-Time Flask and Next.js Application with Redis, Socket.IO, and Docker Compose
currently reading
Carla Simulator 2 : Welcome to the Ride 🚗🏍️
read article
Python: A Comprehensive Overview in One Article
read article
Understanding Authentication: Session-Based vs. Token-Based (and Beyond!)
read article
Building RESTful APIs with Flask
read article
Validatorian
read article
LumaFlow
read article
Featured ones: