Docker Installation
Prerequisites
- Docker and Docker Compose are installed
- Ensure the Docker service is running
1. Create docker-compose.yml
# Create a folder named my-project (or any other name) to store the system files generated by NocoBase
mkdir my-project && cd my-project
# Create an empty docker-compose.yml file
vi docker-compose.yml
Choose a NocoBase version (Version Comparison) and database type, then copy the corresponding configuration into docker-compose.yml.
Configuration Notes
- Choose an image:
latest latest-full beta beta-full alpha alpha-full 1.7.14 1.7.14-full
- For production environments, it is recommended to pin a specific version number to avoid unintentional automatic upgrades. View all versions
- Docker Hub image:
nocobase/nocobase:latest-full
- The full image includes PostgreSQL 16/17 client, MySQL 8.0 client, Oracle 19.25 client required for backup and migration management plugins, as well as LibreOffice required for template printing (PDF).
- If you need to build your own image, you can refer to the official Dockerfile (slim version) and Dockerfile-full (full version)
- Modify
APP_KEY: Please replace your-secret-key with a random string, which is used to encrypt sensitive information such as user tokens.
- Use an existing database: If you already have a database service, please change
DB_HOST to the database server address, and delete or comment out the database service configuration (e.g., postgres, mysql, mariadb services).
- Port mapping: By default, port 80 of the container is mapped to port 13000 of the host. You can modify it as needed.
networks:
nocobase:
driver: bridge
services:
app:
image: nocobase/nocobase:latest-full
restart: always
networks:
- nocobase
depends_on:
- postgres
environment:
# Application key, used to generate user tokens, etc.
# If APP_KEY is changed, old tokens will become invalid
# Can be any random string, and ensure it is not leaked
- APP_KEY=your-secret-key
# Database type, supports postgres, mysql, mariadb
- DB_DIALECT=postgres
# Database host, can be replaced with an existing database server IP
- DB_HOST=postgres
# Database port
- DB_PORT=5432
# Database name
- DB_DATABASE=nocobase
# Database user
- DB_USER=nocobase
# Database password
- DB_PASSWORD=nocobase
# Timezone, please change it to your local timezone, e.g., America/New_York
- TZ=Etc/UTC
volumes:
- ./storage:/app/nocobase/storage
ports:
- '13000:80'
# init: true
# If you use an existing database service, you can skip starting postgres
postgres:
image: postgres:16
restart: always
command: postgres -c wal_level=logical
environment:
POSTGRES_USER: nocobase
POSTGRES_DB: nocobase
POSTGRES_PASSWORD: nocobase
volumes:
- ./storage/db/postgres:/var/lib/postgresql/data
networks:
- nocobase
networks:
nocobase:
driver: bridge
services:
app:
image: nocobase/nocobase:latest-full
restart: always
networks:
- nocobase
depends_on:
- mysql
environment:
# Application key, used to generate user tokens, etc.
# If APP_KEY is changed, old tokens will become invalid
# Can be any random string, and ensure it is not leaked
- APP_KEY=your-secret-key
# Database type, supports postgres, mysql, mariadb
- DB_DIALECT=mysql
# Database host, can be replaced with an existing database server IP
- DB_HOST=mysql
# Database port
- DB_PORT=3306
# Database name
- DB_DATABASE=nocobase
# Database user
- DB_USER=root
# Database password
- DB_PASSWORD=nocobase
# Whether to convert table and field names to snake case
- DB_UNDERSCORED=true
# Timezone, please change it to your local timezone, e.g., America/New_York
- TZ=Etc/UTC
volumes:
- ./storage:/app/nocobase/storage
ports:
- '13000:80'
# init: true
# If you use an existing database service, you can skip starting mysql
mysql:
image: mysql:8
environment:
MYSQL_DATABASE: nocobase
MYSQL_USER: nocobase
MYSQL_PASSWORD: nocobase
MYSQL_ROOT_PASSWORD: nocobase
restart: always
volumes:
- ./storage/db/mysql:/var/lib/mysql
networks:
- nocobase
networks:
nocobase:
driver: bridge
services:
app:
image: nocobase/nocobase:latest-full
restart: always
networks:
- nocobase
depends_on:
- mariadb
environment:
# Application key, used to generate user tokens, etc.
# If APP_KEY is changed, old tokens will become invalid
# Can be any random string, and ensure it is not leaked
- APP_KEY=your-secret-key
# Database type, supports postgres, mysql, mariadb
- DB_DIALECT=mariadb
# Database host, can be replaced with an existing database server IP
- DB_HOST=mariadb
# Database port
- DB_PORT=3306
# Database name
- DB_DATABASE=nocobase
# Database user
- DB_USER=root
# Database password
- DB_PASSWORD=nocobase
# Whether to convert table and field names to snake case
- DB_UNDERSCORED=true
# Timezone, please change it to your local timezone, e.g., America/New_York
- TZ=Etc/UTC
volumes:
- ./storage:/app/nocobase/storage
ports:
- '13000:80'
# init: true
# If you use an existing database service, you can skip starting mariadb
mariadb:
image: mariadb:11
environment:
MYSQL_DATABASE: nocobase
MYSQL_USER: nocobase
MYSQL_PASSWORD: nocobase
MYSQL_ROOT_PASSWORD: nocobase
restart: always
volumes:
- ./storage/db/mariadb:/var/lib/mysql
networks:
- nocobase
networks:
nocobase:
driver: bridge
services:
app:
image: nocobase/nocobase:beta-full
restart: always
networks:
- nocobase
depends_on:
- postgres
environment:
# Application key, used to generate user tokens, etc.
# If APP_KEY is changed, old tokens will become invalid
# Can be any random string, and ensure it is not leaked
- APP_KEY=your-secret-key
# Database type, supports postgres, mysql, mariadb
- DB_DIALECT=postgres
# Database host, can be replaced with an existing database server IP
- DB_HOST=postgres
# Database port
- DB_PORT=5432
# Database name
- DB_DATABASE=nocobase
# Database user
- DB_USER=nocobase
# Database password
- DB_PASSWORD=nocobase
# Timezone, please change it to your local timezone, e.g., America/New_York
- TZ=Etc/UTC
volumes:
- ./storage:/app/nocobase/storage
ports:
- '13000:80'
# init: true
# If you use an existing database service, you can skip starting postgres
postgres:
image: postgres:16
restart: always
command: postgres -c wal_level=logical
environment:
POSTGRES_USER: nocobase
POSTGRES_DB: nocobase
POSTGRES_PASSWORD: nocobase
volumes:
- ./storage/db/postgres:/var/lib/postgresql/data
networks:
- nocobase
networks:
nocobase:
driver: bridge
services:
app:
image: nocobase/nocobase:beta-full
restart: always
networks:
- nocobase
depends_on:
- mysql
environment:
# Application key, used to generate user tokens, etc.
# If APP_KEY is changed, old tokens will become invalid
# Can be any random string, and ensure it is not leaked
- APP_KEY=your-secret-key
# Database type, supports postgres, mysql, mariadb
- DB_DIALECT=mysql
# Database host, can be replaced with an existing database server IP
- DB_HOST=mysql
# Database port
- DB_PORT=3306
# Database name
- DB_DATABASE=nocobase
# Database user
- DB_USER=root
# Database password
- DB_PASSWORD=nocobase
# Whether to convert table and field names to snake case
- DB_UNDERSCORED=true
# Timezone, please change it to your local timezone, e.g., America/New_York
- TZ=Etc/UTC
volumes:
- ./storage:/app/nocobase/storage
ports:
- '13000:80'
# init: true
# If you use an existing database service, you can skip starting mysql
mysql:
image: mysql:8
environment:
MYSQL_DATABASE: nocobase
MYSQL_USER: nocobase
MYSQL_PASSWORD: nocobase
MYSQL_ROOT_PASSWORD: nocobase
restart: always
volumes:
- ./storage/db/mysql:/var/lib/mysql
networks:
- nocobase
networks:
nocobase:
driver: bridge
services:
app:
image: nocobase/nocobase:beta-full
restart: always
networks:
- nocobase
depends_on:
- mariadb
environment:
# Application key, used to generate user tokens, etc.
# If APP_KEY is changed, old tokens will become invalid
# Can be any random string, and ensure it is not leaked
- APP_KEY=your-secret-key
# Database type, supports postgres, mysql, mariadb
- DB_DIALECT=mariadb
# Database host, can be replaced with an existing database server IP
- DB_HOST=mariadb
# Database port
- DB_PORT=3306
# Database name
- DB_DATABASE=nocobase
# Database user
- DB_USER=root
# Database password
- DB_PASSWORD=nocobase
# Whether to convert table and field names to snake case
- DB_UNDERSCORED=true
# Timezone, please change it to your local timezone, e.g., America/New_York
- TZ=Etc/UTC
volumes:
- ./storage:/app/nocobase/storage
ports:
- '13000:80'
# init: true
# If you use an existing database service, you can skip starting mariadb
mariadb:
image: mariadb:11
environment:
MYSQL_DATABASE: nocobase
MYSQL_USER: nocobase
MYSQL_PASSWORD: nocobase
MYSQL_ROOT_PASSWORD: nocobase
restart: always
volumes:
- ./storage/db/mariadb:/var/lib/mysql
networks:
- nocobase
networks:
nocobase:
driver: bridge
services:
app:
image: nocobase/nocobase:alpha-full
restart: always
networks:
- nocobase
depends_on:
- postgres
environment:
# Application key, used to generate user tokens, etc.
# If APP_KEY is changed, old tokens will become invalid
# Can be any random string, and ensure it is not leaked
- APP_KEY=your-secret-key
# Database type, supports postgres, mysql, mariadb
- DB_DIALECT=postgres
# Database host, can be replaced with an existing database server IP
- DB_HOST=postgres
# Database port
- DB_PORT=5432
# Database name
- DB_DATABASE=nocobase
# Database user
- DB_USER=nocobase
# Database password
- DB_PASSWORD=nocobase
# Timezone, please change it to your local timezone, e.g., America/New_York
- TZ=Etc/UTC
volumes:
- ./storage:/app/nocobase/storage
ports:
- '13000:80'
# init: true
# If you use an existing database service, you can skip starting postgres
postgres:
image: postgres:16
restart: always
command: postgres -c wal_level=logical
environment:
POSTGRES_USER: nocobase
POSTGRES_DB: nocobase
POSTGRES_PASSWORD: nocobase
volumes:
- ./storage/db/postgres:/var/lib/postgresql/data
networks:
- nocobase
networks:
nocobase:
driver: bridge
services:
app:
image: nocobase/nocobase:alpha-full
restart: always
networks:
- nocobase
depends_on:
- mysql
environment:
# Application key, used to generate user tokens, etc.
# If APP_KEY is changed, old tokens will become invalid
# Can be any random string, and ensure it is not leaked
- APP_KEY=your-secret-key
# Database type, supports postgres, mysql, mariadb
- DB_DIALECT=mysql
# Database host, can be replaced with an existing database server IP
- DB_HOST=mysql
# Database port
- DB_PORT=3306
# Database name
- DB_DATABASE=nocobase
# Database user
- DB_USER=root
# Database password
- DB_PASSWORD=nocobase
# Whether to convert table and field names to snake case
- DB_UNDERSCORED=true
# Timezone, please change it to your local timezone, e.g., America/New_York
- TZ=Etc/UTC
volumes:
- ./storage:/app/nocobase/storage
ports:
- '13000:80'
# init: true
# If you use an existing database service, you can skip starting mysql
mysql:
image: mysql:8
environment:
MYSQL_DATABASE: nocobase
MYSQL_USER: nocobase
MYSQL_PASSWORD: nocobase
MYSQL_ROOT_PASSWORD: nocobase
restart: always
volumes:
- ./storage/db/mysql:/var/lib/mysql
networks:
- nocobase
networks:
nocobase:
driver: bridge
services:
app:
image: nocobase/nocobase:alpha-full
restart: always
networks:
- nocobase
depends_on:
- mariadb
environment:
# Application key, used to generate user tokens, etc.
# If APP_KEY is changed, old tokens will become invalid
# Can be any random string, and ensure it is not leaked
- APP_KEY=your-secret-key
# Database type, supports postgres, mysql, mariadb
- DB_DIALECT=mariadb
# Database host, can be replaced with an existing database server IP
- DB_HOST=mariadb
# Database port
- DB_PORT=3306
# Database name
- DB_DATABASE=nocobase
# Database user
- DB_USER=root
# Database password
- DB_PASSWORD=nocobase
# Whether to convert table and field names to snake case
- DB_UNDERSCORED=true
# Timezone, please change it to your local timezone, e.g., America/New_York
- TZ=Etc/UTC
volumes:
- ./storage:/app/nocobase/storage
ports:
- '13000:80'
# init: true
# If you use an existing database service, you can skip starting mariadb
mariadb:
image: mariadb:11
environment:
MYSQL_DATABASE: nocobase
MYSQL_USER: nocobase
MYSQL_PASSWORD: nocobase
MYSQL_ROOT_PASSWORD: nocobase
restart: always
volumes:
- ./storage/db/mariadb:/var/lib/mysql
networks:
- nocobase
3. Install and Start NocoBase
# Pull the latest image
docker compose pull
# Run in the background (installation will run automatically on the first run)
docker compose up -d
# View installation and running logs
docker compose logs -f app
app-postgres-app-1 | nginx started
app-postgres-app-1 | yarn run v1.22.15
app-postgres-app-1 | $ cross-env DOTENV_CONFIG_PATH=.env node -r dotenv/config packages/app/server/lib/index.js install -s
app-postgres-app-1 | Done in 2.72s.
app-postgres-app-1 | yarn run v1.22.15
app-postgres-app-1 | $ pm2-runtime start --node-args="-r dotenv/config" packages/app/server/lib/index.js -- start
app-postgres-app-1 | 2022-04-28T15:45:38: PM2 log: Launching in no daemon mode
app-postgres-app-1 | 2022-04-28T15:45:38: PM2 log: App [index:0] starting in -fork mode-
app-postgres-app-1 | 2022-04-28T15:45:38: PM2 log: App [index:0] online
app-postgres-app-1 | 🚀 NocoBase server running at: http://localhost:13000/
4. Log in to NocoBase
Open http://localhost:13000 in your browser. The initial account and password are admin@nocobase.com and admin123.
Account Security Notice
After logging in for the first time, please change the default password promptly to ensure system security.
5. Production deployment
If you use the built-in Nginx image, it is usually better not to expose 13000 directly to the public internet. A more common setup is to keep the container port available only on the host and let the host Nginx handle the domain, HTTPS, and reverse proxy.
Proxy the root path with Nginx
The following config proxies domain requests to http://127.0.0.1:13000/:
server {
listen 80;
server_name your_domain.com; # Replace your_domain.com with your domain
location / {
proxy_pass http://127.0.0.1:13000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $upstream_x_forwarded_proto;
proxy_set_header Host $final_host;
proxy_set_header Referer $http_referer;
proxy_set_header User-Agent $http_user_agent;
add_header Cache-Control "no-cache, no-store" always;
proxy_cache_bypass $http_upgrade;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
proxy_buffering off;
}
}
If you also want to enable HTTPS, configure 443 and the certificate on the host Nginx. The NocoBase container does not need to handle certificates separately.
The location / block in this root-path configuration also proxies /api/, /ws, and /files/. If you split static assets from application routes, make sure /files/ is still forwarded to NocoBase and is not handled as a static directory.
Subpath deployment
If you want to deploy the app under a subpath, such as https://your_domain.com/nocobase/, configure the APP_PUBLIC_PATH environment variable first:
services:
app:
image: nocobase/nocobase:latest
environment:
+ - APP_PUBLIC_PATH=/nocobase/
Keep the leading and trailing / in the path. After this is configured, the app URL becomes http://127.0.0.1:13000/nocobase/.
Then configure the host Nginx with the same subpath proxy:
server {
listen 80;
server_name your_domain.com; # Replace your_domain.com with your domain
location /nocobase/ {
proxy_pass http://127.0.0.1:13000/nocobase/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $upstream_x_forwarded_proto;
proxy_set_header Host $final_host;
proxy_set_header Referer $http_referer;
proxy_set_header User-Agent $http_user_agent;
add_header Cache-Control "no-cache, no-store" always;
proxy_cache_bypass $http_upgrade;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
proxy_buffering off;
}
# Keep compatibility with root-level file access URLs.
location ^~ /files/ {
proxy_pass http://127.0.0.1:13000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $upstream_x_forwarded_proto;
proxy_set_header Host $final_host;
proxy_set_header Referer $http_referer;
proxy_set_header User-Agent $http_user_agent;
add_header Cache-Control "no-cache, no-store" always;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
}
}
Keep these points in mind:
APP_PUBLIC_PATH and the path in proxy_pass must stay consistent. If either side misses /nocobase/, static assets and routing will usually not work correctly
/nocobase/files/ is forwarded by location /nocobase/; the compatible root-level /files/ route must be forwarded to NocoBase separately
Other options
If you do not want to use the built-in Nginx, you can also use one of these separate proxy setups: