Upgrading
Pull the latest image and restart. Your data and config are preserved.
Upgrading NocoDB means pulling the latest Docker image and restarting your stack. Your data (in Postgres) and your config (in nocodb/db.json and docker.env) are preserved across the upgrade.
TL;DR
If you used the Single-server install:
cd nocodb
./update.shIf you used the Quickstart or Custom infrastructure examples:
docker compose pull
docker compose up -dBoth paths cause brief downtime while the containers restart.
Before upgrading
- Back up your Postgres database. See Backups. Always back up before a major version upgrade.
- Check the Changelog for breaking changes since your current version.
- On an older bind-mount install? If your deployment keeps data in
./postgresand./nocodbinstead of Docker named volumes, do the bind-mount to named-volume migration first, or NocoDB will start with an empty database.
Step-by-step
# Move into your deployment directory (where docker-compose.yml lives)
cd nocodb
# 1. Pull the latest images
docker compose pull
# 2. Restart with the new images (NocoDB rolls forward; data is preserved)
docker compose up -d
# 3. Optional: clean up unused image layers to free disk
docker image prune -fThe installation wizard's ./update.sh does exactly these three steps.
Migrating from bind mounts to named volumes
Older NocoDB deployments stored data in host directories next to docker-compose.yml (./postgres, ./redis, ./nocodb). Current deployments use Docker-managed named volumes (postgres_data, redis_data, nocodb_data). If you pull a newer compose file, or re-run the installer, over an older bind-mount deployment, Docker mounts new, empty volumes and NocoDB starts with a fresh, empty database.
Your data is not lost: it stays in the old ./postgres and ./nocodb directories. But you must copy it into the new volumes before the first docker compose up -d on the new compose file, or NocoDB will initialize an empty database.
This is a one-time migration, and you only need it for the database and attachments. Redis holds cache and queue state, so a fresh, empty redis_data volume is fine.
Using an external (managed) Postgres? Your database lives outside Docker and is unaffected, so skip the Postgres copy below and migrate only the attachments.
1. Stop the old stack
cd nocodb # your deployment directory
docker compose down2. Switch to the new compose file, then create the empty volumes
Re-run the installer, or replace docker-compose.yml with the named-volume version, then create the volumes without starting anything:
docker compose up --no-startFind the new volume names. Compose prefixes them with your deployment directory:
docker volume ls | grep -E '_(postgres|nocodb)_data'
# e.g. nocodb_postgres_data, nocodb_nocodb_data3. Copy your data into the new volumes
A throwaway alpine container copies each old host directory into its volume. As long as the new stack uses the same Postgres major version as your old one, the raw data directory is compatible and transfers cleanly:
# Database (skip this if you use an external Postgres)
docker run --rm \
-v "$(pwd)/postgres:/from:ro" \
-v nocodb_postgres_data:/to \
alpine sh -c "cp -a /from/. /to/"
# Attachments and app data
docker run --rm \
-v "$(pwd)/nocodb:/from:ro" \
-v nocodb_nocodb_data:/to \
alpine sh -c "cp -a /from/. /to/"If your directory is not named nocodb, replace nocodb_postgres_data and nocodb_nocodb_data with the names from step 2.
4. Start and verify
docker compose up -dSign in and confirm your bases, records, and attachments are all present. Once verified, the old data directories are safe to remove:
rm -rf ./postgres ./redisKeep ./nocodb/, which still holds db.json, the database connection that the new compose mounts into the container.
A raw data-directory copy only works within the same Postgres major version. If you are also moving to a new major version, pg_dump from the old stack and restore into the new one instead. See Backups.
Pinning to a specific version
Production deployments often pin to a specific version rather than tracking latest:
# In docker-compose.yml
services:
nocodb:
image: nocodb/nocodb:2026.06.0
worker:
image: nocodb/nocodb:2026.06.0Bump the tag, run docker compose up -d, and you've upgraded to that version.
Available tags are listed on Docker Hub.