What did you just ship?
COPY . . copies everything in the folder: your local node_modules, log files — and your .env with the production password. Anyone who pulls the image can read it. A .dockerignore file excludes paths from the build context, and secrets are passed when the container runs, not baked in.
Exclude, then inject
cd cafe docker build -t leaky -f Dockerfile . docker run --rm leaky cat .env printf 'node_modules\n.env\n*.log\n' > .dockerignore docker build -t safe . docker run --rm safe cat .env docker run -d --name api -p 3000:3000 -e DB_HOST=db.internal -e NODE_ENV=staging safe curl -s localhost:3000/api/info
Even after you delete a secret in a later layer, it still lives in the earlier layer. Never COPY or ARG real secrets into an image.