Cómo manejar variables de entorno en Node.js con dotenv y process.env paso a paso

DUGLAS MORENODUGLAS MORENO 👁 8

Introducción

En cualquier proyecto de Node.js es habitual encontrarse con valores que no deben quedar hardcodeados en el código fuente: credenciales de bases de datos, claves de APIs, puertos de escucha, etc. Estos valores se conocen como variables de entorno y su correcta gestión es fundamental para:

  • Mantener la seguridad (evitar que secretos se publiquen en repositorios).
  • Permitir que la misma aplicación se ejecute en distintos entornos (desarrollo, testing, producción) sin cambios en el código.
  • Facilitar la configuración en contenedores y plataformas cloud.

Este artículo está dirigido a desarrolladores que ya manejan Node.js a nivel básico y quieren aprender a usar dotenv junto a process.env de forma práctica y segura. Al terminar, sabrás cómo crear, cargar y consumir variables de entorno, cómo definir valores por defecto, y qué errores comunes evitar.

1. ¿Qué son las variables de entorno?

Una variable de entorno es un par clave/valor que el sistema operativo pone a disposición de los procesos que se ejecutan. En Node.js, todas esas variables están accesibles a través del objeto global process.env.

console.log(process.env.PATH); // Imprime la variable PATH del sistema

En la práctica, usamos variables de entorno para separar la configuración del código. Así, el mismo código puede correr en distintas máquinas simplemente cambiando el archivo de configuración.

2. Por qué usar dotenv

Node.js no tiene una forma nativa de leer archivos .env. La librería dotenv llena ese vacío: lee un archivo de texto plano con formato KEY=VALUE y carga esas parejas dentro de process.env antes de que tu aplicación arranque.

Ventajas principales:

  • Simplicidad: sólo agregar una línea de código.
  • Compatibilidad: funciona con cualquier versión de Node.
  • Flexibilidad: puedes tener varios archivos .env (por ejemplo, .env.development, .env.test).

3. Instalación y configuración básica

3.1 Instalar la dependencia

npm install dotenv --save

3.2 Crear el archivo .env

En la raíz del proyecto, crea un archivo llamado .env y agrega tus variables:

# .env
PORT=3000
DB_HOST=localhost
DB_USER=admin
DB_PASS=supersecret
API_KEY=abcdef123456

Nota: el archivo no debe subirse al control de versiones. Añádelo a .gitignore.

echo '.env' >> .gitignore

3.3 Cargar el archivo al iniciar la app

En el punto de entrada de tu aplicación (por lo general index.js o app.js) agrega la siguiente línea antes de cualquier otro require que dependa de variables de entorno:

require('dotenv').config();
console.log('Variables cargadas:', process.env.PORT, process.env.DB_HOST);

Salida esperada (asumiendo que el archivo .env contiene los valores mostrados antes):

Variables cargadas: 3000 localhost

4. Accediendo a variables de entorno en tu código

Una vez que dotenv ha ejecutado config(), todas las variables estarán disponibles en process.env. Veamos algunos casos de uso.

4.1 Configuración de un servidor Express

require('dotenv').config();
const express = require('express');
const app = express();

const PORT = process.env.PORT || 8080; // valor por defecto si no está definido

app.get('/', (req, res) => {
  res.send('Hola Mundo!');
});

app.listen(PORT, () => {
  console.log(`Servidor escuchando en http://localhost:${PORT}`);
});

Salida esperada (con el .env anterior):

Servidor escuchando en http://localhost:3000

Si eliminamos PORT del archivo .env, la salida será http://localhost:8080 gracias al valor por defecto.

4.2 Conexión a una base de datos con pg (PostgreSQL)

require('dotenv').config();
const { Client } = require('pg');

const client = new Client({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: 'mydb'
});

client.connect()
  .then(() => console.log('Conectado a PostgreSQL'))
  .catch(err => console.error('Error de conexión:', err.message));

Salida esperada (asumiendo credenciales correctas):

Conectado a PostgreSQL

Importante: nunca imprimas directamente una variable sensible (como DB_PASS) en logs de producción.

5. Variables de entorno por entorno (development, test, production)

En proyectos reales, cada entorno tiene su propio conjunto de valores. dotenv permite cargar archivos diferentes según una variable NODE_ENV.

5.1 Estructura de archivos

my-app/
├─ .env.development
├─ .env.test
├─ .env.production
├─ index.js

5.2 Código para seleccionar el archivo correcto

