Cómo pasar variables de entorno a un contenedor Docker con -e y --env-file

DUGLAS MORENODUGLAS MORENO 👁 20

Introducción

Cuando trabajás con contenedores Docker, una de las tareas más frecuentes es configurar el entorno de ejecución de la aplicación mediante variables de entorno. Estas variables permiten cambiar el comportamiento de un servicio sin modificar su imagen: por ejemplo, activar modo debug, definir puertos de conexión a bases de datos, o especificar claves de API.

En este artículo vas a aprender:

  • Qué son las variables de entorno y por qué son útiles en contenedores.
  • Cómo pasarlas a un contenedor usando la bandera -e (una a una).
  • Cómo pasarlas mediante un archivo con la opción --env-file.
  • Cuál es la diferencia entre ambos enfoques y cuándo conviene usar cada uno.
  • Buenas prácticas, errores comunes y cómo depurar problemas relacionados con el entorno.

El contenido está pensado para desarrolladores, DevOps y cualquier persona que ya tenga nociones básicas de Docker y quiera profundizar en la gestión de configuración. Los ejemplos incluyen comandos de terminal que podés copiar y pegar, junto con la salida esperada para que veás exactamente qué ocurre.


Variables de entorno en Docker: concepto rápido

Una variable de entorno es un par NAME=VALUE que el proceso dentro del contenedor puede leer mediante el entorno del sistema operativo. En Linux, cualquier programa puede acceder a estas variables mediante getenv() (en C), os.getenv() (en Python), process.env (en Node.js) o simplemente leyendo el entorno del shell.

Docker aísla el entorno del contenedor del host, pero provee mecanismos para inyectar variables desde el host al contenedor al momento de crear o ejecutar el contenedor. Las dos formas más usadas son:

  1. -e o --env: permite especificar una variable directamente en la línea de comandos.
  2. --env-file: indica un archivo que contiene una lista de variables, una por línea, en formato NAME=VALUE.

Ambas opciones se pueden combinar; las variables definidas con -e sobrescriben a las del mismo nombre que provienen del archivo.


Pasar variables con -e

Sintaxis básica

docker run -e VAR_NAME=value imagen:etiqueta comando

Cada -e agrega una variable. Si necesitás pasar varias, repetís la opción tantas veces como sea necesario.

Ejemplo interactivo sin Docker

Para ilustrar el efecto sin depender de Docker, podemos usar el comando env de Bash, que muestra todas las variables de entorno del proceso actual. Vamos a crear un subproceso que reciba una variable y luego la imprima.

VAR_SALUDO="Hola desde -e"
bash -c 'echo "$VAR_SALUDO"'

Salida esperada

Hola desde -e

En este ejemplo, la variable VAR_SALUDO se define en el shell padre y luego se pasa al subproceso mediante la herencia de entorno (el -c de bash recibe el entorno del proceso que lo invoca). En Docker, el mecanismo es análogo, pero la inyección se hace desde el daemon hacia el proceso del contenedor.

Ejemplo con Docker (no ejecutable en el playground)

Supongamos que tenés una imagen simples que solo imprime el valor de una variable llamada APP_MODE. Podés usar la imagen oficial alpine y el comando sh -c 'echo "APP_MODE=$APP_MODE"'.

docker run --rm -e APP_MODE=production alpine:latest sh -c 'echo "APP_MODE=$APP_MODE"'

Salida esperada

APP_MODE=production

Si la variable no está definida, el contenedor imprimirá una cadena vacía:

docker run --rm alpine:latest sh -c 'echo "APP_MODE=$APP_MODE"'

Salida esperada

APP_MODE=

Pasar varias variables con -e

docker run --rm \
  -e DB_HOST=db.example.com \
  -e DB_PORT=5432 \
  -e DB_USER=appuser \
  -e DB_PASS=secreto \
  alpine:latest sh -c 'echo "DB_HOST=$DB_HOST DB_PORT=$DB_PORT"'

Salida esperada

