Skip to content

Feature/container systemd service - #129

Open
Louwrensth wants to merge 11 commits into
iterorganization:developfrom
Louwrensth:feature/container-systemd-service
Open

Louwrensth wants to merge 11 commits into
iterorganization:developfrom
Louwrensth:feature/container-systemd-service

Conversation

@Louwrensth

@Louwrensth Louwrensth commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Multi-stage, hardened container image (dff1797, 54cfabe, 2076fbb, f8f05d9, 0e43e0f, c2cbe1f, 8c4adb9) — Rewrites the Dockerfile as a cached multi-stage build producing a minimal, non-root runtime image served by Gunicorn.

systemd service deployment (30c4d6e, f71c379, e198a38, 962323b, 88b48f2) — Adds a Makefile, systemd unit, env example and compose override to install and run the stack as a privileged systemd service from /opt/simdb-server.

Shared version derivation (8ba1290, 4edd539) — Adds docker/version.sh, used by the Makefile, CI and simdb-instance, so build, tag and reported versions stay consistent.

GHCR image build and publish workflow (d01caa8, 96da38e) — Publishes versioned :develop/:latest images to GHCR and restricts PyPI publishing to the privileged repository.

Docker Compose stack rework (3f9597b, 39e1c36, 8c4adb9, 0e43e0f, 88b48f2) — Adds image tags and build args, tightens the postgres healthcheck, pins base images and fixes the Alpine locale initdb issue.

Gunicorn production server (b687b99, cd4970a, 0e43e0f, 85be298) — Introduces an env-configurable Gunicorn config with stdout logging and makes it the container entrypoint.

Removal of legacy init/nginx assets (cc9b189, 220bbb9, f888889, f3b46a5, 4475eb6, 27e82ac) — Deletes the SysV init script, packaged nginx configs, redundant scripts and the multi-Python compose file, moving nginx assets under docker/.

Deployment documentation rewrite (962323b, 23a0424, 220bbb9) — Rewrites the install, nginx/gunicorn, SSL and Docker guides for the new prefix-based deployment and systemd workflow.

Dependency and config cleanup (f613436, 51cad9a, ae5523c, f0145b5, 0e43e0f) — Drops unused flask-mail, adds gunicorn, and adds a caching section to config/simdb.cfg.

@Louwrensth
Louwrensth force-pushed the feature/container-systemd-service branch 2 times, most recently from b1095ac to dd2f1b2 Compare September 24, 2026 15:51
@Louwrensth
Louwrensth force-pushed the feature/container-systemd-service branch from 922af0d to 23a0424 Compare October 1, 2026 16:11
@Louwrensth Louwrensth changed the title [WIP] Feature/container systemd service Feature/container systemd service Oct 6, 2026
@Louwrensth
Louwrensth marked this pull request as ready for review October 6, 2026 18:31
@Louwrensth Louwrensth self-assigned this Oct 7, 2026
@Louwrensth
Louwrensth force-pushed the feature/container-systemd-service branch 2 times, most recently from 4aa6485 to bf78d02 Compare October 13, 2026 20:58
Comment thread docker-compose.yml
context: .
args:
APP_VERSION: ${APP_VERSION:-0.0.0}
image: ${SIMDB_IMAGE:-simdb-server}:${SIMDB_TAG:-local}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, is image available all the time locally? or other services can also try to pull if not available?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the default, docker compose will build it locally if not present.

simdb-instance has docker-compose-dev.yml for alternative image: simdb-dev:${SIMDB_TAG:-local}

The systemd unit' env will modify the SIMDB_IMAGE SIMDB_TAG to point to a built image / tag on ghcr.io.

Other users can use the same env vars to do so.

Once production ready, we can (think if we would want to) change the default to point to such image/tag on ghcr.io. Is that what you meant?

What other services are you thinking about?

Comment thread Makefile
read ans; case "$$ans" in [yY]*) ;; *) echo "aborted"; exit 1;; esac
-rm -f "$(DESTDIR)$(systemd_unitdir)/$(SIMDB_PROJECT_NAME).service"
-rm -rf "$(DESTDIR)$(package_etcdir)"
-rm -rf "$(DESTDIR)$(package_optdir)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will delete uploaded data and not sure should we guard that properly. Or ask user if user needs to delete in two steps..

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're absolutely right.

On the other hand:

  • uninstall is not a typical target for Makefile anyway. I wanted it for making sure it is all gone while re-testing installing.
  • upload_folder is destined to not be /opt/simdb-server/upload_folder but mounted outside /opt entirely

So I think less is more. I can remove the make target altogether. Or reduce it to a message with instructions for the admin to delete manually.

Agree?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with this -> reduce it to a message with instructions for the admin to delete manually

Comment thread config/simdb.cfg Outdated
secret_key = CHANGE_ME

[cache]
type = SimpleCache

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious about why SimpleCache and not not shared redis cache as we have Gunicorn setup now?
https://www.geeksforgeeks.org/system-design/redis-cache/

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes totally, RedisCache makes more sense with multiple workers that gunicorn launches. At the time, I didn't want to think about making that work then. But I suppose it is easy enough. Thanks. :)

@prasad-sawantdesai prasad-sawantdesai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Can we have flow of setting up the server document inside docs? We already have all the pieces ready in the documentation.

@Louwrensth

Copy link
Copy Markdown
Contributor Author

Thanks. Can we have flow of setting up the server document inside docs? We already have all the pieces ready in the documentation.

Yes. I'll review that for sure.

I'm working on streamlining some pesky uid/gid issue first.

- pin base image tags
- uv sync --no-build for dependencies
  So that it fails quickly rather than try to (slowly) build a dependency when the built package proves unavailable. This was the case for flask-mail~=0.9.1 at python 3.12.

- docker-compose: only need to build image once
  Add `image` spec so docker compose builds it only once instead four times for migrations, web, worker, and beat.
  remove docker-compose-pyver.yml

- gunicorn: expose access and error logs to stdout

- add gunicorn.conf.py without mounting it
  it is baked into the image and reads everything tunable from the GUNICORN_* environment.

- .gitignore: add common data folders
- .gitignore, .dockerignore: cleanup

- scripts/simdb{,_server}: remove redundant scripts
  uv already installs the ones defined in pyproject.toml, under [project.scripts]

- simdb instance: move nginx.dev.conf to docker/
migrations service should wait for a healthy postgres.
postgres should not need `locale` command, it doesn't exist on alpine.
- multi-stage build + server
  build: with all compile dependencies.
  server: with only execute capabilities and OCI labels.
  add validation stage.

- non-root user
  Celery was complaining loudly.

- uv sync --no-dev only,
  UV_NO_DEV environment makes uv run throw warning "has no effect".

- setuptools tweak
  SETUPTOOLS_SCM_PRETEND_VERSION_FOR_IMAS_SIMDB
- add docker compose layer
- add system unit service and env files
- add Makefile for easy deployment
- add to docs
- use docker/version.sh
- simplify variables
- simplify gha workflow to reduce artifact juggling
- simple ci triggers for image building tagging and publishing
- consistent image addresses
- consistent git/image/package version tags
- remove docker test target to verify code
- documentation errata
Add docker/entrypoint/boot-nonroot.sh instead of fixed USER directive in Dockerfile. It will setup the correct user matching APP_UID and APP_GID so that the data directory can be written to without needing to rebuild the image.
@Louwrensth
Louwrensth force-pushed the feature/container-systemd-service branch from f7cfa31 to 4057971 Compare October 16, 2026 18:20

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants