# How to Deploy DeepTutor to Production: Complete Docker Setup Guide

> Deploy DeepTutor to production with this complete Docker setup guide. Learn to configure environment variables, build the Docker image, and launch the FastAPI backend and Next.js frontend using docker compose.

- Repository: [✨Data Intelligence Lab@HKU✨/DeepTutor](https://github.com/HKUDS/DeepTutor)
- Tags: how-to-guide
- Published: 2026-04-08

---

**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.

```bash
cp .env.example .env

```

Edit `.env` to include at minimum:

```bash
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`](https://github.com/HKUDS/DeepTutor/blob/main/docker-compose.yml) configuration, this value is propagated into the container at runtime [*docker-compose.yml*](https://github.com/HKUDS/DeepTutor/blob/main/docker-compose.yml#L38-L81).

## 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*](https://github.com/HKUDS/DeepTutor/blob/main/Dockerfile#L15-L86).

Run the build command:

```bash
docker compose build

```

This process:
1. Builds the frontend assets in a Node.js stage
2. Installs Python requirements into a slim base image
3. Copies built assets and application code into the final stage

## Step 3 – Launch with Docker Compose

Start the production stack in detached mode:

```bash
docker compose up -d

```

The [`docker-compose.yml`](https://github.com/HKUDS/DeepTutor/blob/main/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*](https://github.com/HKUDS/DeepTutor/blob/main/docker-compose.yml#L16-L95).

Verify both services are healthy:

```bash
docker compose ps
curl -f http://localhost:8001/

```

## Architecture: How the Container Orchestrates Services

During startup, the **[`entrypoint.sh`](https://github.com/HKUDS/DeepTutor/blob/main/entrypoint.sh)** script (embedded in the Dockerfile at lines 60-68) validates the configuration, creates necessary user-data directories, and launches `supervisord` [*Dockerfile*](https://github.com/HKUDS/DeepTutor/blob/main/Dockerfile#L60-L68).

`supervisord` then manages two background processes via generated helper scripts:

- **[`start-backend.sh`](https://github.com/HKUDS/DeepTutor/blob/main/start-backend.sh)**: Executes `uvicorn` on the port defined by `BACKEND_PORT` (default 8001) [*Dockerfile*](https://github.com/HKUDS/DeepTutor/blob/main/Dockerfile#L98-L110)
- **[`start-frontend.sh`](https://github.com/HKUDS/DeepTutor/blob/main/start-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 on `FRONTEND_PORT` (default 3782) [*Dockerfile*](https://github.com/HKUDS/DeepTutor/blob/main/Dockerfile#L126-L155)

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:

```bash
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build

```

The [`docker-compose.dev.yml`](https://github.com/HKUDS/DeepTutor/blob/main/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 `supervisord` for simplified deployments.
- **Configure `.env`** with LLM credentials and set `NEXT_PUBLIC_API_BASE_EXTERNAL` for remote access.
- **Build once** using the multi-stage `Dockerfile` that 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`](https://github.com/HKUDS/DeepTutor/blob/main/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`](https://github.com/HKUDS/DeepTutor/blob/main/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`](https://github.com/HKUDS/DeepTutor/blob/main/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`](https://github.com/HKUDS/DeepTutor/blob/main/docker-compose.yml), so the update will not affect stored user data.