Skip to content

Update#

You are here

Step 4 of the Production deployment (Podman) guide, after Ontop. This page deploys a new release. Next: day-to-day Maintenance & troubleshooting.

Today: build the images locally#

The OEP-specific images (application and ontop) are not published to a registry yet, so updating means rebuilding them on the host from the checked-out source. The postgres, fuseki and lookup images are pulled and rarely change.

# 1. Get the release you want to deploy
git fetch --all --tags
git checkout <tag-or-branch>
git pull

# 2. Keep the running image under a second name, to roll back to
podman tag ghcr.io/openenergyplatform/oeplatform-production:latest \
  ghcr.io/openenergyplatform/oeplatform-production:previous

#    Rebuild the application image (runs collectstatic + asset compression)
#    Build under the ghcr name the unit references (see Install) — no re-tag needed.
podman build -t ghcr.io/openenergyplatform/oeplatform-production:latest -f podman/Dockerfile .

# 3. Rebuild ontop only if its ontology/mapping/driver changed
podman build -t ghcr.io/openenergyplatform/oeplatform-ontop:latest -f docker/Dockerfile.ontop docker/

# 4. Restart the app (postgres and fuseki keep running)
systemctl --user restart oep-oeplatform
# restart ontop too if you rebuilt it:
systemctl --user restart oep-ontop

What happens on restart#

Release steps run inside the container automatically on start — you do not run them by hand:

Manual (legacy bare-metal) step Where it runs now
npm ci / npm run build in the image build (Dockerfile)
pip install -r requirements.txt in the image build (Dockerfile)
collectstatic / compress in the image build (Dockerfile)
manage.py migrate on container start (entrypoint.sh)
alembic upgrade head on container start (entrypoint.sh)
touch wsgi.py / reload Apache container restart

Database migrations run automatically

Django + Alembic migrations execute on app-container start. Before deploying a release that includes migrations, make sure you have a current database backup (see Maintenance).

Roll back#

If the new image does not come up, put the previous one back under the name the unit starts and restart:

podman tag ghcr.io/openenergyplatform/oeplatform-production:previous \
  ghcr.io/openenergyplatform/oeplatform-production:latest
systemctl --user restart oep-oeplatform

This returns the code only. Migrations the new image already applied stay in the database; undoing them needs the backup taken before the update.

Once: move Fuseki's data into its volume#

Earlier versions of oep-fuseki.container mounted the fuseki-databases volume at /home/fuseki/databases, a path Fuseki never uses. The image keeps everything under /fuseki (datasets, dataset registry, shiro.ini), which was therefore an anonymous volume, and the unit removes that with the container. Any restart of oep-fuseki, or a reboot, deleted the OEKG. The unit now mounts the volume at /fuseki.

Copy before you restart

On a host installed with the old unit, the OEKG exists only in the running container. Re-running install.sh changes nothing yet, but the next restart of oep-fuseki starts from an empty store. Do the copy below first.

# 1. Count the triples, to compare afterwards
curl -s http://localhost:3030/ds/query -H 'Accept: text/csv' \
  --data-urlencode 'query=SELECT (COUNT(*) AS ?n) {{?s ?p ?o} UNION {GRAPH ?g {?s ?p ?o}}}'

# 2. Stop the app, the only writer, so the copy is consistent
systemctl --user stop oep-oeplatform

# 3. Copy /fuseki from the running container into the named volume.
#    No --rm: it would try to remove the volumes taken over from `fuseki`.
podman run --name fuseki-copy --user root --volumes-from fuseki \
  -v systemd-fuseki-databases:/new --entrypoint sh \
  docker.io/stain/jena-fuseki:5.1.0 \
  -c 'cp -a /fuseki/. /new/ && find /new -name tdb.lock -delete'
podman rm fuseki-copy

# 4. Install the new unit and restart onto the volume
bash podman/quadlets/install.sh
systemctl --user restart oep-fuseki
systemctl --user start oep-oeplatform

Then repeat the count from step 1: it must be the same, and journalctl --user -u oep-fuseki must not show Initializing Apache Jena Fuseki for this start. podman inspect fuseki --format '{{range .Mounts}}{{.Name}} {{end}}' lists only systemd-fuseki-databases.

The admin password lives in the volume

The image writes ADMIN_PASSWORD into /fuseki/shiro.ini on the first start only. With /fuseki kept, a later change of the variable has no effect; change shiro.ini in the volume instead.

Forthcoming: pull published images#

Once a tagged release (v*) publishes the application and ontop images to the registry, the update flow becomes a pull instead of a local build. The published image is self-contained, so you do not need the application source (no git pull) just to get a new image:

# (forthcoming — not yet available)
podman pull ghcr.io/openenergyplatform/oeplatform-production:latest
podman pull ghcr.io/openenergyplatform/oeplatform-ontop:latest
systemctl --user restart oep-oeplatform oep-ontop

When do you still need git pull?

Only when the deployment config in the repo changed — the quadlet unit files, install.sh, oep.env.example, or the nginx / lookup service configs. Those live in the repo, not in the image. If a release touches them, git pull and re-run bash podman/quadlets/install.sh (and install-nginx.sh if the nginx config changed) before restarting. If only the application changed, the two podman pulls above are enough.

Not enabled yet

Until image publishing lands, use the local build flow above — which does require git pull, because there the image is built from the checkout. The image names shown here are the intended published names; building locally under the same names keeps the switch seamless later.


Next → Maintenance & troubleshooting — logs, restarts, resets, and common failure modes.