build: overhaul container build logic - #2650
Open
conorsch wants to merge 16 commits into
Open
Conversation
conorsch
force-pushed
the
conorsch/ci-containerfile-consolidation
branch
from
August 31, 2026 23:14
4bfa86b to
3c905fd
Compare
conorsch
marked this pull request as ready for review
August 31, 2026 23:30
Uses a multi-stage build for the container artifacts, and targets
individual stages for the various contexts: dev and prod Django, the
dev webpack watcher, and the dev and prod chart pregenerator.
This is basically a mechanical port of the same changes in the other web
repos, but in PFT, there's a multi-container setup for chart pregeneration.
Specific changes bundled into this commit:
* rename devops/ -> ci/, splitting containers from scripts
* rename quay.io -> ghcr.io container registries throughout
* build prod Django at USERID=1000 and chartgen at 1001 everywhere,
keeping dev and prod artifacts the same
* create the gcorn account unconditionally, since prod addresses it by
name in COPY --chown and USER; a conditional useradd only defers the
failure to those lines
* generate version info in a discarded stage with .git bind-mounted,
so the git history never lands in an image layer. The report loses
its `pip freeze` section, which that stage cannot produce
* stop shipping node_modules/ and .git/ in the prod Django image; the
old find/-prune only skipped the chown, not the COPY
* drop the gulp-cli install, which had no gulp to run
* ensure the OCI labels land in the final image artifacts
* correct a few copy/paste hold-overs that referenced "fpf" or "freedompress"
* add some healthcheck behavior for stable compose startups
* strives to add podman support
* `.dockerignore`: `node_modules` -> `**/node_modules`, so the chartgen
stage no longer copies chart_pregenerator/node_modules
Here we adhere to a best practice for container image building: rather than omitting specific filepaths, we by default omit all files in the repo, and selectively permit certain paths. The goal is to control tightly what makes it into the built artifact, ensuring that creds and other miscellanea don't pollute prod builds. The previous denylist was both stale and too narrow. It named `client/build/` and `.versioninfo`, neither of which exists, while letting `.coverage`, `coverage.xml`, `coverage/`, `htmlcov/`, `import.db`, `db-snapshots/`, `.ruff_cache/` and stray notes at the repo root into the prod build context, and from there into the published image. Note that `build` must be permitted: as well as being webpack's output directory it is an INSTALLED_APP, a namespace package that Django will not start without. Its bundle subdirectory is re-excluded so that stale dev bundles from a host `npm run start` cannot survive into the prod asset build, where collectstatic's manifest rewriting would trip over them. `STATISTICS.rst` is permitted because statistics/views.py reads it at request time, and `chart_pregenerator` because the `chartgen` stage copies it wholesale -- minus its own build/, coverage/ and node_modules.
Ports the Makefile to a justfile, in line with the other web repos. Standardize the target names somewhat, for consistency, e.g. * dev-tests -> test * dev-jest-tests -> test-js * dev-import-db -> import-db * dev-save-db -> save-db Where possible, we execute tests without the full compose stack. Touches up the dev/db paths, which had a few copy/paste holdovers from historical ports of tooling from other FPF web repos. Dead molecule references are dropped from .gitignore and pyproject.toml.
Opts into the hadolint checks, with a custom config, in CI. There's a lockfile lint checker in CI now, too, but that'll require a backend setting on Github, to set it as a required check. `ruff format --check` was already in use here, so no lint diffs are bundled into this commit: it was already clean.
When SELinux is set to enforcing, we need the "z" flag on volume mounts to ensure that the mounted files are labeled correctly. Refs freedomofpress/securedrop.org#1581
Updates the hadolint config to silence a warning about non-numeric uid handling. We're pretty defensive about this already; specifically, we use runAsUser=1000 in the k8s manifests already, which covers us here even if we mess up on the containerfile spec. Mechanically ported from [0]. [0] freedomofpress/freedom.press#3276'
paulschreiber
force-pushed
the
conorsch/ci-containerfile-consolidation
branch
from
September 1, 2026 03:19
23991c6 to
98b3bd2
Compare
paulschreiber
force-pushed
the
conorsch/ci-containerfile-consolidation
branch
from
September 1, 2026 22:19
98b3bd2 to
1d98674
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR attempts to standardize the container build logic for this repo, matching the pattern already approved and merged in:
Specifically, the changes are:
ci/directoryMakefileas ajustfile✨The containerfile refactor leaves the pip-tools usage in-place. We'll circle back on the Python package management story in the near future.
Related work
Testing and review
Please make sure the local compose setup works for you. Make sure you can run the operations you normally do, and report anything that's broken or surprising.
As with the other PRs, the commits are discrete enough to drop any individual pieces if anything's objectionable.