feat(container): Add PostgreSQL image - #241
Merged
Merged
Conversation
Add a digest-pinned, non-root ExtendDB image built only with the PostgreSQL backend while keeping the PostgreSQL server external. Provide a hardened local Compose stack with separate volume-init, bootstrap, and serving roles. Exercise build and prebuilt artifacts, API persistence, graceful shutdown, and migration bootstrap behavior. Generate reproducible Rust dependency notices and embed immutable source metadata. Accept bootstrap secrets from environment variables so they do not appear in process arguments.
robinnsc
marked this pull request as ready for review
August 7, 2026 08:52
robinnsc
requested review from
LeeroyHannigan,
amrith,
c33howard,
jcshepherd,
pdf-amzn and
yesyayen
as code owners
August 7, 2026 08:52
jcshepherd
reviewed
Aug 7, 2026
| pg_user: String, | ||
|
|
||
| /// PostgreSQL admin password | ||
| /// PostgreSQL admin password. |
Collaborator
There was a problem hiding this comment.
I wonder if we should pause here and retire the "PG"-isms: they're just going to get more confusing. Would it be easier to do that now, maybe in a separate PR, and then revise this one? Like EXTENDDB_DB_PASSWORD or some such. I think the PR/RFC for TiDB had some work on this too.
jcshepherd
reviewed
Aug 7, 2026
| "EXTENDDB_PG_PASSWORD", | ||
| ) | ||
| .unwrap(); | ||
| assert_eq!(args.len(), 3); |
Collaborator
There was a problem hiding this comment.
Nit: More convincing if this also validated the actual args.
jcshepherd
approved these changes
Aug 7, 2026
jcshepherd
left a comment
Collaborator
There was a problem hiding this comment.
A couple comments below, but on reflection I think addressing the "PG" smell should be done separately, as it'll touch more than just one env variable.
8 tasks
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.
What
Add a production-shaped, registry-neutral container image for ExtendDB using the PostgreSQL storage backend.
Container image
10001:10001.LICENSE, projectNOTICE, and generated software licensenotices.
dpkgmetadata and/usr/share/doc/*/copyrightfiles.tini.extenddb healthcheckfor container liveness.directory.
The normal image startup does not initialize or migrate a database.
Local Compose environment
Add a local-development-only Compose stack with four separate roles:
The serving container:
The volume initializer runs as root with only CAP_CHOWN. The bootstrap container receives the elevated credentials only for the one-time lifecycle operation.
Non-argv bootstrap secrets
Add environment-based alternatives for bootstrap database passwords:
EXTENDDB_PG_PASSWORD
EXTENDDB_APP_PASSWORD
These are supported by:
Existing --pg-pass and --extenddb-pass arguments remain supported. Explicit CLI arguments take precedence.
Environment-sourced values are appended only to the in-process argument vector used by the storage bootstrapper. They do not appear in the operating system’s process command line.
Build metadata
Allow container builds to inject deterministic metadata through:
EXTENDDB_GIT_HASH
EXTENDDB_BUILD_TIME
Local non-container builds retain the existing Git and current-time fallbacks.
Software license notices
Add reproducible license-notice generation using pinned cargo-about 0.9.0:
devtools/generate-software-license-notices
devtools/generate-software-license-notices --check
The generated SOFTWARE-LICENSE-NOTICES.html represents the locked PostgreSQL build graph for both supported GNU/Linux architectures:
Build dependencies are included, development dependencies are excluded, and generation fails on unresolved license metadata. The artifact currently covers 293 selected Rust packages and 28 license identifiers.
Debian package attribution remains in /usr/share/doc/*/copyright with the dpkg database intact.
Smoke testing
Add ci/smoke-test-container.sh, which supports two modes:
The smoke test:
Uses a unique Compose project, image tag, and Docker-allocated loopback port.
Confirms volume-init, bootstrap, and serving roles use the same image ID.
Verifies UID/GID, read-only root, capabilities, and
no-new-privileges.
Confirms no PostgreSQL server exists in the image.
Confirms no setuid/setgid executable remains.
Verifies configuration and TLS private-key modes.
Compares OCI version, revision, and creation labels with embedded binary
metadata.
Runs extenddb verify.
Creates an account, user, policy, and access key.
Executes CreateTable, PutItem, and GetItem through the AWS CLI.
Restarts the serving container and verifies persistence.
Sends SIGTERM and requires a clean exit.
Recreates the Compose stack without deleting volumes.
Confirms the existing-config migration path runs successfully.
Verifies data remains available after migration.
Removes disposable containers, networks, volumes, images, and credentials.
Documentation
Document:
Registry provisioning, release-version selection, SBOM/scanning/signing, and publishing automation are outside this PR.
Why
ExtendDB needs a tested container artifact before publishing an image to a public registry.
The image intentionally contains only ExtendDB. PostgreSQL remains separate so its backup, patching, scaling, upgrade, and availability lifecycle can be managed independently.
The container must also support production orchestrator expectations:
This PR is based directly on main and does not include PR235. The container implementation can be reviewed independently because Compose and the documented production lifecycle run exactly one initialization or migration operation. PR235 remains a prerequisite for the first official public release because it adds migration serialization as defense in depth.
Testing done
Rust validation
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test --workspace
cargo build --locked --release
-p extenddb
--no-default-features
--features postgres
Script and configuration validation
bash -n
ci/smoke-test-container.sh
devtools/generate-software-license-notices
shellcheck
ci/smoke-test-container.sh
devtools/generate-software-license-notices
devtools/generate-software-license-notices --check
docker compose -f docker-compose.yml config --quiet
hadolint Dockerfile
git diff --check
Container smoke testing
The complete build-mode and prebuilt-image smoke tests passed, including:
Multi-architecture validation
A local OCI build completed successfully for:
The resulting index contained both image manifests and per-platform provenance
attestations.
The renamed runtime notice artifact was also validated in a built image:
/usr/share/doc/extenddb/SOFTWARE-LICENSE-NOTICES.html
It is installed read-only at mode 0444; the previous filename is absent.
Checklist
ADR / RFC: n/a — this adds packaging, local deployment, and release-support
artifacts without changing the service wire protocol or storage architecture.
Breaking changes
None.
The existing password CLI arguments remain supported. The new environment
variables provide a safer alternative for one-time bootstrap jobs.
By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache License 2.0 and I agree to the Developer Certificate of
Origin (DCO). See CONTRIBUTING.md (../CONTRIBUTING.md) for details.