The same image should generally run in dev, staging, and production — what differs is configuration, not the artifact itself (this is the same "promote one build artifact" principle covered in the CI/CD reference). The standard mechanism is environment variables injected at docker run/Compose time, not baked into the image:
docker run -e DATABASE_URL=postgres://prod-host/app -e LOG_LEVEL=warn myapp
services:
web:
image: myapp:1.4.2
env_file: .env.production # loaded at container start, not build time
Baking environment-specific values into the image with ENV in the Dockerfile means building a different image per environment — which reintroduces exactly the "am I testing what I'm shipping" problem that promoting one artifact through environments is meant to avoid (see CI/CD Pipelines Explained). Keep the image environment-agnostic; inject configuration at runtime.