Tiempo de lectura: 20 minutos.
Público objetivo: Desarrolladores de software
Nivel: Básico.
Fecha publicación: 8 de Marzo de 2022
Hola a todos y todas, me alegra que visiten nuevamente nuestro blog, aunque he de confesarles que no soy uno de sus bloggers habituales, hemos decidido dejar descansar a nuestro querido Jhon J Valero R durante un tiempo y aproveché la oportunidad para compartirles un tema el cual me tiene interesado hace un largo tiempo. Sin más preámbulos ni confesiones adicionales, los invito a entrar libremente y por su propia voluntad y dejar parte de la felicidad que traen con ustedes.
Montar un entorno de desarrollo… (Estoy seguro que alguno hizo una mueca con solo leerlo) todo aquel que haya realizado este proceso debe saber que es una tarea indispensable y realmente tediosa a la hora de correr nuestros proyectos, debemos verificar versiones, programas, librerías, instalar y configurar herramientas de entornos de versiones, instalar dependencias y finalmente correr el proyecto, todo eso para (En algunas ocasiones) encontrarnos con errores que no tuvieron tus compañeros y que no existen en producción… Esto se traduce a horas de producción pérdidas por parte de un desarrollador.
Aquí entra Docker, una herramienta que no solo nos va a permitir hacer este proceso una sola vez, compartirlo con todo el equipo de desarrollo y emplearlo en producción, además reducirá el ya conocido por todos “En local funcionaba bien, no se que paso” al permitirnos crear una imagen con todo lo necesario para nuestro proyecto, almacenado en un repositorio.
La documentación de Docker nos dice:
“ La imagen del contenedor Docker es un paquete de software ejecutable independiente y liviano que incluye todo lo necesario para ejecutar una aplicación: código, tiempo de ejecución, herramientas del sistema, bibliotecas del sistema y configuraciones. ”
Alguien puede estar leyendo este texto y pensar que es básicamente una máquina virtual, ¿por qué no emplear VirtualBox en lugar de usar Docker? Pero es importante hablar del elefante en la habitación, supongamos que su aplicación tiene entre 100 o 200 MB, pero un sistema operativo completo puede pasar fácilmente a GigaBytes.
Docker lo resuelve usando contenedores para ejecutar las aplicaciones. Primero, Docker crea una imagen de su aplicación y luego la ejecuta como contenedores. De esta manera, en lugar de usar un sistema operativo completo para una sola aplicación, usa algunos recursos compartidos comunes y ejecuta su aplicación en contenedores empleando Docker Engine, el cual se encarga de eliminar la dependencia del sistema operativo completo de su aplicación.
Para entender los próximos pasos en la implementación de Docker es necesario establecer el orden del directorio de un proyecto en cuestión y sus características, este proyecto divide el mismo en dos carpetas independientes para el manejo del frontEnd y backEnd, por lo cual se creará un Docker individual para cada proyecto.
FROM python:3
ENV PYTHONUNBUFFERED 1
WORKDIR /app/api
COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY . ./
EXPOSE 8000
FROM node:13.12.0-alpine
WORKDIR /app/frontend
COPY package.json package-lock.json ./
RUN npm install
RUN npm install react-scripts@3.4.1 -g
COPY . ./
EXPOSE 3000
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'bug',
'USER': config('DB_USER'),
'PASSWORD': config('DBPASS'),
'HOST': 'db', # You are supposed to use service name not localhost
'PORT': '3306',
}
}
version: "3.2"
services:
redis:
restart: always
image: redis:5
ports:
- "6379:6379"
networks:
- db-net
db:
restart: always
image: mariadb:5.5
environment:
- MYSQL_HOST=localhost
- MYSQL_PORT=3306
- MYSQL_ROOT_HOST=%
- MYSQL_DATABASE=bug
- MYSQL_USER=<<username>>
- MYSQL_PASSWORD=<<password>>
- MYSQL_ROOT_PASSWORD=<<rootpassword>>
ports:
- "3302:3306"
networks:
- db-net
project:
restart: always
container_name: code
command : bash -c "python check_db.py --service-name db --ip db --port 3306 &&
python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000"
env_file:
- ./project/settings.ini
build:
context: ./project/
dockerfile: Dockerfile
ports:
- "8000:8000"
depends_on:
- db
- redis
networks:
- db-net
frontend:
restart: always
command : npm start
container_name: front
build:
context: ./frontend/
dockerfile: Dockerfile
ports:
- "3000:3000"
stdin_open: true
depends_on:
- project
networks:
- db-net
networks:
db-net:
driver: bridge
En la primera parte se está creando el manejo de la base de datos empleando mariadb y variables de entorno para los datos privados del cliente. Posteriormente establecemos los parámetros necesarios para correr el proyecto de backend y frontend y corremos los comandos para la base de datos, migraciones y finalmente proyecto.
Version: Establece tu versión.
services: Define sus servicios. En el código podemos ver servicios de redis, db, project y frontend. Puede definir tantos servicios como desee.
Restart: always le dice al contenedor que reinicie el servicio si se apaga inesperadamente.
Image: Aquí definimos las imágenes que van a ser utilizadas es posible emplear tanto los Dockerfile que habíamos revisado previamente como imágenes estándar no personalizadas (por ejemplo: mariadb:5.5)
Ports: port1:port2 le dice al contenedor que escuche qué puerto. El puerto 1 puede ser cualquier puerto desocupado, pero el puerto 2 debe ser el puerto que habría utilizado si estuviera ejecutando su aplicación en localhost. Es posible emplear el mismo puerto si se tiene la seguridad de estar libre.
Command: En este espacio se especifican los comandos para ejecutar el momento de iniciar el contenedor
Container_name: Si no define un container_name, la ventana acoplable proporciona un valor predeterminado basado en su carpeta y servicio.
Depends_on: Dice a Docker que un determinado servicio depende de otros servicios, por lo que primero debe iniciar sus contenedores antes de iniciar el contenedor actual.
Build:
Context: como una ruta relativa para su Dockerfile con respecto a su archivo docker-compose.
Dockerfile: es el nombre de su Dockerfile.
El primer paso será construir tus imágenes. para ello en la terminal será necesario ubicarse en la carpeta donde esta ubicado el docker compose
docker-compose build
Una vez terminado este proceso será posible ejecutar la aplicación empleando el comando correspondiente. Es posible que deba darle a su aplicación un minuto para correr las migraciones de forma adecuada, configurar el backend y ejecutar los servidores.
docker-compose up -d
Para comprobar los contenedores que se están ejecutando actualmente
docker-compose ps -a
Visita http://localhost:3000/ según el puerto que se haya configurado y podrás acceder a tu aplicación.
Finalmente para detener su aplicación.
docker-compose down
Espero que este pequeño acercamiento a Docker les haya ayudado a despertar un poco la curiosidad y probar esta útil herramienta para el desarrollo y dejar atrás esos tortuosos momentos al montar un entorno desde 0 o el terror que da formatear un equipo en mitad de un desarrollo.
Les deseo un excelente dia y no se preocupen no es un adiós, estaré por aquí en un futuro contándoles alguna otra herramienta de desarrollo que haya probado y me haya ayudado
Autor: Alvaro Juan Pablo Aguirre Sierra
Ingeniero de Software en Elemental Lab