DB_HOST=db.example.com DB_PORT=5432

Pasar variables con --env-file

Formato del archivo

El archivo pasado a --env-file debe contener una variable por línea, en formato NAME=VALUE. Los comentarios se pueden iniciar con # y las líneas en blanco se ignoran. No se permiten espacios alrededor del signo = (aunque algunas versiones de Docker los toleran, es buena práctica evitarlos).

Ejemplo de archivo .env:

# Configuración de la aplicación
APP_ENV=staging
LOG_LEVEL=debug
MAX_WORKERS=4

# Credenciales (no subir este archivo a repositorios públicos)
DB_PASSWORD=supersecreto
API_KEY=abc123def456

Uso básico

docker run --rm --env-file .env alpine:latest sh -c 'echo "APP_ENV=$APP_ENV LOG_LEVEL=$LOG_LEVEL"'

Salida esperada

APP_ENV=staging LOG_LEVEL=debug

Creando el archivo y probándolo (executable)

Podemos demostrar el mismo efecto sin Docker usando el comando env y el builtin export de Bash para cargar el archivo en el entorno del proceso actual.

cat > demo.env <<'EOF'
FOO=bar
BAZ=qux
EOF
# Cargar el archivo en el entorno actual
export $(grep -v '^#' demo.env | xargs)
echo "FOO=$FOO, BAZ=$BAZ"

Salida esperada

FOO=bar, BAZ=qux

En este bloque, grep -v '^#' elimina las líneas de comentario, xargs las convierte en argumentos para export, y luego las variables están disponibles en la shell.

Sobrescribiendo variables con -e

Cuando usás tanto --env-file como -e, las variables definidas con -e tienen prioridad y reemplazan a las del mismo nombre que vienen del archivo.

docker run --rm \
  --env-file .env \
  -e LOG_LEVEL=error \
  alpine:latest sh -c 'echo "LOG_LEVEL=$LOG_LEVEL"'

Salida esperada

LOG_LEVEL=error

Aquí el archivo .env define LOG_LEVEL=debug, pero la opción -e LOG_LEVEL=error la sobrescribe.


Comparación entre -e y --env-file

Característica -e --env-file
Cantidad de variables Ideal para pocas (1‑5) Ideal para muchas o configuraciones complejas
Legibilidad en CLI Puede tornar el comando muy largo Mantiene la línea de comandos limpia
Facilidad de versionado Difícil de versionar Fácil de versionar con Git (añadiendo el archivo)
Sobrescritura Sobrescribe variables del archivo No puede sobrescribirse por sí mismo (necesita -e)
Portabilidad Depende de la línea de comandos El archivo puede reutilizarse en múltiples contenedores
Seguridad (manejo de secrets) Se ve en ps y en el historial También se ve si el archivo está legible; mejor usar Docker secrets o un vault

Cuándo usar cada uno

  • -e es práctico cuando necesitás probar rápidamente una configuración, pasar un único flag de depuración, o cuando la variable proviene de otro proceso (por ejemplo, salida de un comando).
  • --env-file es la opción recomendada para entornos de producción, donde tenés un conjunto estable de variables que no cambian frecuentemente. Permite mantener el docker run corto y delegar la gestión de configuración a un archivo que puede ser versionado, revisado y desplegado junto con tu código.

Buenas prácticas

  1. Nunca incluyas secrets en archivos de texto sin cifrar que vayan a repositorios públicos. Usa .gitignore para excluir .env o, mejor aún, emplea herramientas como Docker Secrets, HashiCorp Vault o AWS Secrets Manager.
  2. Documentá el formato esperado de tu archivo de entorno. Un README.env.example con variables de ejemplo (sin valores reales) ayuda a nuevos integrantes del equipo.
  3. Usá nombres en mayúsculas y guiones bajos (SERVICE_PORT, FEATURE_FLAG) para seguir la convención de variables de entorno.
  4. Validá las variables dentro del contenedor al inicio de la aplicación. Un script de entrada (entrypoint.sh) puede chequear que variables obligatorias estén definidas y fallar con un mensaje claro si falta alguna.
  5. Evité espacios alrededor del = en el archivo de entorno; aunque Docker a veces los ignora, otras herramientas (como dotenv en Node.js o python-dotenv) pueden fallar.
  6. Versioná el archivo de ejemplo, no el archivo con valores reales. Así el repositorio muestra qué variables se necesitan sin exponer información sensible.
  7. Combínalas con -e para overrides temporales (por ejemplo, activar modo debug en un entorno de staging sin modificar el archivo).
  8. Limpiá el historial de la shell después de definir variables sensibles con -e (unset VAR o history -c) para evitar que queden registradas.

