Skip to content

build: overhaul container build logic - #2650

Open
conorsch wants to merge 16 commits into
developfrom
conorsch/ci-containerfile-consolidation
Open

build: overhaul container build logic#2650
conorsch wants to merge 16 commits into
developfrom
conorsch/ci-containerfile-consolidation

Conversation

@conorsch

@conorsch conorsch commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

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:

  • use a single containerfile with a multi-stage build, copying assets between
  • organizes deployment build tooling under top-level ci/ directory
  • rewrites the Makefile as a justfile
  • intentional support for SELinux volume mounts, for Linux users

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.

@conorsch
conorsch force-pushed the conorsch/ci-containerfile-consolidation branch from 4bfa86b to 3c905fd Compare August 31, 2026 23:14
@conorsch
conorsch marked this pull request as ready for review August 31, 2026 23:30
@conorsch
conorsch requested review from a team as code owners August 31, 2026 23:30
conorsch and others added 15 commits August 31, 2026 21:50
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
paulschreiber force-pushed the conorsch/ci-containerfile-consolidation branch from 23991c6 to 98b3bd2 Compare September 1, 2026 03:19
@paulschreiber
paulschreiber force-pushed the conorsch/ci-containerfile-consolidation branch from 98b3bd2 to 1d98674 Compare September 1, 2026 22:19
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