How to Deploy DeepTutor to Production: Complete Docker Setup Guide
Deploy DeepTutor to production by configuring environment variables from .env.example, building the multi-stage Docker image, and running docker compose up -d to launch the all-in-one container that supervises both the FastAPI backend (port 8001) and Next.js frontend (port 3782).
DeepTutor is an open-source intelligent tutoring system developed by HKUDS that pairs a FastAPI backend with a Next.js frontend. To deploy DeepTutor to production, the repository packages both services into a single Docker image orchestrated by supervisord, enabling portable deployments across local machines, VPS instances, or cloud platforms.
Step 1 – Configure Production Environment Variables
Begin by copying the template and setting your LLM provider credentials. The application requires API keys for both the language model and embedding service to function.
cp .env.example .env
Edit .env to include at minimum:
LLM_BINDING=openai
LLM_MODEL=gpt-4o-mini
LLM_API_KEY=sk-xxxxxxxxxxxx
EMBEDDING_BINDING=openai
EMBEDDING_MODEL=text-embedding-3-large
EMBEDDING_API_KEY=sk-xxxxxxxxxxxx
EMBEDDING_DIMENSION=3072
Remote Server Configuration
For deployments where the browser accesses the backend over a network, you must set NEXT_PUBLIC_API_BASE_EXTERNAL (or NEXT_PUBLIC_API_BASE) in .env. This variable tells the frontend the public address of the FastAPI server (e.g., https://my-server.com:8001). According to the docker-compose.yml configuration, this value is propagated into the container at runtime docker-compose.yml.
Step 2 – Build the Multi-Stage Production Image
The Dockerfile uses a multi-stage build process that compiles the Next.js frontend, installs Python dependencies, and assembles the final production image Dockerfile.
Run the build command:
docker compose build
This process:
- Builds the frontend assets in a Node.js stage
- Installs Python requirements into a slim base image
- Copies built assets and application code into the final stage
Step 3 – Launch with Docker Compose
Start the production stack in detached mode:
docker compose up -d
The docker-compose.yml exposes two ports: 8001 for the FastAPI backend and 3782 for the Next.js frontend. It also mounts persistent volumes for user data storage docker-compose.yml.
Verify both services are healthy:
docker compose ps
curl -f http://localhost:8001/
Architecture: How the Container Orchestrates Services
During startup, the entrypoint.sh script (embedded in the Dockerfile at lines 60-68) validates the configuration, creates necessary user-data directories, and launches supervisord Dockerfile.
supervisord then manages two background processes via generated helper scripts:
start-backend.sh: Executesuvicornon the port defined byBACKEND_PORT(default 8001) Dockerfilestart-frontend.sh: Performs runtime substitution of__NEXT_PUBLIC_API_BASE_PLACEHOLDER__with the actual API URL from environment variables, then starts the Next.js standalone server onFRONTEND_PORT(default 3782) Dockerfile
Because Next.js inlines public environment variables at build time, the placeholder replacement technique enables true runtime configuration without requiring image rebuilds when API endpoints change.
Development Mode with Hot-Reload
For local development, use the override file to enable hot-reloading and volume-mounted source code:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
The docker-compose.dev.yml modifies the build context to include full node_modules and mounts local directories for live code changes.
Summary
- DeepTutor packages both frontend and backend into a single Docker image supervised by
supervisordfor simplified deployments. - Configure
.envwith LLM credentials and setNEXT_PUBLIC_API_BASE_EXTERNALfor remote access. - Build once using the multi-stage
Dockerfilethat handles Node.js compilation and Python dependency installation. - Expose ports 8001 and 3782 via Docker Compose, with persistent volumes for data storage.
- Runtime frontend configuration is achieved via placeholder replacement in
start-frontend.sh, eliminating the need to rebuild for different API endpoints.
Frequently Asked Questions
What ports does DeepTutor use in production?
DeepTutor exposes port 8001 for the FastAPI backend API and port 3782 for the Next.js frontend web interface. These are mapped in docker-compose.yml and can be customized via the BACKEND_PORT and FRONTEND_PORT environment variables.
How do I deploy DeepTutor to a remote server with a public domain?
Set NEXT_PUBLIC_API_BASE_EXTERNAL in your .env file to the public HTTPS or HTTP address of your backend (e.g., https://api.example.com:8001). The start-frontend.sh script automatically injects this URL into the built frontend at container startup, allowing the browser to reach the backend across networks.
Can I run DeepTutor without Docker?
While the repository is optimized for Docker deployment, you can run the FastAPI backend directly with uvicorn and the Next.js frontend with npm start after manually installing dependencies and setting all required environment variables. However, the Docker approach is strongly recommended for production consistency.
How do I update my DeepTutor production deployment?
Pull the latest code changes, rebuild the image with docker compose build, and restart the containers with docker compose up -d. Your data persists in the mounted volumes defined in docker-compose.yml, so the update will not affect stored user data.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →