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.
Create docker-compose.yml
Create a docker-compose.yml file with the following content: ---
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 :
Generate APP_SECRET
Before starting, generate a random APP_SECRET for securing sessions:
Replace replace-me-with-a-random-string in the docker-compose.yml with the generated value.
Start the services
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
Verify the deployment
Check that both services are running: 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:
Dependencies Stage
Builder Stage
Runner Stage
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
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ARG BASE_PATH
ENV BASE_PATH=$BASE_PATH
ENV NEXT_TELEMETRY_DISABLED=1
ENV DATABASE_URL= "postgresql://user:pass@localhost:5432/dummy"
RUN npm run build-docker
Copies dependencies from deps stage
Builds the Next.js application
Uses dummy DATABASE_URL for build time
Disables Next.js telemetry
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# Install runtime dependencies
RUN pnpm --allow-build= '@prisma/engines' add \
npm-run-all dotenv chalk semver \
[email protected] \
@prisma/[email protected]
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
CMD [ "pnpm" , "start-docker" ]
Creates non-root user for security
Installs only production dependencies
Copies built application
Runs as unprivileged user
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:
Variable Description Example DATABASE_URLPostgreSQL connection string postgresql://user:pass@host:5432/umamiAPP_SECRETSecret key for securing sessions Generated with openssl rand -base64 32
Variable Description Default PORTApplication port 3000HOSTNAMEBind hostname 0.0.0.0BASE_PATHURL base path None REDIS_URLRedis connection string None
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
Common Commands
Troubleshooting
Cleanup
# 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
# View all logs
docker compose logs
# Execute commands in container
docker compose exec umami sh
# Check container resource usage
docker stats
# Inspect container
docker compose exec umami env
# Stop and remove containers
docker compose down
# Remove containers and volumes
docker compose down -v
# Remove unused images
docker image prune -a
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
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