Warning
En caso de tener un problema relacionado a WSL (Subsistema de Windows para Linux) será necesadio instalar WSL
Una vez instalado docker puedes corroborar su version de la siguiente manera:
docker --versionTeniendo instalado Docker en nuestro sistema, tenemos que elaborar dos archivos principalmente: Docker File y Dockerignore, a contunuación de muestra el desarrollo de ambos.
Se debera crear en la carpeta raiz un archivo llamado "DockerFile".
En la arquitectura propuesta para el proyecto del chatbot podemos encontrar varios servidores que estan realizados con Node.Js y Express. Por lo que, la elaboración del DockerFile sera la misma para estos.
Dentro del DockerFile, para estos servidores mencionados podemos encontrar resumidamente lo siguiente:
FROM node:20-alpine
WORKDIR /app
Para la primera línea depende mucho de la version de node que utilice el proyecto. Para saber que versión de imagen de Node.Js utilizar puedes consultar https://hub.docker.com/_/node
Posteriormente tendremos que copiar el package.json para, después instalar las dependencias
COPY package*.json ./
RUN npm install
Finalmente, copiamos el proyecto con las dependencias, le indicamos el puerto interno que queremos exponer y corremos el servidor con node app.js
COPY . .
EXPOSE 3001
CMD ["node", "app.js"]
Esta misma estructura de imagen sera la misma para el resto de los servidores de node.Js
PARA CONSTRUIR LA IMAGEN corremos el siguiente comando
docker build -t nombre-imagen:0.0.0 .Si quisieramos omitir el versionamiento podemos hacerlo de la siguiente manera:
docker build -t nombre-imagen .Debido a que en Django es necesario un venv para poder corer, este se tiene que especificar en el Dockerfile. Después de especificar la versión de imagen de python a utilizar, instalar las dependencias y copiarlas en el ambiente virtual, podemos establecer las variables del entorno de la siguiente manera:
ENV VIRTUAL_ENV=/venv
ENV PATH="/venv/bin:$PATH"
De esta manera le hemos indicado las variables de entorno para usar el entorno virtual.
Por ultimo tendremos que indicar la dirección del directorio en donde se encontrará el proyecto. Especificamos el puerto a utilizar e indicamos como debera correr el proyecto:
WORKDIR /app/server_clasificador
EXPOSE 8000
CMD ["sh", "-c", "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"]
El archivo .dockerignore cumple la misma función que un archivo .gitignore, especifica qué archivos y directorios deben ser ignorados a la hora de construir una imagen de Docker.
Este archivo deberá de ser creado a la misma altura del archivo Dockerfile.
En cuanto a las imagenes generadas, principalmente se ignoraron archivos como el node_modules, archivos relacionados a git como .git, .gitignore y en su devido caso los archivos de distribución o los .env.
Una vez teniendo los dos archivos anteriormente mencionados y habiendo construido la imagen correctamente podemos proceder a generar el contenedor, para esto necesitaremos conocer el nombre de la imagen a partir de la cual queremos ejecutar el contenedor. Para visualizar las imagenes que tenemos construidas podemos abrir nuestro Docker Desktop y dirigirnos al apartado de imagenes y localizar nuestra imagen. Otra opción es abrir nuestra termial y escribir el siguiente comando:
docker image lsSabiendo el nombre correcto de nuestra imagen también debemos tomar en cuenta en que puerto queremos mapear nuestro puerto del contenedor al puerto de nuestra maquina local y ejecutaremos nuestro contenedor con el siguiente comando:
docker run --name NombreContenedor -p 3000:3000 nombre-imagenTip
Podemos correr el comando sin darle un nombre especifico al contenedor, de ser así, docker le dara un nombre pero, ya que tendremos varios contenedores recomiendo darle un nombre especifico para identificarlo de manera rapida.
Note
Para señalar el mapeo del puerto primero deberemos referirnos al puerto que ocupa en nuestra maquina local (antes de los dos puntos) y después de los dos puntos señalaremos el puerto será el del contenedor.
Para visualizar los contenedores que se encuentran corriendo:
docker psAl querer que los servidores se comuniquen entre si (en este caso los contenedores) debemos tomar en cuenta los siguientes puntos:
- Elaborar una red dentro de docker por la cual se comuniquen los contenedores.
Para elaborar la red interna debemos ejecutar el siguiente comando:
docker network create <nombre_de_la_red>Para visulalizar las redes que tenemos o que hamos creado:
docker network ls- De esta manera conseguimos la comunicación entre los servidores dentro de los contenedores, sin embargo, ya que tenemos API's comunicandose de un servidor a otro debemos cambiar la parte "localhost" de la API con el nombre del contenedor
Si tenemos por ejemplo, la siguiente API:
http://localhost:3002/gpt/consulta-mensaje
Deberemos sustituir la parte de "localhost" con el nombre del contenedor al que se va a conectar. Si por ejemplo el contenedor se llama "ContenedorGPT" se veria de la siguiente forma:
http://ContenedorGPT:3002/gpt/consulta-mensaje
- Como punto final y teniendo estos dos puntos cubiertos podemos ejecutar nuestro contenedor asociado a la red elaborada:
Ejecutar el contenedor conctado a la red elaborada para su comunicación interna:
docker run --network nombre_red --name NombreContenedor -p 3000:3000 nombre-imagenPara visualizar los contenedores que se encuentran corriendo:
docker psPara detener el contenedor vía shell debemos abrir otra ventanda shell y correr :
docker stop 12345678asdfghTomando en cuenta que "12345678asdfgh" es el hash del contenedor a detener el cual podemos consultar con docker ps
Para este caso en el que queremos establecer la comunicación entre el docker que contiene el servidor en Django y un script alojado de manera local en el sistema debemos hacer un cambio similar al que se realizó entre la comunicación entre contenedores.
Se sabe que la comunicación entre el servidor Django y el script se elaboro por medio de sockets, sabiendo esto debemos de identificar la conección con el cliente socket (el script) asi como el puerto que le hemos asignado. Para nuestro desarrollo se encuentra similar a la linea de abajo:
client_socket.connect(('localhost', 3004))
Identificando esta linea en donde se establece la conexión, deberemos de sustituir la parte localhost con host.docker.internal asegurandonos de que el script tenga el puerto establecido, quedando de la siguiente manera:
client_socket.connect(('host.docker.internal', 3004))
Note
Para mas información respecto a este tema de comunicación con un servicio host se puede consultar: https://docs.docker.com/desktop/networking/#:~:text=cases%20and%20workarounds-,I%20want%20to%20connect%20from%20a%20container%20to%20a%20service%20on%20the%20host,-The%20host%20has
Siendo la comunicación exitosa entre estos componentes se comunicó este contenedor con el resto de los servidores elaborados y dockerizados, para esto se siguieron los pasos elaborados en el apartado de comunicación entre contenedores.
- Para la dockerización de la parte del front, al esta, estar elaborada en react y con la herramienta de compilación
Vitees necesario realizar un cambio en el archivovite.config.ts. se debera agregar dentro dedefineConfigel host como true:host: true,quedando todo el vite.config.ts de la siguiene manera:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
export default defineConfig({
plugins: [react()],
server:{
watch:{
usePolling: true,
},
host: true,
}
})
Esta línea permite que Vite escuche en todas las interfaces de red.
Esta es la unica configuración adicional que se hizo solo para la parte de la interfaz para su dockerización, el resto de los pasos fueron los mismos que ya se mencionaron.
- Debido a que los contenedores no tienen un archivo
docker-composeque que se utiliza para definir y ejecutar aplicaciones de múltiples contenedores y además facilita significativamente la gestión de cambios dentro de tu proyecto; a la hora de elaboración de un cambio dentro de cualquiera de los archivos, será necesario volver a elaborar el contenedor de este proyecto, no olvidando hacer referencia a la red que se elaboró para su correcta conexión. A continuación se proporcionan los comando comunmente utilizados para este cambio:
Para visualizar las images exixtentes
docker image lsPara construir la imagen corremos el siguiente comando
docker build -t nombre-imagen .Para visulalizar las redes que tenemos o que hamos creado:
docker network lsEjecutar el contenedor conctado a la red elaborada para su comunicación interna:
docker run --network nombre_red --name NombreContenedor -p 3000:3000 nombre-imagenNote
En caso de tener constantes cambios, recomiendo eliminar previamente el contenedor a sustituir con su respectiva imagen ya que en caso de tener bastantes cambios tendremos bastantes contenedores e imagenes llegando a causar confusión.

