Tutorial conexión de MongoDB en Docker con Express y NodeJS


Mongo express y docker

He estado jugando con Docker para crear algunos servicios, y sobre todo, evitar tener que descargar e instalar plataformas que solo quiero usar de prueba. En mi último demo estuve jugando con MongoDB y se me ocurrió hacer un tutorial para enseñarles a configurar MondoDB en Docker para crear una conexión con NodeJS y ExpressJS.

Prerequisitos

Para poder seguir este tutorial se necesitan tener bases de cómo funciona NodeJS y ExpressJS, así como algo muy introductorio a Docker y Dockerfile, pero ya lo iré explicando.

1. Creación de Dockerfile

Una de las maravillas que ofrece Docker es la posibilidad de preparar todos los componentes que necesitas para tu desarrollo en un editor de texto y de ahí ejecutarlo. Yo para poder montar MongoDB voy a necesitar dos servicios:
  1. El motor de bases de datos de MongoDB
  2. Una interfaz web para administrar visualmente mis bases de datos. En este caso uso Mongo Express
Para empezar hay que crear nuestro documento (docker-compose.yaml). Yo tengo uno similar a este:
version: '3.1'
services:
  mongo:
    image: mongo
    container_name: mongodb
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
      MONGO_INITDB_DATABASE: ejemplodb
    ports:
      - 27017:27017

  mongo-express: 
    image: mongo-express
    restart: always
    container_name: mongodb-ui
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: example
En este Dockerfile estoy configurando las imagenes de MongoDB y Mongo Express, el nombre de los contenedores para identificarlos al momento de detenerlos o eliminarlos, y las configuraciones como el username y password del usuario root. Los puertos están siendo los de default: 27017 para la base de datos y 8081 para la interfaz web.
Una vez hecho eso procedemos a correr el comando
docker-compose up
En este momento se aprovisionan nuestros servicios, y una vez que hayan terminado de inicializarse y construido el contenedor podemos acceder a la interfaz web de Mongo Express

2. Configurar aplicación de NodeJS y ExpressJS

Ahora vamos a crear nuestra conexión desde nuestra aplicación de NodeJS usando Express. Lo primero es installar Express
npm install express
adicional instalamos Mongoose, que es un módulo que nos permite de forma más amigable hacer la conexión y operaciones a nuestras bases de datos de Mongo
npm install mongoose
Ahora sí, a crear nuestra aplicación. (app.js)
const express       = require('express');
const bodyParser    = require('body-parser');
const cors          = require('cors'); 
const mongoose      = require('mongoose');

const PORT = 3000;
const app = express();
app.use(cors());
app.use(bodyParser.json());

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

app.listen(PORT, () =>{
    console.log('Servidor backend listo...');
});
Lo que tenemos en esta app es simplemente:
  1. Incluir los módulos que vamos a ocupar
  2. Inicializar nuestro middleware, el cual puedes o no ocupar para tu aplicación
  3. inicializar un ruteo para cargar nuestro index
  4. configurar el puerto para escuchar peticiones
Teniendo eso ya podemos configurar la conexión a MongoDB en nuestro contenedor en Docker.

3. Conexión a MongoDB

Vamos a empezar con la conexión a nuestra base de datos:
mongoose.connect('mongodb://localhost/basededatos', {useNewUrlParser: true, useUnifiedTopology: true});
Aquí está lo importante para poder conectarnos a nuestra base de datos. Lo primero es que siempre usemos el usuario:password para conectarnos a nuestra base de datos, y lo segundo es que mencionemos a qué base de datos queremos conectarnos.
const connection = mongoose.connection;

connection.once('open', () =>{
    console.log('Conectado a la BD');
});
Lo siguiente es la conexión con el evento de 'open', y una vez que conecte vamos a poder ver en nuestra consola el mensaje de que tuvimos éxito.

Algunos errores comunes

Al menos a mi en un principio traté de usar la conexión de este forma
mongoose.connect('mongodb://user:pass@localhost/db', {useNewUrlParser: true, useUnifiedTopology: true});
poniendo las credenciales de root no me dejaba autenticarme, me salía el siguiente error:
UnhandledPromiseRejectionWarning: MongoError: Authentication failed
Lo que podemos es crear un nuevo usuario para poder autenticarnos sin tener que ser root.
Para ello nos conectamos a nuestra consola de mongo en Docker
docker exec -it mongodb mongo -u root
Usamos el comando exec para poder ejecutar un servicio dentro de nuestro contenedor, el cual es mongo. Hay que notar que pongo la bandera de usuario para poder loguearnos como root y me pidan la contraseña. Añadir un nuevo usuario con permisos require que seas administrador para hacerlo, si solo te logueas no va a ser posible.
Ya dentro de nuestra consola de Mongo, vamos a ir a ejecutar la siguiente función para crear un nuevo usuario
use tu-base-de-datos
db.createUser({
    user: 'user',
    pwd: 'pass',
    roles: [
        { role: 'readWrite', db: 'tu-base-de-datos' }
    ]
})
con eso ya puedes autenticarte con esta forma
mongoose.connect('mongodb://user:pass@localhost/db', {useNewUrlParser: true, useUnifiedTopology: true});
Tutorial conexión de MongoDB en Docker con Express y NodeJS Tutorial conexión de MongoDB en Docker con Express y NodeJS Reviewed by Marcos Rivas Rojas on miércoles, septiembre 11, 2019 Rating: 5