Skip to content

Run the server in Docker for the new lab server - #3

Merged
rcb1409 merged 1 commit into
mainfrom
deploy/docker
Sep 28, 2026
Merged

rcb1409 merged 1 commit into
mainfrom
deploy/docker

Conversation

@rcb1409

@rcb1409 rcb1409 commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator

Why

eln_server is moving from the old droplet (a systemd service on a venv, gunicorn serving TLS itself) to the new lab server, where each app runs in Docker behind the shared Caddy edge proxy. The lab's address stays the same, https://eln.ddomlab.org:5000: Caddy will send /pth/... to the PTH container and everything else to this one (separate PR in ddomlab/lab-edge).

What's added

File Purpose
Dockerfile Python 3.11 on Debian 12, the same as the old server. Adds Pango + DejaVu fonts (label PDFs), libXrender/libXext (RDKit images), tzdata. Runs as uid 1000, 1 gunicorn worker (as before, ~120–160 MB), --timeout 600 to match the timer client, access log to stdout. Healthcheck on /ping.
constraints.txt Exact package versions the offline tests and the local eLabFTW 5.6.12 run passed with, so a rebuild months from now installs the same code.
deploy/compose.yaml Builds from the checkout. Mounts config.yaml (writable, because the settings page saves to it) and secrets.yaml (read-only) from the repo root. Joins lab-net, publishes only 127.0.0.1:5001 for the timers on the same host. cap_drop: ALL, no-new-privileges, 512 MB memory cap. Won't start if either file is missing, instead of Docker silently creating empty folders.
.dockerignore Keeps secrets, config, tests and .git out of the image.
.github/workflows/docker-image.yml On PRs and pushes to main: build, run the offline tests inside the image, smoke-test /ping, / and a label PDF (asserts the text renders in DejaVu). Nothing is published.
client/install.sh Optional ELN_SERVER_URL=... to point the timers at the server at install time.
README.md Docker deploy steps.

Behavior change

Container time is America/New_York, like the eLabFTW container. The old server ran in UTC, so bottles opened after 8 PM Eastern were stamped with the next day's "Opened" date.

Tested locally (Docker Desktop, arm64)

  • Image builds. 72 offline tests pass inside it.
  • docker compose up with this compose file: healthy, runs as eln, 512 MB limit, all capabilities dropped. /ping answers on 127.0.0.1:5001 and as eln-server:5000 from another container on lab-net.
  • Label PDF renders its text in embedded DejaVu Sans Mono, the same font the old server uses. No fontconfig or gunicorn errors in the logs.
  • The settings page can write config.yaml through the mount.
  • With secrets.yaml missing, compose refuses to start ("bind source path does not exist").
  • I ran the workflow's steps locally from the YAML file. GitHub will run them on amd64 on this PR.

🤖 Generated with Claude Code

- Dockerfile: Python 3.11 on Debian 12 (as on the old server), with the
  system libraries WeasyPrint and RDKit need and DejaVu fonts for labels.
  Runs gunicorn as uid 1000 with one worker and a 600 s timeout (matching
  the timer client's wait). Lab timezone, so "Opened" dates are local.
- constraints.txt pins the package versions the tests were run against.
- deploy/compose.yaml builds from the checkout and mounts config.yaml and
  secrets.yaml (never baked into the image). Joins lab-net for the edge
  proxy and listens on 127.0.0.1:5001 for the local timer client. Refuses
  to start if either file is missing instead of creating empty folders.
- CI builds the image, runs the offline tests inside it, and smoke-tests
  /ping and a label PDF (checks the text renders in DejaVu).
- client/install.sh accepts ELN_SERVER_URL to point the timers at the
  server without editing the unit files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rcb1409
rcb1409 merged commit 76b8c92 into main Sep 28, 2026
1 check passed
@rcb1409
rcb1409 deleted the deploy/docker branch September 28, 2026 19:06
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