Skip to content

Instantly share code, notes, and snippets.

@omaryupio
Last active June 8, 2024 00:32
Show Gist options
  • Select an option

  • Save omaryupio/c6702dc13568687cef1a13b1b3b73882 to your computer and use it in GitHub Desktop.

Select an option

Save omaryupio/c6702dc13568687cef1a13b1b3b73882 to your computer and use it in GitHub Desktop.
Documentación elaborada para la dockerización de proyecto "Chatbot"

Yupio Logo

Docker Logo

Comandos de Docker utilizados y notas de su implementación

Instalaciones necesarias

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 --version

Teniendo instalado Docker en nuestro sistema, tenemos que elaborar dos archivos principalmente: Docker File y Dockerignore, a contunuación de muestra el desarrollo de ambos.

Generación de Imagenes (DockerFile)

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 .

Imagen en Django

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"]

Generación de .dockerignore

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.

Generación de Contenedor

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 ls

Sabiendo 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-imagen

Tip

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 ps

Comunicación entre Contenedores

Al 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-imagen

Para visualizar los contenedores que se encuentran corriendo:

  docker ps

Para detener el contenedor vía shell debemos abrir otra ventanda shell y correr :

  docker stop 12345678asdfgh

Tomando en cuenta que "12345678asdfgh" es el hash del contenedor a detener el cual podemos consultar con docker ps

Comunicación entre contenedor y script local

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))   

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.

Otras consideraciones

  • Para la dockerización de la parte del front, al esta, estar elaborada en react y con la herramienta de compilación Vite es necesario realizar un cambio en el archivo vite.config.ts. se debera agregar dentro de defineConfig el 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-compose que 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 ls

Para construir la imagen corremos el siguiente comando

  docker build -t nombre-imagen .

Para visulalizar las redes que tenemos o que hamos creado:

  docker network ls

Ejecutar el contenedor conctado a la red elaborada para su comunicación interna:

  docker run --network nombre_red --name NombreContenedor -p 3000:3000 nombre-imagen

Note

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment