¿Está buscando una manera de hacer que su aplicación MERN sea compatible con todas las computadoras mientras desarrolla la aplicación? ¡Has venido al lugar correcto! Dockerize su aplicación, y este tutorial de pila MERN es justo lo que necesita.
En este tutorial, aprenderá los conceptos básicos de dockerizar una pila MERN, cómo funciona y cómo implementarlo en varias aplicaciones.
¡Siga leyendo y resuelva los problemas de compatibilidad dockerizando su aplicación!
Requisitos
Este tutorial será una demostración práctica. Si desea seguirnos, asegúrese de tener:
- Docker Desktop 4.5.0+ instalado.
- Nodo 16.0+ instalado.
- Un sistema operativo compatible con Docker:este tutorial usa Windows 10.
- Virtualización habilitada y kernel de Linux instalado (para Windows).
- Servicio de prueba de API (Postman).
Configuración de Docker
Docker es una plataforma de software que acelera la creación, prueba, implementación y administración de aplicaciones. Docker utiliza un contenedor para almacenar todas las dependencias y configuraciones del sistema operativo necesarias para que las aplicaciones se ejecuten en cualquier entorno.
Antes de Dockerizar una pila MERN, primero deberá crear una imagen de nodo personalizada con un archivo Docker.
1. Abra la aplicación Docker para verificar si Docker se inició correctamente. A continuación, puede ver que el motor de Docker se está ejecutando ya que la barra de estado (abajo a la izquierda) es verde.
2. A continuación, cree una carpeta de proyecto llamada MERN-Docker . Esta carpeta contendrá todos los recursos para este tutorial.
3. Cree un .js archivo con su editor de código preferido en la carpeta de su proyecto (MERN-Docker ). Puede nombrar el archivo como desee, pero el archivo se llama server.js en este tutorial. El servidor.js El archivo contendrá todos los códigos para la aplicación del nodo.
4. Abra su terminal y ejecute el siguiente comando npm para inicializar la aplicación (init –y) y cree un package.json archivo.
npm init --y
5. Finalmente, ejecute el siguiente comando para instalar el express
dependencia, lo que le permite crear API para su aplicación de nodo.
npm i express
Configuración de un servidor Express
Después de inicializar la aplicación MERN e instalar la dependencia express, configurará un servidor express simple. Este tutorial utiliza un servidor express simple para demostrar cómo se pueden dockerizar las aplicaciones Express y Node.
1. Abra el servidor.js archivo y cree un GET
express ruta a /
.
El siguiente código envía un mensaje de bienvenida cuando se envía una solicitud GET a http://localhost:5000 .
//Importing and creating an instance of express
const express = require("express");
const app = express();
//Setting PORT to 5000 if PORT is not listed in environmental variables.
const PORT = process.env.PORT || 5000;
// Creating the `GET` route
app.get("/", (req, res) => {
res.send("<h2>Welcome Friends</h2>");
});
//Starting the express server
app.listen(PORT, () =>
console.log(`Server running at http://localhost:${PORT}`)
);
2. Ahora, ejecute el siguiente comando de nodo para iniciar la aplicación express.
node server.js
Si la aplicación se ejecuta correctamente, verá el resultado a continuación.
3. Finalmente, haga una solicitud GET a http://localhost:5000 usando un servicio de prueba de API, como Postman, para probar la ruta rápida.
Creación y creación de una imagen personalizada en este tutorial de Mern Stack
Después de configurar la ruta, el siguiente paso es integrar la aplicación express en un contenedor Docker utilizando una imagen base. En este tutorial, utilizará la imagen base oficial del nodo para configurar el contenedor.
1. Cree un archivo llamado Dockerfile y complete el siguiente código, que crea una imagen de nodo personalizada para su aplicación. Una imagen personalizada le permite agregar su código fuente a la imagen y las configuraciones para su imagen.
# Sets the base image of the application to the node’s official image.
FROM node:17
# Sets the Working Directory as "/server"
WORKDIR /server
# Copies the package.json file into "/server" and runs npm i
COPY package.json /server
RUN npm i
# Copies the entire source code into "/server"
COPY . /server
# Specifies the port the node app will be running on
EXPOSE 5000
# Runs "node server.js" after the above step is completed
CMD ["node", "server.js"]
2. Ejecute el siguiente comando de compilación de docker para crear una imagen personalizada llamada (-t) node-image en el directorio de trabajo (.).
docker build -t node-image .
El siguiente resultado muestra cómo Docker usa el Dockerfile para construir la imagen.
3. Por último, ejecute el siguiente comando de imagen acoplable para enumerar (ls) todas las imágenes construidas.
docker image ls
A continuación, puede ver todas las imágenes disponibles, incluida la imagen del nodo que creó.
Configurando nodemon
Ha creado con éxito una imagen de nodo personalizada, y eso es genial. Pero necesitará ayuda para desarrollar su aplicación cuando haya cambios, y ahí es donde entra en juego la adición de nodemon.
nodemon reinicia automáticamente la aplicación cuando se detectan cambios en los archivos. Pero primero, tendrás que instalarlo.
1. Ejecute el npm
comando a continuación para instalar nodemon
como una dependencia de desarrollo (--save-dev
).
npm i nodemon --save-dev
2. A continuación, abra el package.json archivo en su editor de código preferido para agregar la configuración a continuación.
"scripts": {
"start": "node server.js",
"dev": "nodemon -L server.js"
},
3. Abra el Dockerfile y cambie el CMD
comando al de abajo.
CMD ["npm", "run", "dev"]
4. Por último, ejecute el siguiente docker build
comando para reconstruir la imagen (node-image
).
docker build -t node-image .
Puede ver a continuación que Docker solo cargó los datos almacenados en caché en el segundo paso y ejecutó el comando desde el tercero hasta el último paso. Este comportamiento es el resultado de los cambios que realizó en package.json archivo (almacenamiento en caché de Docker).
Aceleración de las creaciones de Docker mediante la exclusión de archivos y carpetas
Quizás desee acelerar la creación de Docker y proteger el contenido confidencial. Si es así, cree un .dockerignore donde especificará los archivos y las carpetas que se ignorarán para que no se copien en su contenedor de Docker.
1. Cree un archivo llamado .dockerignore con su editor de texto y enumere los archivos, como se muestra a continuación, para excluirlos de la copia en su contenedor Docker.
node_modules
Dockerfile
.dockerignore
2. Ahora, ejecuta el siguiente docker build
comando para reconstruir la imagen (node-image
).
docker build -t node-image .
3. Después de crear la imagen, ejecute el siguiente comando de ejecución de docker para iniciar un contenedor de aplicación de nodo utilizando la imagen de nodo en el puerto 5000 (-p 5000:5000). Este comando también hace que el contenedor sea accesible a través de http://localhost:5000 .
De forma predeterminada, Docker tiene un mecanismo de seguridad que evita que otras máquinas accedan al contenedor de Docker. La única forma de acceder al contenedor Docker es especificando un puerto de acceso.
docker run --name node-app -d -p 5000:5000 node-image
Para detener el contenedor, ejecute docker rm node-app -f.
4. Ahora, ejecute el siguiente comando docker ps para ver todos los contenedores activos (-a).
docker ps -a
A continuación, puede ver que su contenedor Docker (aplicación de nodo) está activo.
5. Ejecute el comando docker exec a continuación para iniciar un shell interactivo (-it) (bash) dentro del contenedor de aplicación de nodo.
docker exec -it node-app bash
6. Finalmente, ejecute el siguiente dir
comando para verificar si los archivos en .dockerignore archivo se agregaron al contenedor (node-app
).
dir
Puede ver en el resultado a continuación que los archivos que enumeró en .dockerignore El archivo no está incluido en el contenedor Docker de la aplicación de notas.
La carpeta node_modules en el contenedor fue generada por el comando npm i del Dockerfile.
Crear la imagen de nodo con Docker-compose
Ha aprendido el ciclo de vida básico de un contenedor:construir, iniciar y detener un contenedor. Pero, ¿aún se puede mejorar el ciclo de vida? Docker-compose le permite simplificar el ciclo de vida no solo de uno sino de numerosos contenedores.
Con Docker-compose, solo necesita ejecutar un comando de Docker para iniciar todos los contenedores y un comando para cerrar todos los contenedores en lugar de ejecutar una serie de comandos. Estos comandos de Docker siguen las instrucciones enumeradas en docker-compose archivo.
Para comenzar con Docker-compose, necesita un archivo YAML que contenga todos los servicios y las configuraciones para estos servicios. Algunas de estas configuraciones incluyen.
- Configuración de compilación:contiene la ubicación del Dockerfile que desea usar para compilar el servicio y otras opciones de compilación.
- Imágenes:puede usar imágenes en hub.docker.com en lugar de crear su imagen personalizada.
- Variables de entorno:Almacena configuraciones a variables en su código.
- Puertos:esta opción especifica en qué puerto se ejecutará la aplicación.
- Red:esta opción permite que un contenedor se comunique con otro contenedor.
Cree un archivo YAML llamado docker-compose.yml y complete la configuración a continuación, lo que crea una imagen de nodo personalizada.
YAML es sensible a la sangría, así que asegúrese de utilizar la indexación adecuada.
# Version of Docker-compose
version: '3.8'
services:
# Service name
node:
# Creating a custom image
build:
# Location to the Dockerfile
context: .
# Name of the Dockerfile
dockerfile: Dockerfile
ports:
# External port:Internal port
- 5000:5000
Ejecute el siguiente comando para construir e iniciar el servicio de nodo.
docker-compose up --build
Configuración de volúmenes para datos persistentes en Docker Container
Después de crear la imagen del nodo, deberá almacenar datos estáticos y sincronizar su código fuente con el código fuente en el contenedor. ¿Cómo? Mediante la configuración de volúmenes y montajes de enlace para el contenedor Docker.
En este tutorial, comenzará a configurar volúmenes primero. Los volúmenes en Docker son directorios fuera del contenedor de Docker que contienen los datos de ese contenedor. Los volúmenes se utilizan principalmente para almacenar datos persistentes, como códigos fuente, archivos de registro, etc.
1. Abra su docker-compose archivo en su editor de código.
2. Agregue las configuraciones de volumen a continuación bajo el node
servicio de docker-compose expediente.
La siguiente configuración crea un volumen llamado nodeVolume y almacena el volumen en una carpeta llamada server. Pero no dude en cambiar el nombre del volumen y la carpeta.
---
node:
---
# ADD THE CONFIGURATION FROM THIS POINT to create a volume named nodeVolume
volumes:
# Syntax <nameOfVolume>:<directorInDocker>
- nodeVolume:/server
# Making the node service volume accessible to other services.
volumes:
# Declaring the node service volume.
nodeVolume:
3. Por último, ejecute el siguiente comando para reconstruir la imagen (imagen de nodo).
docker-compose up -d --build
Configurar Bind Mount para sincronizar el directorio local con el contenedor Docker
Bind mount es un mecanismo que sincroniza una carpeta en su máquina local con una carpeta en el contenedor de Docker. Un montaje de vinculación almacena datos en el contenedor, pero los datos también se eliminan cuando se elimina el contenedor.
Los montajes de enlace se utilizan principalmente en la etapa de desarrollo donde los datos son dinámicos (la información cambia con frecuencia). Con un montaje de vinculación, no tiene que reconstruir la aplicación cada vez que se realiza un cambio en el código fuente de la aplicación.
Para configurar un montaje de enlace:
1. Abra su docker-compose archivo y agregue el código a continuación en el node
servicio bajo volumes
.
El siguiente código sincroniza el directorio de trabajo de la aplicación con el directorio /app en el contenedor. Al mismo tiempo, el código evita que su código fuente realice cambios en el archivo node_modules en el directorio de la aplicación.
---
node:
volumes:
---
# ADD THE CONFIGURATION FROM THIS POINT to sync the working directory
# for the application to the /app directory in the container
- .:/server
- /server/node_modules
2. Ejecute el siguiente comando para reconstruir la imagen del nodo.
docker-compose up -d --build
La modificación de archivos desde el directorio /app de la aplicación en Docker afectará los archivos en su máquina local ya que las carpetas están sincronizadas. Para restringir que Docker realice cambios en el código fuente de su aplicación, agregue la opción de solo lectura (:ro) a su configuración de montaje de enlace, como se muestra a continuación.
node:
volumes:
- ./:./server:ro # Adding the read-only option
- - /server/node_modules
3. Abra el servidor.js archivo en su editor de código, reemplace h1
encabezado a h5
, como se muestra a continuación, y guarde los cambios. Estos cambios en server.js El archivo le permite probar si la configuración de montaje de enlace funciona.
app.get("/", (req, res) => {
res.send("<h5>Welcome Friends</h5>");
});
4. Ahora, ejecute el siguiente comando para ver todos los contenedores en ejecución.
docker ps
5. Ahora, ejecute docker exec
comando a continuación para ejecutar un shell interactivo (-it
) de su contenedor de nodos en ejecución (mern-docker_node_1
).
docker exec -it mern-docker_node_1 bash
6. Finalmente, ejecuta el cat
Comando a continuación para mostrar el contenido modificado dentro de server.js
archivo en su contenedor de nodo.
cat server.js
Como puede ver a continuación, el encabezado cambió a h5.
Conectando MongoDB a la aplicación MERN
MongoDB es un programa de base de datos orientado a documentos NoSQL, gratuito, de código abierto y multiplataforma. En este tutorial, configurará MongoDB y verá cómo el servicio de nodo de la sección anterior puede comunicarse con MongoDB.
Abra el docker-compose archivo en su editor de código y agregue la configuración especificada a continuación en el node
servicio.
Esta configuración utiliza la imagen Docker oficial de Mongo para construir el servicio MongoDB (contenedor).
version: '3.8'
services:
node:
...
# ADD THE CONFIGURATION FROM THIS POINT to build the MongoDB service
environment:
- PORT=5000
# For security, specify a username and password as environmental variables
# Username for the mongo database
- MONGO_INITDB_ROOT_USERNAME=mern
# Password for the mongo database
- MONGO_INITDB_ROOT_PASSWORD=merndocker
# Enables the mongo service to start before the node service
depends_on:
- mongo
# Name of mongo service
mongo:
# Official mongo image from docker.hub
image: mongo
environment:
# Username for the mongo database
- MONGO_INITDB_ROOT_USERNAME=mern
# Password for the mongo database
- MONGO_INITDB_ROOT_PASSWORD=merndocker
volumes:
# <nameOfVolume>:<directorInDocker>
- mongoDB:/data/db
volumes:
# Making the volume accessible by other containers
mongoDB:
Ahora, ejecute docker-compose
comando a continuación para --build
e inicie el servicio mongo.
docker-compose up -d --build
Como puede ver a continuación, Docker está creando un volumen para el servicio mongo.
Vincular NodeJS a MongoDB
Después de compilar el servicio mongo, ahora puede vincular el servicio NodeJS a MongoDB. Vincular Nodejs a MongoDB le permite almacenar datos en la base de datos de MongoDB.
Usar el nombre de un servicio es una de las formas comunes de comunicarse con diferentes contenedores. Y este tutorial usa la dependencia de mongoose para vincular el servicio de nodo a MongoDB. Pero primero tendrás que instalar mongoose.
1. Ejecute el siguiente comando para instalar mongoose
.
npm i mongoose
2. A continuación, abra server.js y agregue el código a continuación, que importa la dependencia de mongoose y la usa para vincular NodeJS con MongoDB.
El siguiente código utiliza el nombre de usuario y la contraseña que almacenó como variables de entorno en docker-compose archivo para conectar el servicio de nodo con MongoDB.
const mongoose = require('mongoose');
// Gets the Username and Password
const MONGO_URI = `mongodb://${process.env.MONGO_INITDB_ROOT_USERNAME}:${process.env.MONGO_INITDB_ROOT_PASSWORD}@mongo:27017`;
// Creating the connect function
const connectDB = async () => {
await mongoose
.connect(MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log("Mongo connected successfully"))// Logs out successful when MongoDB connects.
.catch((e) => {
console.log(e.message);// Logs out the error message if it encounters any.
});
};
// Calling the Connect Function
connectDB();
...
3. Ahora, ejecute el siguiente comando docker-compose para reconstruir la imagen del nodo.
docker-compose up -d --build
4. Finalmente, ejecute el siguiente comando para abrir los registros de la aplicación y verifique si MongoDB se conectó correctamente.
docker-compose logs
A continuación, puede ver MongoDB conectado correctamente.
Agregar Redis a la aplicación MERN
Acaba de agregar MongoDB como segundo servicio a la aplicación MERN y ahora agregará Redis como el tercero. Redis es una base de datos NoSQL comúnmente utilizada para almacenar tokens y datos en caché.
Abra el docker-compose y agregue la siguiente configuración debajo de mongo
servicio bajo services
, como se muestra a continuación.
Esta configuración configura la imagen Docker oficial de Redis
services:
---
mongo:
---
# ADD THE CONFIGURATION FROM THIS POINT to set up the Redis service
redis:
image: redis
Configuración del lado del cliente de la aplicación MERN
Desde la configuración de su aplicación en el lado del servidor, profundice en la configuración de una aplicación React como el lado del cliente de la aplicación MERN. React es una biblioteca de JavaScript para crear interfaces de usuario.
1. Ejecute el siguiente comando para crear una aplicación React simple. Este comando crea automáticamente un directorio llamado cliente en el directorio raíz de la aplicación MERN.
npx create-react-app client
El comando create-react-app comienza a instalar todas las dependencias requeridas en el resultado a continuación.
2. Una vez completada la instalación, abra el cliente directorio en el directorio raíz de la aplicación MERN y cree un Dockerfile dentro de él. Puede nombrar el Dockerfile de manera diferente, pero el Dockerfile se llama react.dockerfile en este tutorial.
3. Agregue el siguiente código en el Dockerfile (react.dockerfile) , que crea una imagen React personalizada.
# Official node image
FROM node:17
# Setting the working directory to "/client"
WORKDIR /client
# Copies the package.json file into "/client" and run npm i
COPY package.json /client
RUN npm install
# Copies the entire react source code into "/client"
COPY . /client
EXPOSE 3000
# Starting the react app
CMD [ "npm", "start"]
4. Ahora, abra su docker-compose archivo y reemplace el contenido con el siguiente código.
El siguiente código agrega un servicio de reacción en los servicios con la ubicación y el nombre de Dockerfile.
Agregará partes del código que agregará en el archivo docker-compose y verá el código completo en la última parte de estos pasos.
# Version of Docker-compose
version: '3.8'
services:
# Add the react service
react:
# Location to the dockerfile
context: ./client
# Name of the dockerfile
dockerfile: react.dockerfile
5. Configure los volumes
, ports
y depends_on
opciones, como se muestra a continuación.
volumes:
# Bind-mounts configuration
- ./client:/client
# Ignoring any changes made in "node_modules" folder
- /client/node_modules
ports:
# External port:Internal port
- 3000:3000
depends_on:
# Starts up the node service before starting up the react service
- node
6. Finalmente, agregue la configuración a continuación para agregar una variable de entorno para habilitar la recarga en caliente en el contenedor Docker. La recarga activa actualiza una página de reacción y vuelve a renderizar sus componentes.
environment:
# Enabling hot reload
- CHOKIDAR_USEPOLLING=true
Seguir los pasos anteriores lo llevará a la configuración a continuación.
version: '3.8'
services:
react:
build:
context: ./client
dockerfile: react.dockerfile
volumes:
- ./client:/client
- /client/node_modules
ports:
- 3000:3000
environment:
- CHOKIDAR_USEPOLLING=true
depends_on:
- node
node:
---
mongo:
---
redis:
---
Conclusión
Este tutorial tiene como objetivo enseñarle cómo configurar su aplicación usando Docker y hacerla compatible con otros dispositivos. ¿Sientes que ese es el caso? En este punto, ha aprendido los conceptos básicos para impulsar el desarrollo de su aplicación de pila MERN.
Como siguiente paso, ¿por qué no aprender a usar NGINX para configurar un proxy para su aplicación e implementarlo en Docker?