An upgrade is simply rebuilding the image from the new source and starting it. The app runs the DB migration itself when it starts. However, the training and build images are built separately inside the cluster. If their code or build settings change, you must republish those images for the change to take effect.

1. Before you upgrade

  1. Take a backup. Restoring from a backup is safer than reverting (downgrading) a migration.

    sudo systemctl start geo-mlops-backup.service
    journalctl -u geo-mlops-backup.service -n 5    # check for "backup finished"
  2. Check whether any training is running. When the app restarts, it sends running training a stop signal, gives it time to leave a checkpoint (60 seconds by default, GEO_MLOPS_TRAINING_GRACE_PERIOD), stops it, and marks it INTERRUPTED. Training that was waiting (QUEUED) also becomes INTERRUPTED on the next start and is not resubmitted automatically. If possible, upgrade when no training is running.

2. Start the new version

Switch the source to the new version (for example, fetch the new version into /opt/geo-mlops), then run the following.

D=/opt/geo-mlops
export GIT_COMMIT=$(git -C $D rev-parse HEAD)          # optional: show the commit in System diagnostics
export BUILT_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ)

# 1) bring the whole stack in line with the file (do not name a service)
docker compose -f $D/docker-compose.yml up -d --build --remove-orphans

# 2) make sure monitoring configuration file changes are applied
docker compose -f $D/docker-compose.yml up -d --force-recreate --no-deps prometheus alertmanager

# 3) clean up old app images
docker image prune -f
  • Do not add a service name (app). up -d app only brings the app and its dependencies in line, so changes to the Prometheus and Alertmanager configuration are not applied.
  • The Prometheus and Alertmanager configurations are file mounts, so the containers must be recreated to see new files. Their data (TSDB, notification state) is in volumes and is kept.
  • Each build leaves the previous app image behind untagged, so remove them now and then with docker image prune -f.
  • If you run the app with a changed memory cap, pass the same GEO_APP_MEM_LIMIT to command 1) as well; without it, the cap returns to 16 GB (Install with Docker Compose).

3. Verify

docker inspect --format='{{.State.Health.Status}}' geo-mlops-app     # healthy
curl -s http://localhost:10000/api/v1/readyz

Then, in System diagnostics (시스템 진단), check that the backend commit in "Deployment info (배포 정보)" is the commit you just deployed, and that the migration number changed on the PostgreSQL card under "Dependencies (의존 컴포넌트)". If the frontend commit is an old one, the browser is caching the previous bundle (refresh).

DB migration

Automatic (default)

The app container's start script (start-uvicorn.sh) runs alembic upgrade head before starting the server. If the migration fails, the server does not start and the container keeps restarting, so look for the cause in the logs.

docker logs --tail=100 geo-mlops-app

Manual

You normally do not need this. To check the state or apply it separately, run it inside the app container (it uses the container's GEO_MLOPS_* settings as they are).

docker exec geo-mlops-app ./run alembic current      # revision currently applied
docker exec geo-mlops-app ./run alembic heads        # latest revision in the code
docker exec geo-mlops-app ./run alembic upgrade head # upgrade to the latest

If you changed build settings: republish images

The training runtime, dataset stager and serving builder images were built once in k3s and stored in the registry. Upgrading the app does not change images that are already built. Republish the matching image in these cases.

What changedWhat to republish
You changed the package proxy settings (GEO_MLOPS_BUILD_PACKAGE_PROXY_ENABLED, …_BUILD_PIP_INDEX_URL, …_BUILD_APT_PROXY) for the first timeServing builder — the script that builds model serving images is inside the builder image, so until you republish it, it ignores the new settings and builds as before
The training runtime (trainer) code changed in the new versionTraining runtime — the training Job runs the trainer inside the image
The stager code changed in the new version (new file types and so on)Dataset stager
  1. Open the matching tab (Training runtime (학습 런타임) / Dataset stager (데이터셋 스테이저) / Serving builder (서빙 빌더)) in Shared images (공유 이미지) in the system console. If a tenant uses its own image, do this on the screen with the same name in that tenant's admin console.
  2. Press Republish (다시 게시) on the image's row and wait until the build finishes. Thanks to the layer cache, it is fast from the second time on.
  3. Training and builds submitted after the publish finishes use the new image. Anything already in progress finishes with the old image.

Next: Backup and restore

Written for the platform as of 2026-10-02.

© MLOps Central Platform