const env = process.env.NODE_ENV || 'development';
require('dotenv').config({ path: `.env.${env}` });
console.log('Entorno:', env);
console.log('Puerto configurado:', process.env.PORT);

Supongamos que los archivos contienen:

  • .env.developmentPORT=3001
  • .env.testPORT=4000
  • .env.productionPORT=80

Ejemplo de ejecución

NODE_ENV=development node index.js

Salida:

Entorno: development
Puerto configurado: 3001
NODE_ENV=production node index.js

Salida:

Entorno: production
Puerto configurado: 80

6. Buenas prácticas y errores comunes

6.1 Buenas prácticas

  1. Mantener .env fuera del VCS
    • Añadí siempre a .gitignore.
  2. Usar valores por defecto en el código
    • const PORT = process.env.PORT || 3000;
  3. Validar variables al iniciar
    • Usa librerías como joi o zod para chequear que todas las variables necesarias están presentes.
  4. No almacenar secretos en logs
    • Evita console.log(process.env) en producción.
  5. Documentar variables esperadas
    • Crea un README-ENV.md con descripción y ejemplos.

6.2 Errores comunes

Error Por qué ocurre Cómo evitarlo
Olvidar require('dotenv').config() antes de usar process.env Las variables aún no están cargadas Colocá la línea como la primera instrucción de tu entry point
Tener espacios o comillas en el archivo .env dotenv interpreta todo como parte del valor Usa KEY=value sin comillas y sin espacios alrededor del =
Subir el .env al repo Exposición de credenciales Añadí .env* al .gitignore y usa git rm --cached .env si ya está versionado
Usar variables que no existen y no definir un fallback La aplicación falla con undefined Siempre proveé un valor por defecto o lanza un error explícito
Cargar varios archivos .env sin control Sobrescritura inesperada de valores Usa la opción override: false o carga manualmente según la lógica de tu app

7. Herramientas complementarias

  • dotenv-cli: permite ejecutar scripts con variables de un archivo .env sin modificar tu código.
  • cross-env: útil para definir variables de entorno en scripts npm de forma portable (Windows/Linux).
  • dotenv-safe: verifica que todas las variables requeridas estén definidas y opcionalmente usa un archivo .env.example como plantilla.

7.1 Ejemplo con dotenv-safe

  1. Instalar:
npm install dotenv-safe --save
  1. Crear .env.example con las claves obligatorias:
# .env.example
PORT=
DB_HOST=
DB_USER=
DB_PASS=
  1. En tu entry point:
require('dotenv-safe').config();
console.log('Todas las variables obligatorias están presentes');

Si falta alguna variable, la ejecución aborta con un mensaje claro.

8. Uso de variables de entorno en Docker y CI/CD

Cuando desplegás en contenedores, no usás archivos .env dentro de la imagen. En su lugar, pasás variables al docker run o al docker-compose.yml.

# docker-compose.yml
version: '3.8'
services:
  app:
    image: my-node-app
    env_file:
      - .env.production
    ports:
      - "80:3000"

En pipelines de GitHub Actions, definís secretos y los exponés como variables:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      - name: Set up Node
        uses: actions/setup-node@v3
        with:
          node-version: '20'
      - name: Install deps
        run: npm ci
      - name: Run tests
        env:
          DB_HOST: ${{ secrets.DB_HOST }}
          DB_USER: ${{ secrets.DB_USER }}
          DB_PASS: ${{ secrets.DB_PASS }}
        run: npm test

9. Resumen de comandos útiles

# Instalar dotenv
npm install dotenv --save

# Añadir .env al .gitignore
echo '.env' >> .gitignore

# Ejecutar con variable de entorno específica
NODE_ENV=production node index.js

# Usar dotenv-cli para correr sin modificar código
npx dotenv -e .env.production -- node index.js

Conclusión

Manejar variables de entorno en Node.js con dotenv y process.env es una práctica esencial para escribir aplicaciones seguras, configurables y portables. Aprendimos a:

  • Crear y cargar un archivo .env.
  • Acceder a los valores mediante process.env con fallback seguros.
  • Gestionar distintos entornos (development, test, production).
  • Aplicar buenas prácticas y evitar errores típicos.
  • Integrar la configuración con Docker y pipelines CI/CD.

Con estos conceptos, ya podés estructurar tu proyecto de manera que la configuración quede separada del código, lo que facilita el mantenimiento y la escalabilidad. Como próximo paso, considerá usar dotenv-safe o esquemas de validación con zod para reforzar la robustez de tu configuración.

Comentarios (0)

Sé el primero en comentar.

Dejá tu comentario