Skip to content

fix(docker): make compose flow work as documented#247

Open
JereSalo wants to merge 8 commits into
OpenZeppelin:mainfrom
lambdaclass:docker-compose-fixes
Open

fix(docker): make compose flow work as documented#247
JereSalo wants to merge 8 commits into
OpenZeppelin:mainfrom
lambdaclass:docker-compose-fixes

Conversation

@JereSalo
Copy link
Copy Markdown

@JereSalo JereSalo commented May 22, 2026

Hey! At LambdaClass we are experimenting with deploying our own guardian instance and we found a few things that we thought were worth changing, mostly aimed towards improving the docker compose flow.

Fixes

  • .env was being ignored by the container, it now reaches the server (or skipped cleanly if absent)
  • Postgres compose advertised but didn't wire connection between server and postgres, now it works end-to-end (documented it in the README)
  • Clarify in .env.example that the GUARDIAN_OPERATOR_PUBLIC_KEYS_JSON variable is not read by the server but by a script that is for AWS deploy.
  • Missing POSTGRES_PASSWORD silently broke postgres later, now it fails immediately with a clear hint

Summary by CodeRabbit

  • Documentation

    • Updated environment configuration examples with clearer guidance for Docker Compose and local server deployments.
    • Revised Docker Compose setup instructions for improved Postgres integration.
  • Chores

    • Updated .gitignore to exclude temporary directory.
    • Enhanced Docker configuration for improved environment variable management.

Review Change Stack

JereSalo added 7 commits May 21, 2026 16:04
The server service had `environment:` for inline overrides but no
`env_file:` entry, so values from .env never reached the running
process inside the container. Compose only loaded .env to expand
${VAR} inside the YAML itself.

Add `env_file: [.env]` so .env remains the single source of truth
for container configuration.
docker-compose.postgres.yml only declared the postgres service,
so combining it with the main compose left the server built
without the `postgres` Cargo feature and with no DATABASE_URL
pointing at the postgres service. The "use instead" README
pointer was therefore broken: running the file alone gave users
a lonely postgres with no Guardian, and running both files
combined gave a server that silently used the filesystem
backend (DATABASE_URL reached the container but the binary had
no code to consume it).

Changes:

- docker-compose.postgres.yml: add a `server` override that
  rebuilds with GUARDIAN_SERVER_FEATURES=postgres, waits for
  the postgres healthcheck via depends_on, and sets
  DATABASE_URL using the `postgres` service hostname.
- README.md: fix the absolute path link to be relative, replace
  the "use instead" wording with the combined compose command,
  and note that --build is required to switch backend.
- .env.example: split the commented DATABASE_URL into the
  in-compose variant (host `postgres`) and the host-run variant
  (host `localhost`), and mark POSTGRES_PASSWORD as required
  for the postgres compose path.

After these changes the documented postgres flow works
end-to-end: postgres comes up healthy, the server is rebuilt
with the postgres feature, diesel migrations run on startup,
and the server reads and writes through postgres.
The /var/ directory accumulates filesystem-backend runtime state
(storage, metadata, keystore) when GUARDIAN_*_PATH is pointed at
./var/... — a common bare-metal convention to avoid writing to
the absolute /var/guardian default. Mirror the existing /keystore/
rule so this state stays out of git.
The active GUARDIAN_OPERATOR_PUBLIC_KEYS_JSON line suggested a general
configuration option, but the server code does not read this variable.
It is consumed only by scripts/aws-deploy.sh, which translates it into
a Secrets Manager secret and sets the server's
GUARDIAN_OPERATOR_PUBLIC_KEYS_SECRET_ID accordingly. For local or
docker setups the server reads GUARDIAN_OPERATOR_PUBLIC_KEYS_FILE.

Replace the misleading active line with a commented block that shows
both options and notes the docker-specific need to mount the keys
file into the container.
env_file: [.env] required the .env file to exist or compose would
fail at config/up time, even though the server has working
defaults and can boot without it. Use the `required: false` variant
so .env is loaded if present and silently ignored when absent.
This preserves the original Compose behavior of "no .env is fine"
while keeping the F1 fix (variables propagate to the container
when .env exists).

POSTGRES_PASSWORD was documented as required for the postgres
override but only commented in .env.example, so a user who forgot
to set it would see the postgres container start with an empty
password and the server fail to connect with a generic interpolation
result. Use ${POSTGRES_PASSWORD:?...} on the DATABASE_URL so compose
errors immediately with a clear remediation hint.
@JereSalo JereSalo requested a review from zeljkoX as a code owner May 22, 2026 15:17
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 73070f52-0413-4c24-9dc2-1637cf8be9b1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR enables local Docker Compose development with Postgres by adding an override-based service configuration, updating environment variable examples, and documenting the combined Docker Compose invocation for users setting up the development environment.

