(Esta es la segunda parte de una guía practica sobre contenedores que abarca el desarrollo de un API CRUD, el uso de Docker para la contenerizacion de la aplicación, la incorporación de Docker Compose para la sincronización de múltiples contenedores, y finalmente Kubernetes para la orquestación de los contenedores que conforman la aplicación que desarrollaremos.) Codigo Fuente
En esta oportunidad utilizaremos Docker para construir una imagen de Node.js que incluya nuestra API CRUD desarrollada en la guía anterior. Luego ejecutaremos el contenedor y descubriremos la necesidad de incorporar mas contenedores. Debido a esto, utilizaremos Docker Compose para ejecutar en simultaneo 3 contenedores: Uno ejecutando nuestro servidor Node.js, otro ejecutando MySQL y el ultimo ejecutando PhpMyAdmin. Esto se puede visualizar en el siguiente diagrama:
1) Requisitos
Primero instalaremos las tecnologías necesarias para el desarrollo de esta guía: Docker y Docker-Compose.
Si ya posees las tecnologías mencionadas anteriormente y las de la primera parte de la guía, puedes saltarte a la sección 2
1.1) Instalando Docker
Existen varios métodos para instalar Docker, pero en esta guía instalaremos Docker usando el repositorio.
Primero, configuramos el repositorio con los siguientes comandos de terminal:
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
Luego agregamos la clave GPG oficial de Docker con:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
El siguiente paso es configurar el repositorio estable:
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Finalmente instalamos la última versión de Docker Engine y Containerd:
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
Podemos verificar que Docker Engine está instalado correctamente ejecutando la imagen hello-world:
sudo docker run hello-world
Mas detalles acerca este paso en: https://docs.docker.com/engine/install/ubuntu/
1.2) Instalando Docker Compose
Primero, descargamos la versión estable actual de Docker Compose:
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Luego aplicamos permisos ejecutables al binario:
sudo chmod +x /usr/local/bin/docker-compose
Finalmente verificamos la versión de Docker Compose para comprobar que la instalacion fue exitosa:
docker-compose --version
Mas detalles acerca este paso en: https://docs.docker.com/compose/install/
2) Contenerizando nuestra aplicación Node.js
Primero necesitamos crear un Dockerfile (documento de texto que contiene todos los comandos que un usuario puede llamar en la línea de comandos para ensamblar una imagen) en nuestro directorio de proyecto:
touch Dockerfile
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
RUN npm install -g nodemon
COPY script.js ./
CMD ["nodemon","script.js"]
La primera sentencia indica que vamos a utilizar Node.js v14 como nuestra imagen base.
Luego configuramos nuestro directorio de trabajo, que en nuestro caso será una carpeta llamada “app” y contendrá nuestros archivos.
A continuación copiamos tanto package.json como package-lock.json en nuestro directorio de trabajo. Este archivo contiene los nombres de los paquetes necesarios para ejecutar nuestra aplicación.
Luego queremos que el contenedor instale las dependencias con el comando RUN. Además, copiamos nuestro archivo principal “script.js”.
Finalmente le decimos al contenedor que ejecute el comando “nodemon script.js” para iniciar el servidor cuando el contenedor comience a ejecutarse.
Ahora construimos nuestra imagen con el siguiente comando:
sudo docker build -t node-restapi .
Deberíamos obtener una respuesta como la siguiente:
Como recordamos, configuramos nuestro servidor para que se ejecute en el puerto 8080. Sin embargo, ahora ese será el puerto dentro del contenedor.
Entonces, cuando queremos ejecutar nuestro contenedor, tenemos que adjuntar un puerto de nuestra máquina local al puerto del contenedor.
Eso se logra con el parámetro “-p 7000: 8080”. En ese caso, el puerto 7000 se conectará al puerto 8080 del contenedor.
Además, queremos ejecutar el contenedor con una terminal interactiva para imprimir el estado del servidor. Para eso, agregamos el parámetro “-it”. El comando completo es el siguiente:
sudo docker run -it -p 7000:8080 node-restapi
En el log mostrado en la terminal podemos apreciar que nuestro contenedor no se pudo conectar correctamente a la base de datos. Esto sucede porque el contenedor no tiene nuestra base de datos, pues está en nuestra máquina local. Esto sera resuelto en la siguiente sección mediante Docker Compose.
Ahora nuestro contenedor se está ejecutando. Abrimos otra terminal para ver todos los contenedores en ejecución:
sudo docker ps
Si intentamos realizar una petición GET a la ruta http://localhost:7000/students, vemos el siguiente error en la terminal del contenedor:
Esa es una buena señal. Nuestro servidor intenta manejar la petición, pero registra un error porque no puede conectarse a la base de datos para consultar la solicitud. Esto es lo que vamos a resolver en el siguiente apartado.
3) Contenerizando nuestra base de datos y sincronizando nuestra aplicación basada en contenedores con Docker Compose
En esta sección vamos a ejecutar 3 contenedores simultáneamente:
- Servidor Node.js
- Base de datos MySql
- Administrador de base de datos PhpMyAdmin.
Primero, necesitamos hacer un par de cambios en algunos archivos. Editemos nuestro archivo script.js, específicamente el objeto mysqlConnection:
Antes:
//MySQL details
var mysqlConnection = mysql.createConnection({
host: "localhost",
user: "root",
password: "password",
database: "studentmanagement",
multipleStatements: true,
});
Despues:
var mysqlHost = process.env.MYSQL_HOST || 'localhost';
var mysqlPort = process.env.MYSQL_PORT || '3306';
var mysqlUser = process.env.MYSQL_USER || 'root';
var mysqlPass = process.env.MYSQL_PASS || 'password';
var mysqlDB = process.env.MYSQL_DB || 'studentmanagement';
//MySQL details
var mysqlConnection = mysql.createConnection({
host: mysqlHost,
port: mysqlPort,
user: mysqlUser,
password: mysqlPass,
database: mysqlDB,
multipleStatements: true,
});
Este cambio es para usar la variable de entorno del contenedor para configurar el usuario, la contraseña, el puerto, el host y la base de datos de MySQL.
Anteriormente, expusimos el puerto 8080 del contenedor manualmente en la terminal, pero puede ser configurado en el Dockerfile:
Antes:
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY script.js ./
CMD ["node","script.js"]
Despues:
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY script.js ./
EXPOSE 8080
CMD ["node","script.js"]
Ahora construimos nuestra nueva imagen con el siguiente comando:
sudo docker build . -t nodejs-studentmanagement
Luego vamos a crear el archivo docker-compose.yml, que describe los servicios, redes, variables de entorno y comunicación entre los contenedores:
touch docker-compose.yml
Como mencionamos, necesitamos tres servicios: nodejs, mysql y phpmyadmin. Además, vamos a tener dos redes: frontend y backend. La red de backend contendrá los tres servicios y la red de frontend solo el servicio Node.js.
Además, conectaremos el puerto 30001 al 8080 de nuestro contenedor Node.js y el puerto 30002 al puerto 80 del servicio PhpMyAdmin. El archivo docker-compose.yml debe contener lo siguiente:
La imagen de MySQL 5.7 habilita por defecto el puerto 3306 para conexiones entrantes, mientras que PhpMyAdmin habilita por defecto el puerto 80 para conexiones entrantes.
version: "3.2"
services:
nodejs:
build:
context: .
image: nodejs-studentmanagement
depends_on:
- mysql
networks:
- frontend
- backend
environment:
- MYSQL_HOST=mysql-studentmanagement
- MYSQL_USER=smuser
- MYSQL_PASS=smpass
- MYSQL_DB=studentmanagementdb
volumes:
- ./www/:/var/www/html
ports:
- "30001:8080"
container_name: nodejs-studentmanagement
mysql:
image: mysql:5.7
networks:
- backend
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_USER=smuser
- MYSQL_PASSWORD=smpass
- MYSQL_DATABASE=studentmanagementdb
container_name: mysql-studentmanagement
phpmyadmin:
image: phpmyadmin/phpmyadmin:4.7
depends_on:
- mysql
networks:
- backend
ports:
- "30002:80"
environment:
- PMA_HOST=mysql-studentmanagement
- PMA_PORT= 3306
volumes:
- /sessions
container_name: phpmyadmin-studentmanagement
networks:
frontend:
backend:
Finalmente usamos docker-compose para construir y ejecutar los tres contenedores, manteniendo las dependencias entre ellos:
sudo docker-compose up
Ahora los tres contenedores están funcionando.
A continuacion necesitamos configurar la base de datos. Para ello, utilizaremos PhpMyAdmin, que está adjunto al puerto 30002.
Abrimos nuestro navegador y navegamos a http: //localhost:30002 e iniciamos sesión con las credenciales descritas en el docker-compose.yml:
- User: smuser
- Password: smpass
Ahora usamos nuestra base de datos "studentmanagementdb" y hacemos una consulta SQL para crear nuestra tabla de estudiantes:
CREATE DATABASE studentmanagement;
USE studentmanagement;
CREATE TABLE student (student_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,student_name VARCHAR(50),student_email VARCHAR(100), student_phone VARCHAR(15));
Además, necesitamos nuestro procedimiento almacenado para identificar las solicitudes de agregar/editar:
DELIMITER //
CREATE PROCEDURE `studentAddOrEdit`(
IN _student_id INT,
IN _student_name VARCHAR(50),
IN _student_email VARCHAR(100),
IN _student_phone VARCHAR(15)
)
BEGIN
IF _student_id = 0 THEN
INSERT INTO student(student_name,student_email,student_phone)
VALUES (_student_name,_student_email,_student_phone);
ELSE
UPDATE student
SET
student_name = _student_name,
student_email = _student_email,
student_phone = _student_phone
WHERE student_id = _student_id;
END IF;
SELECT _student_id AS 'student_id';
END //
Nos aseguramos de que se haya creado correctamente navegando a la pestaña Rutinas:
4) Probando nuestra API con Postman
Podemos hacer una petición POST para registrar un estudiante con Postman:
Podemos hacer una petición POST para registrar otro estudiante:
Podemos realizar una petición GET para obtener los estudiantes con el navegador, que realiza peticiones HTTP GET por defecto al navegar a una dirección:
Podemos editar un alumno con una petición PUT:
Podemos obtener un alumno específico con una petición GET:
Podemos eliminar a un estudiante con una petición DELETE:
Finalmente podemos visualizar los estudiantes desde el navegador para verificar el resultado final:
Conclusion
En esta segunda parte de la guia utilizamos Docker para construir una imagen de Node.js con nuestro programa y ejecutamos nuestro propio contenedor. Tras esto surgio la necesidad de conectar el contenedor a una base de datos, por lo que utilizamos Docker Compose para ejecutar en simultaneo 3 contenedores: el servidor Node.js, la base de datos MySql y el administrador de base de datos PhpMyAdmin.
En la siguiente guia migraremos nuestra aplicacion multicontenedor de Docker Compose a una arquitectura de Kubernetes.
Espero que te haya sido de utilidad esta guia y nos vemos en la siguiente!
Top comments (0)