docker-compose-variables-entorno-env

Variables de entorno en Docker Compose

  • 5 min

Las variables de entorno en Docker Compose son valores externos que parametrizan el archivo YAML sin tener que editarlo cada vez.

En el artículo anterior escribimos un docker-compose.yml que funcionaba, pero tenía un problema de seguridad y flexibilidad.

Teníamos cosas como:

environment:
  MYSQL_ROOT_PASSWORD: password123  # ❌ ¡Contraseña visible!
ports:
  - "8080:80"                       # ❌ Puerto fijo
Copied!

Si compartes este proyecto:

  1. Seguridad: Todo el mundo conoce tu contraseña de administrador.
  2. Rigidez: Si tu compañero ya usa el puerto 8080 para otra cosa, tiene que editar tu archivo docker-compose.yml para poder trabajar.

Para solucionar esto, Docker Compose se integra nativamente con archivos .env.

El código (YAML) define la estructura, pero la configuración (Variables) define el entorno.

¿Qué es una variable de entorno?

Es un valor dinámico que puede afectar al comportamiento de los procesos en un ordenador. En Docker Compose, usamos estas variables para sustituir valores dentro del archivo YAML antes de ejecutarlo.

La sintaxis para usar una variable en Compose es el estilo “Shell”: ${NOMBRE_VARIABLE}.

Transformando nuestro YAML

Vamos a arreglar nuestro desastre de seguridad. En lugar de escribir los valores a fuego, ponemos “placeholders” (marcadores de posición):

services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}  # ✅ Variable
      MYSQL_DATABASE: ${DB_NAME}           # ✅ Variable

  admin:
    image: phpmyadmin/phpmyadmin
    ports:
      - "${HOST_PORT}:80"                  # ✅ Variable
    depends_on:
      - db
Copied!

Si intentas ejecutar docker compose up ahora, Docker te avisará (o usará cadenas vacías) porque esas variables no están definidas. Necesitamos darles valor.

En ejemplos antiguos veréis muchas veces version: "3.8" al principio del archivo. En Docker Compose actual, ese campo se conserva por compatibilidad, pero ya no hace falta ponerlo.

El archivo .env

Docker Compose busca automáticamente en la misma carpeta un archivo llamado .env (oculto, empieza por punto).

Es un archivo de texto simple con formato CLAVE=VALOR. Crea un archivo .env junto a tu docker-compose.yml:

# Configuración de Base de Datos
DB_PASSWORD=SuperSecreto123!
DB_NAME=mi_aplicacion

# Configuración de Puertos
HOST_PORT=8080
Copied!

¡Listo! No tienes que configurar nada más. Cuando ejecutes docker compose up, Docker leerá el .env, sustituirá ${DB_PASSWORD} por SuperSecreto123! y levantará los contenedores.

Seguridad y Git

El archivo .env NUNCA se sube al repositorio de código (Git). Contiene tus secretos reales. Tu contraseña de producción, tus claves de API, etc.

Entonces, ¿cómo sabe mi equipo qué variables necesita crear? La práctica estándar es crear un archivo de plantilla llamado .env.example (o .env.template).

Pasos para hacerlo bien:

Crea tu .env con tus contraseñas reales.

Añade .env a tu archivo .gitignore. (Esto evita que lo subas por error).

Crea un .env.example con valores falsos o vacíos:

# .env.example
DB_PASSWORD=cambiar_esto
DB_NAME=app_db
HOST_PORT=8080
Copied!

Sube el .env.example a GitHub.

Cuando un desarrollador nuevo se descargue tu proyecto, verá el .example, hará una copia, la renombrará a .env y pondrá sus propios valores.

El archivo .env evita que escribas secretos dentro del YAML, pero no es una caja fuerte. Si alguien tiene acceso al servidor o al proyecto local, podrá leerlo. Para secretos sensibles, usad un gestor de secretos o Docker Secrets cuando tenga sentido.

Secrets en Docker Compose

Si tenéis una contraseña, un token o una clave privada, lo ideal es no tratarlo como una variable normal.

Para estos casos, Docker Compose permite declarar secrets. La idea es sencilla: en lugar de pasar el valor como variable de entorno, Docker monta un archivo dentro del contenedor y la aplicación lo lee desde ahí.

Por ejemplo, para una base de datos PostgreSQL:

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt
Copied!

En este caso, la contraseña real está en un archivo local:

./secrets/db_password.txt
Copied!

Y dentro del contenedor aparece montada como:

/run/secrets/db_password
Copied!

La imagen oficial de PostgreSQL entiende la variable POSTGRES_PASSWORD_FILE, lee la contraseña desde ese archivo y evita que tengamos que escribirla directamente en el YAML.

Esto no convierte automáticamente vuestro portátil en Fort Knox. En Docker Compose local, el archivo ./secrets/db_password.txt sigue existiendo en vuestro disco y debéis protegerlo con permisos adecuados y excluirlo de Git.

Pero es mucho mejor que dejar la contraseña escrita en docker-compose.yml o meterla dentro de la imagen.

La diferencia entre .env y env_file

Hay una confusión común en Docker Compose.

  1. Sustitución en YAML (lo que acabamos de ver): Docker lee el .env y cambia ${VAR} dentro del propio archivo docker-compose.yml. Sirve para configurar puertos, réplicas, versiones de imagen, etc.
  2. Pasar variables al contenedor (env_file): A veces tienes una aplicación (ej: Django o Laravel) que necesita 50 variables de entorno para funcionar internamente. Escribirlas todas en la sección environment: del YAML ensucia mucho. Puedes decirle a Docker: “Coge este archivo entero e inyecta todas sus variables DENTRO del contenedor”.
services:
  mi-app:
    image: mi-imagen
    env_file:
      - ./config/app.env  # Carga todo lo que haya aquí dentro del contenedor
Copied!