Errores comunes y cómo depurarlos

1. Variable no definida dentro del contenedor

Síntomas: La aplicación falla porque espera una variable que no está.

Posibles causas:

  • Error de tipografía en el nombre (p.ej. DB_HOST vs DB-HOST).
  • El archivo --env-file no se encuentra en la ruta especificada.
  • La línea en el archivo tiene espacios extra o está comentada inadvertidamente.

Cómo diagnosticar:
Ejecutá un contenedor con un shell interactivo y viste el entorno:

docker run --rm --env-file .env -e EXTRA=test alpine:latest env

Esto imprimirá todas las variables definidas. Buscá la que esperás y verificá su valor.

2. Valor vacío o inesperado

Síntomas: La variable está definida pero contiene una cadena vacía o un valor distinto al esperado.

Posibles causas:

  • La línea en el archivo termina con un espacio después del = (p.ej. API_KEY= ).
  • Se usó comillas simples o dobles que fueron parte del valor (p.ej. API_KEY="abc123" ).
  • La variable fue sobrescrita por una -e posterior sin darse cuenta.

Cómo diagnosticar:
Revisá el archivo con cat -A .env para mostrar caracteres invisibles (como ^M para carriage return). También podés usar set -a; source .env; set +a en una shell y luego echo "$API_KEY" para ver el valor tal como lo interpreta Bash.

3. El archivo no se lee por permisos

Síntomas: Docker muestra un error como "cannot open .env: permission denied).

Posibles causas:

  • El archivo no es legible por el usuario que ejecuta el daemon Docker (generalmente root).
  • El archivo está dentro de un volumen montado con opciones ro que no permiten lectura.

Cómo diagnosticar:
Verificá los permisos con ls -l .env y, si es necesario, cambiálos con chmod 644 .env.


Conclusión

Pasar variables de entorno a un contenedor es una operación sencilla pero fundamental para configurar aplicaciones de forma flexible y segura. Las dos opciones principales de Docker, -e y --env-file, cumplen funciones complementarias:

  • Usá -e cuando necesitás pasar pocas variables, hacer pruebas rápidas o sobreescribir valores de forma puntual.
  • Recurrí a --env-file cuando tenés un conjunto amplio de configuraciones que querés mantener versionadas, legibles y reutilizables en múltiples contenedores.

Recordá siempre validar que las variables lleguen correctamente al contenedor, evitando dejar secrets en archivos sin proteger y siguiendo las buenas prácticas de nomenclatura y documentación. Con estos conocimientos podés gestionar la configuración de tus contenedores de forma profesional, reduciendo errores de despliegue y facilitando la colaboración en equipo.


Próximos pasos

Si querés profundizar, investigá sobre:

  • Docker Secrets y cómo manejar información sensible de forma más segura que con -e o --env-file.
  • Archivos de composición (docker-compose.yml) y la sintaxis env_file y environment para definir variables en servicios múltiples.
  • Integración con herramientas de orquestación como Kubernetes (ConfigMaps y Secrets) y cómo se traducen las mismas ideas a esos entornos.

Con eso tendrás una visión completa de la gestión de configuración en el mundo de los contenedores, desde el sencillo docker run hasta plataformas de producción escalables.

Comentarios (0)

Sé el primero en comentar.

Dejá tu comentario