# How to Deploy OpenMAIC Using Docker: A Complete Production Setup Guide

> Easily deploy OpenMAIC using Docker with this complete production setup guide. Clone the repo, set env variables, and run a single command for a seamless installation.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: how-to-guide
- Published: 2026-09-08

---

**Deploy OpenMAIC using Docker by cloning the repository, configuring environment variables in `.env.local`, and running `docker compose up --build -d` for the core app or adding the `video-export` profile to include the isolated MP4 render service.**

OpenMAIC is a modern web application from THU-MAIC that runs entirely inside Docker containers. The repository provides production-ready containerization with two specialized Dockerfiles and a [`docker-compose.yml`](https://github.com/THU-MAIC/OpenMAIC/blob/main/docker-compose.yml) that orchestrates the complete stack. This guide walks through each deployment step while explaining the security and networking decisions implemented in the source code.

## Prerequisites and Repository Structure

Before deploying, ensure you have **Docker Engine 20.10+** and **Docker Compose v2** installed. The repository organizes container assets across three key locations:

- **`Dockerfile`** – Production Next.js application build
- **`render-service/Dockerfile`** – Isolated video rendering environment
- **[`docker-compose.yml`](https://github.com/THU-MAIC/OpenMAIC/blob/main/docker-compose.yml)** – Service orchestration with profile-based activation

Clone the repository to your local machine:

```bash
git clone https://github.com/THU-MAIC/OpenMAIC.git
cd OpenMAIC

```

## Core Container: The OpenMAIC Application

The main `Dockerfile` in the repository root builds a production-optimized Next.js application. It handles dependency installation via `npm ci`, compiles static assets, and produces a minimal runner image that serves pre-built files on **port 3000**.

According to the OpenMAIC source code, this container:

- Uses multi-stage builds to minimize final image size
- Bakes `NEXT_PUBLIC_*` environment variables into the client bundle at build time
- Mounts a persistent volume (`openmaic-data`) at `/app/data` for runtime file storage

### Step 1: Configure Environment Variables

Create a `.env.local` file in the repository root with required runtime configuration:

```bash
cat > .env.local <<EOF
NEXT_PUBLIC_PERSISTENCE=https://your-persistence-api.example.com
NEXT_PUBLIC_PERSISTENCE_TOKEN=YOUR_TOKEN
EOF

```

The [`docker-compose.yml`](https://github.com/THU-MAIC/OpenMAIC/blob/main/docker-compose.yml) supports additional build-time arguments including `ALPINE_MIRROR` and `NPM_REGISTRY` for organizations behind corporate proxies. Refer to the full variable list in the repository's main [`README.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/README.md).

### Step 2: Deploy the Core Application

Build and start only the OpenMAIC application container:

```bash
docker compose up --build -d

```

This command starts the `openmaic` service and exposes it at `http://localhost:3000`. The `-d` flag runs containers in detached mode suitable for production deployments.

## Video Export: The Isolated Render Service

OpenMAIC supports MP4 video export through a **security-hardened render service** defined in `render-service/Dockerfile`. This container combines Node.js 22, Chromium headless shell, and FFmpeg in an isolated networking environment.

### Security Architecture

As implemented in `THU-MAIC/OpenMAIC`, the render service applies defense-in-depth measures:

- **Network isolation**: Runs on an internal Docker network (`render`) unreachable from the host
- **Egress lockdown**: Entrypoint script configures **iptables rules** that block all outbound traffic except loopback and established connections
- **Process containment**: The untrusted Chromium browser cannot reach external hosts even if compromised

The render service exposes **port 9000** internally and is accessible only from the main application container via `http://render-service:9000`.

### Step 3: Enable Video Export Capability

Activate the render service using Docker Compose profiles:

```bash
docker compose --profile video-export up --build -d

```

This launches both the core application and the isolated render environment. The profile-based approach keeps resource-intensive video processing optional.

## Optional: Server-Side Persistence with PostgreSQL

For deployments requiring durable storage, enable the `server-persistence` profile:

```bash
docker compose --profile server-persistence up --build -d

```

Set the database password via `.env.local`:

```bash
echo "POSTGRES_PASSWORD=secure_password_here" >> .env.local

```

The [`docker-compose.yml`](https://github.com/THU-MAIC/OpenMAIC/blob/main/docker-compose.yml) automatically configures the PostgreSQL connection and volume persistence.

## Deployment Profiles Reference

| Profile | Services Launched | Use Case |
|---------|-------------------|----------|
| *(default)* | `openmaic` only | Basic deployment, no video export |
| `video-export` | `openmaic` + `render-service` | Full functionality with MP4 generation |
| `server-persistence` | `openmaic` + `postgres` | Durable storage backend |
| Combined | `--profile video-export --profile server-persistence` | Production-ready complete stack |

## Verifying Your Deployment

Check container status after startup:

```bash
docker compose ps

```

View application logs:

```bash
docker compose logs -f openmaic

```

Test video export functionality by triggering an MP4 generation through the web interface, then monitor the render service:

```bash
docker compose logs -f render-service

```

## Key Configuration Files

| File | Purpose | Location |
|------|---------|----------|
| `Dockerfile` | Production Next.js build with minimal runtime image | Repository root |
| `render-service/Dockerfile` | Hardened Chromium + FFmpeg environment for video processing | `render-service/` |
| [`docker-compose.yml`](https://github.com/THU-MAIC/OpenMAIC/blob/main/docker-compose.yml) | Service definitions, networks, volumes, and profile triggers | Repository root |
| [`render-service/README.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/render-service/README.md) | Security model and networking documentation | `render-service/` |

The [`render-service/README.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/render-service/README.md) specifically documents the iptables egress rules and resource profile recommendations for production deployments.

## Troubleshooting Common Issues

**Build failures behind corporate proxy**: Set `ALPINE_MIRROR` and `NPM_REGISTRY` build arguments in [`docker-compose.yml`](https://github.com/THU-MAIC/OpenMAIC/blob/main/docker-compose.yml) or export as environment variables before building.

**Render service timeouts**: The Chromium process requires substantial memory. Ensure Docker Desktop or your daemon allocates at least **4GB RAM** to container workloads.

**Persistence connection errors**: Verify `NEXT_PUBLIC_PERSISTENCE` and `NEXT_PUBLIC_PERSISTENCE_TOKEN` values in `.env.local` are correctly formatted without trailing slashes.

## Summary

- **Clone** the OpenMAIC repository from `THU-MAIC/OpenMAIC`
- **Configure** `.env.local` with required `NEXT_PUBLIC_*` variables
- **Deploy core app** with `docker compose up --build -d`
- **Add video export** using `--profile video-export` for the security-isolated render service
- **Enable persistence** with `--profile server-persistence` when PostgreSQL is needed
- **Verify** iptables rules in `render-service/Dockerfile` provide Chromium sandboxing for untrusted code execution

## Frequently Asked Questions

### What Docker version is required for OpenMAIC?

Docker Engine 20.10 or later with Compose v2 support is required. The [`docker-compose.yml`](https://github.com/THU-MAIC/OpenMAIC/blob/main/docker-compose.yml) uses modern syntax including `profiles` and `secrets` that older versions may not parse correctly.

### Why does the render service use iptables?

The `render-service/Dockerfile` entrypoint installs iptables rules that block all outbound traffic except loopback and established connections. This prevents a compromised Chromium process from reaching external hosts, applying defense-in-depth for untrusted browser code execution.

### Can I run OpenMAIC without video export?

Yes. The default `docker compose up` launches only the core `openmaic` container on port 3000. The render service is entirely optional and activated only via the `video-export` profile, reducing resource consumption for deployments that don't need MP4 generation.

### How do I update an existing OpenMAIC Docker deployment?

Pull the latest code with `git pull`, then rebuild with `docker compose up --build -d` (adding profiles as needed). Persistent data in the `openmaic-data` volume and PostgreSQL database survives container recreation.