A real-time collaborative code editor where multiple users can edit the same file simultaneously β like Google Docs, but for code. Built with React, Node.js, Yjs, Socket.io, Docker, and deployed on AWS ECS.
π Live Demo: https://docker-aws-editor.onrender.com/
- Multiple users can join a shared editor session using a username
- All edits sync in real-time across every connected user
- A live sidebar shows who is currently in the session
- Built on Yjs (CRDT-based sync) + Socket.io (WebSockets) for conflict-free collaboration
- The entire app (frontend + backend) runs as a single Docker container
| Layer | Technology |
|---|---|
| Frontend | React.js + Monaco Editor (VS Code's editor) |
| Real-Time Sync | Yjs (CRDT) + y-socket.io |
| Backend | Node.js + Express.js |
| WebSockets | Socket.io |
| Containerization | Docker (Multi-Stage Build) |
| Container Registry | AWS ECR (Elastic Container Registry) |
| Cloud Deployment | AWS ECS (Elastic Container Service) |
Yjs is a CRDT (Conflict-free Replicated Data Type) library. This means:
- Every user has a local copy of the document
- Edits are merged automatically without conflicts
- No central "locking" mechanism needed β everyone types freely
User A (Browser) User B (Browser)
| |
Monaco Editor Monaco Editor
| |
y-socket.io y-socket.io
| |
βββββββββ Socket.io ββββββββ
|
Node.js Server
(YSocketIO handles sync)
|
Serves React build
from /public folder
The backend:
- Serves the React frontend as static files from the
/publicfolder - Handles WebSocket connections via Socket.io
- Uses
YSocketIOto sync Yjs documents between all connected clients
Docker-AWS/
βββ Frontend/
β βββ src/
β β βββ App.jsx # Main React component
β βββ package.json
β βββ vite.config.js
βββ Backend/
β βββ index.js # Express + Socket.io server
β βββ package.json
βββ dockerfile # Multi-stage Docker build
- Node.js 20+
- Docker Desktop
Backend:
cd Backend
npm install
node index.js
# Server running on http://localhost:3000Frontend:
cd Frontend
npm install
npm run dev
# Dev server on http://localhost:5173# Build the image
docker build -t server .
# Run the container
docker run -p 4000:3000 server
# App available at http://localhost:4000The dockerfile uses a multi-stage build to keep the final image small and production-ready:
# Stage 1 β Build the React frontend
FROM node:20-alpine AS frontend-builder
COPY ./Frontend /app
WORKDIR /app
RUN npm install
RUN npm run build # Outputs to /app/dist
# Stage 2 β Run the backend + serve frontend
FROM node:20-alpine
COPY ./Backend /app
WORKDIR /app
RUN npm install
COPY --from=frontend-builder /app/dist /app/public # Copy built frontendWhy multi-stage?
- Stage 1 installs all frontend dev dependencies and builds the React app
- Stage 2 only contains the backend + the compiled frontend files
- Result: a lean production image with no unnecessary build tools
The backend serves the React build as static files:
app.use(express.static("public")) // Serves /app/public = React build outputaws ecr get-login-password --region ap-northeast-1 | docker login \
--username AWS \
--password-stdin 446931897427.dkr.ecr.ap-northeast-1.amazonaws.comOutput: Login Succeeded
Since AWS ECS runs Linux containers, build with the correct platform (important if you're on Windows/Mac ARM):
docker buildx build --platform linux/amd64 -t docker-aws/server .docker tag docker-aws/server:latest \
446931897427.dkr.ecr.ap-northeast-1.amazonaws.com/docker-aws/server:latestdocker push \
446931897427.dkr.ecr.ap-northeast-1.amazonaws.com/docker-aws/server:latestOutput:
latest: digest: sha256:1679862924fc58dcbc7603577fe9f90f7126301149ff149c7f430e8602b17cb3 size: 1994
- Go to AWS Console β ECS β Create Cluster
- Choose Fargate (serverless, no EC2 management)
- Create a Task Definition:
- Container image:
446931897427.dkr.ecr.ap-northeast-1.amazonaws.com/docker-aws/server:latest - Port mapping:
3000
- Container image:
- Create a Service from the task definition
- Set desired count (e.g., 1 for single instance, more for scale)
- ECS pulls from ECR and runs your container automatically
Docker packages your app + all its dependencies into a container β a portable unit that runs the same everywhere, regardless of the host machine's OS or configuration.
| Container | Virtual Machine | |
|---|---|---|
| Startup | Seconds | Minutes |
| Size | MBs | GBs |
| OS | Shares host kernel | Full OS per VM |
| Isolation | Process-level | Hardware-level |
Elastic Container Registry β AWS's private Docker image registry. Like Docker Hub, but hosted on AWS and integrated with ECS.
Elastic Container Service β AWS's managed container orchestration platform. You give it a Docker image and it handles running, scaling, and restarting containers.
Yjs is a conflict-free data sync library. CRDTs guarantee that even if two users edit simultaneously, their changes merge correctly without data loss β no "last write wins" conflicts.
The backend exposes a health check route used by AWS ECS to verify the container is running:
GET /health
β { "message": "ok", "success": true }
- What Docker is and why developers use it
- Difference between containers and virtual machines
- How to write a Dockerfile (
FROM,WORKDIR,COPY,RUN) - Multi-stage Docker builds for optimized images
- Real-time collaboration using Yjs (CRDTs) + Socket.io
- How to push Docker images to AWS ECR
- How to deploy containerized apps on AWS ECS
- How real-world systems scale for multiple users