Saltar al contenido principal

Docker Compose (NestJS y MongoDB)

  • Ejemplo con Nest y MongoDB en una imagen

1. Imagen de nuestra app

Dockerfile

  • Cada from es construir una nueva imagen, ya sea de Node, MongoDB, Postgres, etc.
Dockerfile
# 1. Imagen solo para las dependencias
FROM node:20.9.0-alpine3.18 AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json ./
RUN npm install --frozen-lockfile

# 2. Imagen builder para compilar la aplicación
FROM node:20.9.0-alpine3.18 AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

# 3. Imagen de producción
FROM node:20.9.0-alpine3.18 AS runner
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install --prod
COPY --from=builder /app/dist ./dist

# 4. Iniciar la aplicación
CMD [ "node","dist/main" ]

Con comentarios

Dockerfile
# 1. Imagen solo para las dependencias
# (Si el nuevo build no tiene cambios en las dependencias, no se instalan de nuevo)
# (Si hay nuevas dependencias, se instalan)
FROM node:20.9.0-alpine3.18 AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json ./
RUN npm install --frozen-lockfile

# 2. Imagen builder para compilar la aplicación
# Copia de las deps a la imagen de producción
FROM node:20.9.0-alpine3.18 AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
# Copiar de la carpeta actual a la carpeta de la aplicación
COPY . .
# Compilar la aplicación
RUN npm run build

# 3. Imagen de producción
# Copiar de la imagen de builder a la imagen de producción
FROM node:20.9.0-alpine3.18 AS runner
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install --prod
# Copiar de la imagen de builder a la imagen de producción
COPY --from=builder /app/dist ./dist

# # Copiar el directorio y su contenido
# RUN mkdir -p ./pokedex
# COPY --from=builder ./app/dist/ ./app
# COPY ./.env ./app/.env

# # Dar permiso para ejecutar la applicación
# RUN adduser --disabled-password pokeuser
# RUN chown -R pokeuser:pokeuser ./pokedex
# USER pokeuser

# EXPOSE 3000

# 4. Iniciar la aplicación
CMD [ "node","dist/main" ]

.dockerignore

.dockerignore
dist/
node_modules/

.gitignore
.git/

2. docker-compose.yaml

  • El archivo que une o construye varias imagenes
  • Se pueden crear variables, como prod y dev.
docker-compose.prod.yaml
version: '3'

# Servicios o contenedores que se van a ejecutar
services:

  # 1. Servicio de la aplicación
  pokedexapp:
    # Depende de otras imagenes
    depends_on:
      - db
    # Construir nuestra imagen con la app
    build:
      context: .
      dockerfile: Dockerfile
    image: pokedex-docker
    container_name: pokedexapp
    restart: always
    ports:
      - "${PORT}:${PORT}"
    # Variables de entorno
    environment:
      MONGO_DB: ${MONGO_DB}
      PORT: ${PORT}
      DEFAULT_LIMIT: ${DEFAULT_LIMIT}

  # 2. Servicio de base de datos
  db:
    image: mongo:5.0.0
    container_name: mongo-poke
    restart: always
    ports:
      - 27017:27017
    environment:
      MONGODB_DATABASE: nest-pokemon
    volumes:
      - ./mongo:/data/db

Con comentarios

docker-compose.prod.yaml
version: '3'

# Servicios o contenedores que se van a ejecutar
services:

  # 1. Servicio de la aplicación
  pokedexapp:
    # depende de otro servicio
    depends_on:
      - db
    # Construir nuestra imagen
    build:
      # Buscar el archivo Dockerfile en el directorio
      context: .
      dockerfile: Dockerfile
    # Nombre de la imagen
    image: pokedex-docker
    # Nombre del contenedor
    container_name: pokedexapp
    restart: always # reiniciar el contenedor si se detiene
    ports:
      - "${PORT}:${PORT}"
    # working_dir: /var/www/pokedex
    # Variables de entorno para la aplicación
    environment:
      MONGO_DB: ${MONGO_DB}
      PORT: ${PORT}
      DEFAULT_LIMIT: ${DEFAULT_LIMIT}
    # Opcional, para persistir los datos de la aplicación
    # volumes:
    #   - ./:/var/www/pokedex

  # 2. Servicio de base de datos
  db:
    image: mongo:5.0.0
    container_name: mongo-poke
    restart: always # reiniciar el contenedor si se detiene
    ports:
      - 27017:27017
    environment:
      MONGODB_DATABASE: nest-pokemon
    # Opcional, para persistir los datos de la base de datos
    # volumes:
    #   - ./mongo:/data/db

3. Variables de entorno

.env
PORT=3000
DEFAULT_LIMIT=10

# Debido a utilizar docker entonces no usamos IP, sino el nombre del contenedor
# Utiliza el nombre definido en el docker-compose.yml
# db:
# container_name: mongo-poke
MONGO_DB=mongodb://mongo-poke:27017/nest-pokemon

4. Ejecutar

Ejecutar archivo

docker compose up -d
# -d para cerrar la terminal sin detener los servicios

Build

Cada vez que se hace un cambio en el proyecto, nuevo módulo, funcionalidad, etc.

docker-compose -f docker-compose.prod.yaml --env-file .env.prod up --build -d
info

Por defecto, docker-compose usa el archivo .env, por lo que si tienen el archivo .env y lo configuran con sus variables de entorno de producción, bastaría con

docker-compose -f docker-compose.prod.yaml up --build -d

Run

docker-compose -f docker-compose.prod.yaml --env-file .env.prod up -d
info

Por defecto, docker-compose 

  • Usa el archivo docker-compose.yaml, entoneces si no tenemos otro, como prod no seria necesario
  • Usa el archivo .env, por lo que si tienen el archivo .env y lo configuran con sus variables de entorno de producción
docker-compose up -d