The same image should run in development, staging, and production without change. But those environments need different settings - a different database password, a different log level, a different API URL. If the image cannot change, where do those settings come from? The answer is environment variables.
A good container image is built once and stays fixed. Anything that
varies between environments is fed in from the outside at run time. The
standard channel for that is environment variables - simple KEY=value
pairs the running process can read.
This is a core principle of container design: keep configuration out of the image, and inject it when you run. The image stays generic; the environment variables make each run specific.
Official images lean on this heavily. The Postgres image reads
POSTGRES_PASSWORD to set the database password. The MySQL image reads
MYSQL_ROOT_PASSWORD. Application images read variables for their log
level, port, or connection strings. The image's documentation lists
which variables it understands.
Environment variables suit small pieces of configuration - a hostname, a port, a feature flag, a mode. They are the right tool for most settings.
They are not meant for large data, and they are a weak spot for
secrets, since anything passed as an environment variable can be read
back with docker inspect. That trade-off comes up again in this
topic's scenario. For now, the takeaway is that environment variables
are how you configure a container from the outside without touching the
image.