fix: pass .env variables through to containers in compose.example.yml#2811
fix: pass .env variables through to containers in compose.example.yml#2811RealDiligent wants to merge 1 commit into
Conversation
The example Compose file declared container env only via the x-rails-env
anchor, which lists just DB/Redis/SSL/OpenAI vars, and set no env_file.
Docker Compose auto-reads .env for ${VAR} interpolation in the compose
file itself, but that does NOT inject those values into the containers
unless they are referenced. So documented self-hosting variables placed
in .env — ONBOARDING_STATE, APP_DOMAIN, SMTP_*, EMAIL_SENDER, etc. —
never reached the app: onboarding stayed open and email was broken.
Add env_file: .env (with required: false, so the out-of-the-box run with
no .env still works) to the web and worker services. The explicit
environment anchor still takes precedence, so container-critical settings
(DB_HOST, REDIS_URL, SELF_HOSTED) remain authoritative, and only the
user's own .env values are injected — absent vars stay truly unset so the
app's ENV fallbacks keep working.
Fixes we-promise#2773
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe Compose example adds optional ChangesCompose environment loading
Estimated code review effort: 1 (Trivial) | ~3 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3b581bf42c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| # SMTP_*, etc.). The explicit `environment` values below take precedence | ||
| # over .env, so container-critical settings (DB_HOST, REDIS_URL, ...) stay | ||
| # correct. `required: false` keeps this working when no .env file exists. | ||
| env_file: |
There was a problem hiding this comment.
Keep
.env from overriding the fixed container port
When a self-hoster changes the documented PORT value in .env, this env_file also injects that value into web, so Puma listens on it (config/puma.rb:44) while Compose still publishes ${PORT}:3000 (compose.example.yml:72). For example, PORT=3001 maps host port 3001 to an unused container port 3000, making the UI unreachable. The Compose short port syntax is [HOST:]CONTAINER[/PROTOCOL]; pin PORT: 3000 in the explicit container environment or change the container-side mapping accordingly.
Useful? React with 👍 / 👎.
| # over .env, so container-critical settings (DB_HOST, REDIS_URL, ...) stay | ||
| # correct. `required: false` keeps this working when no .env file exists. | ||
| env_file: | ||
| - path: .env |
There was a problem hiding this comment.
Preserve defaults for blank entries in the sample environment
When users follow docs/hosting/docker.md:61-96 and leave optional entries from .env.example untouched, this imports values such as PRODUCT_NAME=, BRAND_NAME=, and EMAIL_SENDER= as empty strings rather than leaving them unset; the Compose env_file syntax specifies that VAR= becomes an empty string. Consequently, the ENV.fetch defaults in config/initializers/brand.rb:2-3 and app/mailers/application_mailer.rb:3 are bypassed, producing blank product branding and potentially a blank default sender. Comment out optional blank entries in the distributed sample or normalize them before relying on ENV.fetch defaults.
Useful? React with 👍 / 👎.
jjmata
left a comment
There was a problem hiding this comment.
Correct diagnosis of the Compose behavior: .env interpolates ${VAR} references inside the compose file itself, but that's separate from injecting those vars into the container's environment, which needs env_file. Using required: false preserves the "runs with zero configuration" promise, and the explanation of why environment: still wins over env_file (so DB_HOST/REDIS_URL/SELF_HOSTED can't be clobbered by a stray .env value) is accurate and worth having as an inline comment for future readers, which it is.
Good call also explicitly rejecting the "enumerate each var as KEY: ${KEY:-}" alternative — that would force empty-string instead of truly-unset for absent vars, which would break ENV.fetch(key, default)-style fallbacks. Small, config-only, low risk. No concerns; compose.example.ai.yml having the same gap is correctly called out as a possible follow-up rather than scope creep here.
Generated by Claude Code
Fixes #2773
Problem
Self-hosters following the documented setup put variables like
ONBOARDING_STATE,APP_DOMAIN,SMTP_*, andEMAIL_SENDERin their.env, but the app never sees them — onboarding stays open and email doesn't work.printenvinside the container shows only the handful of variables hardcoded in the compose file. Same root cause reported earlier in #2489 (APP_DOMAIN + SMTP).Root cause
compose.example.ymldeclares container environment only via thex-rails-envanchor, which lists just DB / Redis / SSL / OpenAI variables, and sets noenv_file.Docker Compose automatically reads a
.envfile for${VAR}interpolation inside the compose file, but that does not inject those values into the container's environment unless they're referenced somewhere. Since the documented self-hosting variables aren't in the anchor, they're silently dropped.Fix
Add
env_fileto thewebandworkerservices so the user's.envis passed through to the containers:required: falsekeeps the "runs without any configuration" promise (docsdocker.mdline 54) — the out-of-the-box run with no.envstill works.environment:anchor takes precedence overenv_filein Docker Compose, so container-critical settings (DB_HOST: db,REDIS_URL,SELF_HOSTED) remain authoritative and can't be clobbered by a stray.envvalue.env_fileinjects only the variables the user actually set, so absent variables stay truly unset and the app'sENV[...].presence/ENV.fetch(..., default)fallbacks keep working (verified forONBOARDING_STATEinapp/models/setting.rbandAPP_DOMAINinconfig/environments/production.rb).This resolves all documented self-hosting variables at once, not just the handful in the report.
Why not enumerate vars in the anchor instead
Listing each variable as
KEY: ${KEY:-}would force an empty string for every unset variable, which differs from "unset" and can defeatENV.fetch(key, default)for enum-style vars (e.g. provider selection).env_fileavoids that footgun by only passing what's present.Compatibility
The
required: falselong form needs Docker Compose ≥ 2.24 (Jan 2024); the setup guide already uses thedocker composev2 CLI throughout. Happy to fall back to enumerating specific variables in the anchor if the team prefers to support older Compose.Validation
environmentprecedence +env_filebehavior confirmed against the Docker Compose spec.Pull RequestCI on a fork — all jobs green (the change is config-only, no Ruby impact).Risk / scope
compose.example.ai.ymlhas the same pattern; happy to apply the same fix there in a follow-up if desired.🤖 Generated with Claude Code
Summary by CodeRabbit
.envfile support for web and worker services..env..envfile is present.