NocoDB can be deployed using Docker in multiple ways. This guide covers Docker run, Docker Compose, and the auto-upstall script for production deployments.
Docker with SQLite
The simplest way to run NocoDB is with SQLite as the metadata database:
docker run -d \
--name noco \
-v "$(pwd)"/nocodb:/usr/app/data/ \
-p 8080:8080 \
nocodb/nocodb:latest
This command:
- Runs NocoDB in detached mode
- Mounts a local directory for data persistence
- Exposes the application on port 8080
- Uses SQLite (default) for metadata storage
Docker with PostgreSQL
For production use, it’s recommended to use PostgreSQL as the metadata database:
docker run -d \
--name noco \
-v "$(pwd)"/nocodb:/usr/app/data/ \
-p 8080:8080 \
-e NC_DB="pg://host.docker.internal:5432?u=root&p=password&d=d1" \
-e NC_AUTH_JWT_SECRET="569a1821-0a93-45e8-87ab-eb857f20a010" \
nocodb/nocodb:latest
Always generate a unique NC_AUTH_JWT_SECRET for production deployments. Use a strong random string.
Docker Compose
Docker Compose simplifies multi-container deployments. NocoDB provides several configurations:
Basic PostgreSQL Setup
Create a docker-compose.yml file:
version: '2.1'
services:
nocodb:
depends_on:
root_db:
condition: service_healthy
environment:
NC_DB: "pg://root_db:5432?u=postgres&p=password&d=root_db"
image: "nocodb/nocodb:latest"
ports:
- "8080:8080"
restart: always
volumes:
- "nc_data:/usr/app/data"
root_db:
environment:
POSTGRES_DB: root_db
POSTGRES_PASSWORD: password
POSTGRES_USER: postgres
healthcheck:
interval: 10s
retries: 10
test: "pg_isready -U \"$$POSTGRES_USER\" -d \"$$POSTGRES_DB\""
timeout: 2s
image: postgres:16.6
restart: always
volumes:
- "db_data:/var/lib/postgresql/data"
volumes:
db_data: {}
nc_data: {}
Run with:
Production Setup with Traefik
For production deployments with SSL and automatic certificate management:
version: "3.7"
networks:
traefik_proxy:
name: traefik_proxy
services:
nocodb:
container_name: nocodb
depends_on:
- nocodb-db
environment:
- "NC_DB=pg://nocodb-db:5432?u=${DATABASE_USER}&p=${DATABASE_PW}&d=${DATABASE_NAME}"
- "NC_PUBLIC_URL=https://nocodb.${DOMAINNAME}"
- NC_DISABLE_TELE=true
image: "nocodb/nocodb:latest"
labels:
- traefik.enable=true
- traefik.http.services.nocodb.loadbalancer.server.port=8080
- "traefik.http.routers.nocodb.rule=Host(`nocodb.${DOMAINNAME}`)"
- traefik.http.routers.nocodb.entrypoints=https
- com.centurylinklabs.watchtower.enable=true
networks:
- traefik_proxy
restart: always
volumes:
- "nocodb-data:/usr/app/data"
nocodb-db:
container_name: nocodb-db
environment:
POSTGRES_DB: "${DATABASE_NAME}"
POSTGRES_PASSWORD: "${DATABASE_PW}"
POSTGRES_USER: "${DATABASE_USER}"
healthcheck:
interval: 10s
retries: 10
test: "pg_isready -U ${DATABASE_USER} -d ${DATABASE_NAME}"
timeout: 2s
image: "postgres:12.17-alpine"
networks:
- traefik_proxy
restart: always
volumes:
- "nocodb-db:/var/lib/postgresql/data"
traefik:
command:
- "--providers.docker=true"
- "--ping=true"
- "--ping.entryPoint=ping"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=traefik_proxy"
- "--entryPoints.ping.address=:8081"
- "--entrypoints.http.address=:80"
- "--entrypoints.https.address=:443"
- "--entrypoints.https.http.tls.certresolver=letsencrypt"
- "--entrypoints.https.http.tls.domains[0].main=${DOMAINNAME}"
- "--entrypoints.https.http.tls.domains[0].sans=*.${DOMAINNAME}"
- "--entrypoints.http.http.redirections.entryPoint.to=https"
- "--entrypoints.http.http.redirections.entryPoint.scheme=https"
- "--certificatesresolvers.letsencrypt.acme.dnsChallenge.delayBeforeCheck=15"
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.letsencrypt.acme.email=info@${DOMAINNAME}"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesResolvers.letsencrypt.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53"
container_name: traefik
environment:
- "CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}"
image: "traefik:v2.11"
networks:
- default
- traefik_proxy
ports:
- "80:80"
- "443:443"
restart: always
volumes:
- "letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
watchtower:
command: "--schedule \"0 5 * * *\" --cleanup --label-enable"
container_name: watchtower
image: containrrr/watchtower
labels:
- com.centurylinklabs.watchtower.enable=true
networks:
- traefik_proxy
restart: always
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
volumes:
letsencrypt:
name: traefik-letsencrypt
nocodb-data:
name: nocodb-data
nocodb-db:
name: nocodb-db
Auto-upstall (Production)
Auto-upstall is a one-command installation script that sets up NocoDB with all production dependencies:
bash <(curl -sSL http://install.nocodb.com/noco.sh) <(mktemp)
What Auto-upstall Does
- Automatically installs Docker and Docker Compose if not present
- Sets up NocoDB with PostgreSQL, Redis, Minio, and Traefik gateway
- Configures SSL with automatic certificate renewal (requires a domain)
- Enables automatic updates when you run the command again
Auto-upstall requires a domain or subdomain name for SSL certificate generation. Ensure DNS is properly configured before installation.
Auto-upstall Features
- PostgreSQL for metadata storage
- Redis for caching
- Minio for S3-compatible object storage
- Traefik as reverse proxy with automatic HTTPS
- Watchtower for automatic container updates
Accessing NocoDB
After deployment, access NocoDB at:
- Local Docker:
http://localhost:8080/dashboard
- Production with domain:
https://nocodb.yourdomain.com/dashboard
Updating NocoDB
Docker Run
docker stop noco
docker rm noco
docker pull nocodb/nocodb:latest
# Re-run your docker run command
Docker Compose
docker-compose pull
docker-compose up -d
Auto-upstall
# Simply re-run the installation command
bash <(curl -sSL http://install.nocodb.com/noco.sh) <(mktemp)
Next Steps