Skip to main content

Overview

Docker is the recommended deployment method for Umami. It provides a consistent, reproducible environment and simplifies the installation process by bundling all dependencies.

Docker Image

Umami provides official Docker images hosted on GitHub Container Registry:
ghcr.io/umami-software/umami:latest
The Docker image is based on Node.js 22 Alpine Linux for minimal size and security.

Docker Compose Deployment

Basic Setup

The easiest way to deploy Umami is using Docker Compose, which automatically sets up both Umami and PostgreSQL.
1

Create docker-compose.yml

Create a docker-compose.yml file with the following content:
docker-compose.yml
---
services:
  umami:
    image: ghcr.io/umami-software/umami:latest
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://umami:umami@db:5432/umami
      APP_SECRET: replace-me-with-a-random-string
    depends_on:
      db:
        condition: service_healthy
    init: true
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "curl http://localhost:3000/api/heartbeat"]
      interval: 5s
      timeout: 5s
      retries: 5
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: umami
    volumes:
      - umami-db-data:/var/lib/postgresql/data
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 5s
      timeout: 5s
      retries: 5
volumes:
  umami-db-data:
2

Generate APP_SECRET

Before starting, generate a random APP_SECRET for securing sessions:
openssl rand -base64 32
Replace replace-me-with-a-random-string in the docker-compose.yml with the generated value.
3

Start the services

docker compose up -d
This will:
  • Pull the Umami and PostgreSQL images
  • Create a persistent volume for database storage
  • Start both containers in the background
  • Run health checks to ensure services are ready
4

Verify the deployment

Check that both services are running:
docker compose ps
Access Umami at http://localhost:3000

Standalone Docker Deployment

If you prefer to manage your own database, you can run Umami as a standalone container:
docker run -d \
  --name umami \
  -p 3000:3000 \
  -e DATABASE_URL=postgresql://username:password@host:5432/umami \
  -e APP_SECRET=your-secret-key \
  --restart always \
  ghcr.io/umami-software/umami:latest
Replace the DATABASE_URL with your actual PostgreSQL connection string.

Understanding the Dockerfile

The Umami Dockerfile uses a multi-stage build process for optimal image size:
FROM node:22-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm
RUN pnpm install --frozen-lockfile
  • Based on Node.js 22 Alpine
  • Installs pnpm package manager
  • Installs dependencies with locked versions

Custom Build Arguments

The Dockerfile supports build arguments for customization:

BASE_PATH

Serve Umami from a subdirectory:
docker build --build-arg BASE_PATH=/analytics -t umami:custom .
This allows you to access Umami at http://yourdomain.com/analytics

NODE_OPTIONS

Customize Node.js runtime options:
docker build --build-arg NODE_OPTIONS="--max-old-space-size=4096" -t umami:custom .

Environment Variables

Key environment variables for Docker deployment:
VariableDescriptionExample
DATABASE_URLPostgreSQL connection stringpostgresql://user:pass@host:5432/umami
APP_SECRETSecret key for securing sessionsGenerated with openssl rand -base64 32
See the Environment Variables page for a complete list.

Health Checks

The docker-compose.yml includes health checks for both services:

Umami Health Check

healthcheck:
  test: ["CMD-SHELL", "curl http://localhost:3000/api/heartbeat"]
  interval: 5s
  timeout: 5s
  retries: 5
This endpoint returns 200 OK when Umami is ready to accept requests.

PostgreSQL Health Check

healthcheck:
  test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
  interval: 5s
  timeout: 5s
  retries: 5
Ensures PostgreSQL is ready before starting Umami.

Persistent Storage

Database data is stored in a Docker volume:
volumes:
  - umami-db-data:/var/lib/postgresql/data

Backing Up the Volume

# Create backup
docker run --rm \
  -v umami-db-data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/umami-backup.tar.gz /data

# Restore backup
docker run --rm \
  -v umami-db-data:/data \
  -v $(pwd):/backup \
  alpine tar xzf /backup/umami-backup.tar.gz -C /

Managing Docker Containers

# Start services
docker compose up -d

# Stop services
docker compose down

# View logs
docker compose logs -f umami

# Restart services
docker compose restart

# Check status
docker compose ps

Production Recommendations

Use a Reverse Proxy

Put Nginx or Traefik in front of Umami for SSL termination and load balancing.

External Database

Use a managed PostgreSQL service for better reliability and backups.

Resource Limits

Set memory and CPU limits in docker-compose.yml to prevent resource exhaustion.

Regular Backups

Automate database backups with pg_dump or volume snapshots.

Example Production Configuration

docker-compose.yml
services:
  umami:
    image: ghcr.io/umami-software/umami:latest
    ports:
      - "127.0.0.1:3000:3000"  # Only bind to localhost
    environment:
      DATABASE_URL: postgresql://umami:${DB_PASSWORD}@db:5432/umami
      APP_SECRET: ${APP_SECRET}
      FORCE_SSL: 1
      REDIS_URL: redis://redis:6379
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1G
    depends_on:
      db:
        condition: service_healthy
    restart: always
    init: true

Next Steps

Environment Variables

Configure advanced options

Upgrading

Update to the latest version

PostgreSQL

Optimize database performance

Troubleshooting

Solve common issues

Build docs developers (and LLMs) love