2.4 · Configuración : ENV, ARG y archivos .env

Nivel 2 · Dockerfile y build

2.4Configuración : ENV, ARG y archivos .env

Objetivo: Hacer configurable una imagen sin reconstruirla, de dev a prod.
Tiempo estimado: 11 min · lectura autónoma · Si solo tienes 5 min: lee «Lo esencial en 30s» + el esquema.

Lo esencial en 30 segundos

  • ARG construye, ENV ejecuta : ARG vive durante el build y luego desaparece, ENV persiste en el contenedor — no confundirlos.
  • Valores por defecto sanos + sobrecarga : la imagen funciona sin nada y cada entorno sobrecarga en el run — una imagen, N entornos.
  • Secretos fuera de la imagen : estructura versionada (.env.example), valores sensibles fuera de git — nunca una contraseña con commit.

Mini-caso hilado — Idir y los dos puertos de una misma imagen

La imagen versionada de Idir (2.3) funciona, pero dev escucha en 3000 y receta en 8080 : el equipo recompilaba una imagen por entorno. Idir declara ENV PORT=3000 por defecto en el Dockerfile : la imagen funciona sin nada. Luego sobrecarga al lanzar (-e PORT=8080) : dos contenedores de la misma imagen 1.0 responden cada uno en su puerto. La clave de build (ARG) queda limitada al build. En 2.5, Idir verificará que ninguna variable sensible haya quedado fijada en la imagen.

Continuación del hilo conductor 2.3 : la misma imagen de Idir sirve a todos los entornos — y continúa en 2.5.

1. ENV frente a ARG : dos momentos

ARG sirve durante el build (versión por compilar, pasada por --build-arg), y luego desaparece : imposible de encontrar en el run. ENV persiste en el contenedor vivo (puerto, modo, URL base) y sigue siendo sobrecargable en el run -e. Regla : ARG construye, ENV ejecuta. Idir pasa su versión de build en ARG y su puerto de escucha en ENV.

2. Los valores por defecto que ayudan

Se declaran valores por defecto sanos en el Dockerfile (ENV PORT=3000 NODE_ENV=production) : la imagen funciona sin nada. Cada entorno sobrecarga al lanzar (-e PORT=8080). Una imagen que exige diez variables oscuras sin valores por defecto es una imagen mal diseñada : nombres explícitos, documentados, valores por defecto que funcionan. Idir lanza dos contenedores de la misma imagen con dos PORT : cada uno responde en el suyo.

3. El .env : la config versionada sin secretos

En Compose (nivel 3), un archivo .env centraliza las variables por entorno. Principio : la estructura está versionada (.env.example con nombres y valores por defecto no sensibles), los valores sensibles quedan fuera de git (archivo local sin commit, gestor de secretos, variables CI). Nunca una contraseña con commit, nunca un secreto fijado en ENV en la imagen : visible en el historial. Idir versiona el ejemplo y mantiene los valores sensibles fuera del repositorio.

Error frecuente de interpretación: « Pongo la contraseña en ENV en el Dockerfile, eso es configuración ». No : un ENV fijado en el build queda legible en el historial y se va con el push — ya no es config, es una fuga. La regla de Idir : ajustes simples en ENV con valores por defecto sanos, secretos inyectados en el run (o vía secretos gestionados), nunca con commit.
Una imagen, N entornos Valores por defecto sanos en la imagen, sobrecarga al lanzar ENV por defecto La imagenfunciona sin nadarun -e sobrecarga Cadaentorno ajusta al lanzar.env por entorno Estructuraversionada, secretos fuera de git
Valores por defecto sanos en la imagen, sobrecarga al lanzar
Versión en texto del esquema (SEO / lectores de pantalla / traducción): 1) Idir DECLARA : ENV PORT=3000 por defecto en el Dockerfile — la imagen funciona sin sobrecarga ; ARG reservado a los valores de build. 2) SOBRECARGA : -e PORT=8080 en el run para receta, sin reconstruir — misma imagen 1.0, dos puertos. 3) ORDENA : estructura en .env.example versionado, valores sensibles fuera de git (archivo local, secretos gestionados). Lección : la config viaja fuera de la imagen, los secretos nunca la tocan.

🔎 Ejemplo concreto — 🔎 Ejemplo concreto — Misma imagen, dos puertos

La imagen de Idir, configurable sin reconstrucción :

# Dockerfile
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
ENV PORT=3000 NODE_ENV=production
EXPOSE 3000
CMD ["sh", "-c", "node server.js --port $PORT"]

docker run -d -p 3000:3000 mon-app:1.0
docker run -d -p 8080:8080 -e PORT=8080 mon-app:1.0

Lectura : la misma imagen 1.0 sirve a dos entornos : por defecto 3000, sobrecarga 8080 al lanzar.

Lección : la config viaja fuera de la imagen — no se recompila para cambiar un puerto.

Vocabulario de la sección

ARG
Una variable de BUILD, disponible solo durante docker build (vía --build-arg), ausente en el run.