Changes

Docker Compose Postgres Integration

Layer / File(s) Summary
Docker Compose service wiring
docker-compose.yml, docker-compose.postgres.yml
The server service in docker-compose.yml now loads .env file optionally, and docker-compose.postgres.yml introduces a new server service with GUARDIAN_SERVER_FEATURES: postgres build arg, health-gated depends_on for Postgres, and DATABASE_URL pointing to the Postgres container.
Environment configuration and setup documentation
.env.example, README.md, .gitignore
.env.example expands DATABASE_URL documentation with Docker Compose and localhost host examples, and explains two operator public keys configuration options (JSON file or inline JSON). README.md instructs running docker compose -f docker-compose.yml -f docker-compose.postgres.yml up --build -d with POSTGRES_PASSWORD set in .env. .gitignore adds /var/ directory to ignore patterns.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

🐰 A rabbit hops through Docker files with glee,
Composing Postgres for the dev to see,
With .env guides and override play,
Local databases bloom the proper way! 🌱

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(docker): make compose flow work as documented' directly addresses the main objective of this PR—ensuring the Docker Compose workflow functions as documented and resolving deployment issues.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

Thank you for your contribution to guardian. Before being able to integrate those changes, we would like you to sign our Contributor License Agreement. You can sign the CLA by just posting a Pull Request Comment with the sentence below. Thanks.


I confirm that I have read and hereby agree to the OpenZeppelin Contributor License Agreement


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the Docker Compose developer workflow so it works end-to-end as documented, particularly around .env propagation and the Postgres-backed setup.

Changes:

  • Pass .env variables into the server container in the default Compose flow (while allowing .env to be absent).
  • Wire up a Postgres-backed Compose flow by overriding server build features and setting DATABASE_URL, and document the override usage.
  • Clarify .env.example guidance and ignore a local var/ directory.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Updates Compose docs to describe using the Postgres override file.
docker-compose.yml Adds optional .env injection into the server container.
docker-compose.postgres.yml Adds server overrides for Postgres feature + DATABASE_URL and waits for Postgres health.
.gitignore Ignores var/ directory.
.env.example Clarifies Postgres connection examples and operator allowlist variable usage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +5 to +7
build:
args:
GUARDIAN_SERVER_FEATURES: postgres
Comment thread docker-compose.yml
Comment on lines +17 to +19
env_file:
- path: .env
required: false
@zeljkoX
Copy link
Copy Markdown
Collaborator

zeljkoX commented May 25, 2026

@JereSalo

Thanks a lot for your contribution!

It looks good!

Before merging maybe to make docker-compose.postgres.yml independent as per #247 (comment).

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.28%. Comparing base (aba731f) to head (6071beb).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #247      +/-   ##
==========================================
+ Coverage   73.18%   75.28%   +2.09%     
==========================================
  Files         122      131       +9     
  Lines       21565    23314    +1749     
==========================================
+ Hits        15782    17551    +1769     
+ Misses       5783     5763      -20     

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update aba731f...6071beb. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

docker-compose.postgres.yml now uses `include:` to pull in
docker-compose.yml, so the postgres flow can start with a single
`-f docker-compose.postgres.yml` instead of layering two files.
The base server config and top-level volumes are inherited; the
postgres-specific bits layer on top.

Verified `docker compose config` output is byte-identical to the
previous two-file override approach.
@JereSalo
Copy link
Copy Markdown
Author

@JereSalo

Thanks a lot for your contribution!

It looks good!

Before merging maybe to make docker-compose.postgres.yml independent as per #247 (comment).

Hi! Implementing the copilot suggestion as-is won't make it fully independent because docker-compose.postgres.yml would lack the other configuration variables that are already defined in docker-compose.yml.

I experimented with many alternatives to find the best in order to make it independent and I pivoted to use the include feature, which I think is a cleaner approach than the one I previously implemented. The change is in cc76874


Info about the alternatives I analyzed and my thoughts on each (not a necessary read)

  1. Full Duplication: They are fully independent but we have to maintain both files. Not good.
  2. Override: Clean but we have to run it with two -f flags, so it affects the CLI experience.
  3. Using extends: This is a middle ground, though it still depends on the other file, we can run it in the CLI with just one -f flag instead of two as in the case of the override while not duplicating almost anything of the original file. The only detail with this is that we need to define the same volumes in both files because the extends just works for services.
    Example:
...
  extends:
    file: docker-compose.yml
    service: server
...

volumes:
  guardian-postgres: # Specific from this file
  # Duplicated from the other file
  guardian-storage:
  guardian-metadata:
  guardian-keystore:
  1. Using include: The best of all methods, it offers the a lot of independence without full duplication of the docker-compose.yml file. And also the code change is minimal. We just need to add this to the top of the file:
include:
  - docker-compose.yml

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants