Skip to content

fix(reaper): read RYUK_CONTAINER_IMAGE lazily so dotenv / runtime overrides work#1323

Open
dvirarad wants to merge 2 commits into
testcontainers:mainfrom
dvirarad:fix/reaper-image-lazy-env
Open

fix(reaper): read RYUK_CONTAINER_IMAGE lazily so dotenv / runtime overrides work#1323
dvirarad wants to merge 2 commits into
testcontainers:mainfrom
dvirarad:fix/reaper-image-lazy-env

Conversation

@dvirarad
Copy link
Copy Markdown

Summary

Fixes #1310.

reaper.ts exports REAPER_IMAGE as a top-level const whose initializer reads process.env.RYUK_CONTAINER_IMAGE at module load time. As @reporter pointed out, that means anything that mutates the environment after the module is imported — most commonly a dotenv.config() call in user code, or an explicit process.env.RYUK_CONTAINER_IMAGE = ... in a test setup file — is silently ignored, and the user gets the default testcontainers/ryuk:0.14.0 image regardless.

This is inconsistent with every other RYUK_* / TESTCONTAINERS_RYUK_* env var in the same file (lines 36, 93, 100, 103, 106, 109…), all of which are read lazily inside createNewReaper().

Fix

Convert REAPER_IMAGE (eager const) → getReaperImage() (lazy function), matching the existing pattern. Two files touched:

  • packages/testcontainers/src/reaper/reaper.ts — export becomes a function, call site at the bottom of createNewReaper uses getReaperImage().
  • packages/testcontainers/src/generic-container/generic-container.ts — the two === REAPER_IMAGE comparisons become === getReaperImage().

The function is cheap (one env lookup + an ImageName.fromString parse), and both comparisons happen at construction / isReaper() check time — not in a hot loop — so the lazy evaluation has no measurable overhead.

API surface

REAPER_IMAGE was an exported symbol, so this is technically a breaking change for any external consumer that imports it directly. Two notes:

  1. Public docs at docs/configuration.md and the README don't mention REAPER_IMAGE — only the env var RYUK_CONTAINER_IMAGE — so the export was effectively internal.
  2. If maintainers prefer to keep the old name for back-compat, I can re-export getReaperImage as REAPER_IMAGE via an accessor (Object.defineProperty getter on the module's namespace), but that adds complexity for a name that wasn't documented. Happy to switch on request.

Test plan

  • grep confirms no other REAPER_IMAGE references remain in the repo
  • All other env-var reads in reaper.ts already use the lazy pattern; this change brings RYUK_CONTAINER_IMAGE into alignment
  • CI green
  • (optional follow-up) regression test in reaper.test.ts using vi.stubEnv("RYUK_CONTAINER_IMAGE", "...") + vi.resetModules() — happy to add if maintainers want it in this PR

@netlify
Copy link
Copy Markdown

netlify Bot commented May 11, 2026

Deploy Preview for testcontainers-node ready!

Name Link
🔨 Latest commit 4e193cd
🔍 Latest deploy log https://app.netlify.com/projects/testcontainers-node/deploys/6a018a362d95d2000892c6a7
😎 Deploy Preview https://deploy-preview-1323--testcontainers-node.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

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.

RYUK_CONTAINER_IMAGE not responsive to .env or process.env

1 participant