Ejemplo sencillo: Idir pasa la versión por compilar en ARG en el build.

Lo que no es: una variable de ejecución persistida.

Reflejo: valor de build = ARG.

ENV
Una variable de EJECUCIÓN, persistida en el contenedor vivo, con valor por defecto sano sobrecargable en el run.

Ejemplo sencillo: Idir declara ENV PORT=3000, sobrecargado en 8080 en el run.

Lo que no es: una variable que desaparece tras el build.

Reflejo: ajuste de lo vivo = ENV.

-e
La sobrecarga de una variable en docker run : el entorno ajusta sin reconstruir la imagen.

Ejemplo sencillo: Idir lanza receta con -e PORT=8080 sobre la misma imagen.

Lo que no es: una recompilación para cambiar un ajuste.

Reflejo: ajustar = -e al lanzar.

Valor por defecto sano
Un valor ENV que hace funcionar la imagen sin ninguna sobrecarga ; base de una imagen bien diseñada.

Ejemplo sencillo: La imagen de Idir arranca en 3000 sin ninguna opción.

Lo que no es: diez variables oscuras exigidas sin valores por defecto.

Reflejo: funciona sin nada primero.

En la práctica — En la práctica — Configurable en 10 minutos

  1. Añade ENV PORT=3000 a tu Dockerfile y recompila.
  2. Lanza dos contenedores de la misma imagen con dos PORT distintos (-e).
  3. Verifica que cada uno responde en su puerto.
  4. Lista las variables vistas desde dentro (exec + env).
Una sola imagen sirve a todos tus entornos por simple sobrecarga.

Script listo para decir — vender la config sin rebuild (30 s)

« Una sola imagen 1.0 para todos los entornos : por defecto escucha en 3000, receta sobrecarga en 8080 al lanzar, sin reconstruir. Los ajustes simples viajan en ENV, la clave de build queda en ARG, y los secretos nunca están en la imagen. Misma versión en todas partes, solo cambia la config. »

Para decir lanzando los dos contenedores de Idir lado a lado, misma imagen, dos puertos.

Modelo copiar-pegar — Dockerfile configurable (ARG + ENV)

FROM node:20-slim
ARG APP_VERSION=1.0
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
ENV PORT=3000 NODE_ENV=production APP_VERSION=${APP_VERSION}
EXPOSE 3000
CMD ["sh", "-c", "node server.js --port $PORT"]

ARG desaparecido

Una versión leída en el run pero pasada en ARG : vacía al arrancar — Idir la vuelve a copiar en ENV si lo vivo la necesita.

Diez variables oscuras

Imagen que exige diez -e sin valores por defecto : Idir añade valores por defecto sanos y documenta cada nombre.

Secreto en ENV fijado

Contraseña en ENV en el Dockerfile, visible en history : Idir la retira y la inyecta en el run.

.env con commit

Archivo .env con valores sensibles subido a git : Idir versiona .env.example y mantiene los valores fuera del repositorio.

✓ Buenas prácticas

  • Valores por defecto que funcionan sin nada.
  • Nombres de variables explícitos y documentados.
  • Secretos fuera de git, siempre.

✗ Errores frecuentes

  • Poner un secreto en ENV con commit (visible en history).
  • Confundir ARG y ENV (desaparecido en el run).
  • Exigir diez variables oscuras sin valores por defecto.

Puntos clave

  • ARG = build (desaparece), ENV = run (persiste y se sobrecarga).
  • Valores por defecto sanos, sobrecarga al lanzar (-e).
  • Una imagen, N entornos : no se recompila para un ajuste.
  • Secretos fuera de la imagen y fuera de git (estructura versionada, valores protegidos).

Desafío 48h — aplica mañana

Haz configurable tu imagen 1.0 : ENV PORT por defecto, dos contenedores dos puertos (-e), control exec + env dentro, y .env.example sin ningún valor sensible.

Lista de salida de la sección
  • Puedo distinguir ARG (build) y ENV (run) y colocarlos correctamente.
  • Sé servir N entornos con una sola imagen (valores por defecto + -e).
  • Mantengo estructura versionada y secretos fuera de git y fuera de la imagen.
Autoevaluación 1-5 : ¿mi imagen funciona sin sobrecarga ?¿ningún secreto duerme en mi Dockerfile o mi historial ?

Preguntas frecuentes

¿Dónde poner una contraseña de base ?

Ni en el Dockerfile ni en la imagen : en variable en el run (-e), en .env local sin commit, o en secreto gestionado (secretos Compose, variables CI, orquestador). Un secreto fijado en ENV queda legible en el historial y se va con el push.

¿ENV o archivo de config montado ?

ENV para los ajustes simples (puertos, modos, URL) ; archivo montado para las configs ricas (nginx.conf, certificados). Ambos se combinan : uno no excluye al otro.

Comprueba tu comprensión

Cambias el puerto de escucha entre dev y prod. ¿Qué haces ?

Recursos adicionales (opcional, para ir más allá)

Examen del nivel 2Preguntas inéditas y más difíciles para validar tus conocimientos