commit 54e872d46c82a938d46788e9f8a5948952283ee1 Author: mchiecher Date: Thu Sep 11 07:17:37 2025 -0300 Primer commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..2ccb4db --- /dev/null +++ b/README.md @@ -0,0 +1,117 @@ +# Introducci贸n a la Contenerizaci贸n 馃惓 + +Vamos a sumergirnos en el mundo de los contenedores, una tecnolog铆a que ha transformado la forma en que los desarrolladores empaquetan, distribuyen y ejecutan sus aplicaciones. Si bien es un concepto que a menudo se asocia con el backend, entender los fundamentos de los contenedores es crucial para cualquier desarrollador, incluido el frontend. + +## 驴Qu茅 es un Contenedor? + +Un contenedor es una unidad de software empaquetada y estandarizada que puede incluir todo lo necesario para ejecutar una aplicaci贸n: el c贸digo, el entorno de ejecuci贸n, las librer铆as del sistema y las dependencias. + +Piensen en un contenedor como una caja 馃摝 totalmente aislada que contiene su aplicaci贸n. No importa en qu茅 m谩quina o sistema operativo la pongan, la aplicaci贸n dentro de la caja funcionar谩 exactamente igual porque tiene todo lo que necesita consigo. Esto resuelve el cl谩sico problema de **"funciona en mi m谩quina"**. + +> **Nota:** A diferencia de las m谩quinas virtuales (VMs), los contenedores son mucho m谩s ligeros y r谩pidos porque comparten el kernel del sistema operativo del host en lugar de virtualizar un sistema operativo completo. + +## Docker: El Rey de los Contenedores + +Docker es la plataforma m谩s popular para crear, gestionar y ejecutar contenedores. Vamos a ver los componentes principales del ecosistema de Docker. + +### Arquitectura de un Host con Docker + +![Arquitectura de Docker](dockerarchitecture.webp) + +Un host con Docker tiene dos partes principales: + +- **Docker Daemon (o Engine):** Es el proceso que se ejecuta en segundo plano y gestiona todas las operaciones de los contenedores. Se encarga de construir im谩genes, ejecutar contenedores y manejar la red y el almacenamiento. + +- **Docker CLI (Cliente):** Es la herramienta de l铆nea de comandos que usamos para interactuar con el Docker Daemon. Cuando escribes un comando como `docker run`, el cliente se comunica con el daemon para ejecutar la acci贸n. + +### Im谩genes vs. Contenedores + +Es crucial entender la diferencia entre estos dos conceptos: + +- **Imagen:** Una imagen es una plantilla inmutable que contiene las instrucciones para crear un contenedor. Las im谩genes se construyen a partir de un Dockerfile. + +- **Contenedor:** Un contenedor es una instancia en ejecuci贸n de una imagen. Se pueden crear m煤ltiples contenedores a partir de una misma imagen. + +## Conceptos Clave en Docker + +### Persistencia de Datos + +Por defecto, los contenedores son ef铆meros. Esto significa que cuando se detiene y se elimina un contenedor, todos los datos que estaban dentro de 茅l se pierden. Para que los datos persistan, usamos **vol煤menes**. + +Un volumen es un mecanismo de almacenamiento que existe fuera del ciclo de vida del contenedor. Es un directorio en el sistema de archivos del host que se "monta" o se enlaza a un directorio dentro del contenedor. De esta manera, aunque el contenedor sea eliminado, los datos en el volumen permanecen. + +### Exposici贸n de Puertos + +Si su aplicaci贸n se ejecuta dentro de un contenedor, 驴c贸mo se conecta un usuario a ella? La respuesta es **exponiendo puertos**. + +La exposici贸n de puertos crea un enlace entre un puerto del host (tu m谩quina) y un puerto del contenedor. Por ejemplo, si tu aplicaci贸n frontend se ejecuta en el puerto 3000 dentro del contenedor, puedes mapear el puerto 8080 de tu m谩quina al puerto 3000 del contenedor (`-p 8080:3000`). As铆, al acceder a `localhost:8080` desde tu navegador, en realidad est谩s accediendo a la aplicaci贸n dentro del contenedor. + +## Comandos B谩sicos de Docker CLI + +Ahora, vamos a ver los comandos que m谩s usar谩n en su d铆a a d铆a. + +| Comando | Descripci贸n | Ejemplo de Uso | +|---------|-------------|----------------| +| `docker pull` | Descarga una imagen de un registro (como Docker Hub). | `docker pull node:18-alpine` | +| `docker build` | Construye una imagen a partir de un Dockerfile. | `docker build -t mi-app-frontend .` | +| `docker run` | Crea y ejecuta un contenedor a partir de una imagen. | `docker run -d -p 8080:3000 mi-app-frontend` | +| `docker ps` | Lista los contenedores en ejecuci贸n. Usa `-a` para ver todos (ejecutando y detenidos). | `docker ps -a` | +| `docker stop` | Detiene un contenedor en ejecuci贸n. | `docker stop ` | +| `docker start` | Inicia un contenedor que est谩 detenido. | `docker start ` | +| `docker rm` | Elimina un contenedor detenido. | `docker rm ` | +| `docker rmi` | Elimina una imagen. | `docker rmi ` | +| `docker exec` | Ejecuta un comando dentro de un contenedor en ejecuci贸n. | `docker exec -it /bin/bash` | + +## Docker Compose: Orquestaci贸n de Aplicaciones + +Cuando una aplicaci贸n se vuelve m谩s compleja, con un frontend, un backend y una base de datos, ejecutar cada contenedor individualmente se vuelve tedioso. Aqu铆 es donde entra **Docker Compose**. + +Docker Compose es una herramienta para definir y ejecutar aplicaciones multi-contenedor usando un solo archivo `docker-compose.yml`. + +### Ejemplo de docker-compose.yml + +```yaml +version: '3.8' + +services: + frontend: + build: . + ports: + - "8080:3000" + volumes: + - ./src:/usr/src/app/src + container_name: mi_app_frontend + command: npm start + + backend: + image: mi-backend-imagen:1.0 + ports: + - "5000:5000" +``` + +#### Explicaci贸n de las propiedades: + +- **`version`:** Especifica la versi贸n del formato del archivo Compose. +- **`services`:** Define los servicios (contenedores) de la aplicaci贸n. +- **`frontend` y `backend`:** Son los nombres de los servicios que vamos a crear. +- **`build: .`:** Le dice a Docker que construya la imagen para el servicio frontend usando el Dockerfile que est谩 en el directorio actual. +- **`ports`:** Mapea los puertos del host a los puertos del contenedor. +- **`volumes`:** Monta un volumen. En este caso, el c贸digo fuente local (`./src`) se sincroniza con el c贸digo dentro del contenedor, lo que permite ver los cambios en tiempo real sin tener que reconstruir la imagen. 隆Ideal para desarrollo! +- **`container_name`:** Asigna un nombre espec铆fico al contenedor. + +### Comandos 脷tiles de Docker Compose + +| Comando | Descripci贸n | Ejemplo de Uso | +|---------|-------------|----------------| +| `docker compose up` | Construye, crea y levanta todos los servicios definidos en el archivo docker-compose.yml. | `docker compose up -d` Modo que ejecuta los contenedores en segundo plano.| +| `docker compose down` | Detiene y elimina los contenedores, redes y vol煤menes creados por up. | `docker compose down` | +| `docker compose ps` | Lista los servicios de la aplicaci贸n. | `docker compose ps` | +| `docker compose logs` | Muestra los logs de los servicios. | `docker compose logs frontend` | + +## 驴Por qu茅 deber铆amos usar Docker? + +- **Entorno de desarrollo consistente:** Todos en el equipo trabajan con el mismo entorno, eliminando problemas de dependencias. + +- **Aislamiento:** Permite probar diferentes versiones de Node.js o de librer铆as sin afectar el sistema global. + +- **Despliegue simplificado:** El mismo contenedor que se usa para desarrollo se puede usar en producci贸n, lo que reduce las incompatibilidades. \ No newline at end of file diff --git a/backend/build/Dockerfile b/backend/build/Dockerfile new file mode 100644 index 0000000..8253328 --- /dev/null +++ b/backend/build/Dockerfile @@ -0,0 +1,31 @@ +# =========================================== +# DOCKERFILE PARA APLICACI脫N BACKEND PYTHON +# =========================================== + +# Usamos una imagen base ligera de Python 3.10 basada en Alpine Linux +# Alpine es una distribuci贸n Linux muy peque帽a (~5MB) que reduce el tama帽o de la imagen +# python:3.10-alpine incluye Python 3.10 y las herramientas b谩sicas necesarias +FROM python:3.10-alpine + +# Establecemos el directorio de trabajo dentro del contenedor +# Todas las operaciones posteriores (COPY, RUN, CMD) se ejecutar谩n desde este directorio +# /usr/src/app es una convenci贸n com煤n para aplicaciones en contenedores +WORKDIR /usr/src/app + +# Copiamos el archivo de la aplicaci贸n Python desde el host al contenedor +# El primer par谩metro (app.py) es el archivo fuente en el host +# El segundo par谩metro (.) es el destino en el contenedor (directorio actual = /usr/src/app) +# Esto copia app.py al directorio de trabajo del contenedor +COPY app.py . + +# Exponemos el puerto 8000 que usar谩 el servidor web +# Esta instrucci贸n es solo documentativa - no abre el puerto autom谩ticamente +# El puerto se abre realmente cuando se ejecuta el contenedor con -p o en docker-compose +# Es una buena pr谩ctica documentar qu茅 puertos usa la aplicaci贸n +EXPOSE 8000 + +# Comando por defecto para iniciar la aplicaci贸n cuando se ejecute el contenedor +# Se ejecuta autom谩ticamente cuando se inicia el contenedor (a menos que se sobrescriba) +# Formato de array: ["comando", "argumento1", "argumento2"] +# python app.py ejecutar谩 el archivo app.py con el int茅rprete de Python +CMD ["python", "app.py"] diff --git a/backend/build/app.py b/backend/build/app.py new file mode 100644 index 0000000..795ba11 --- /dev/null +++ b/backend/build/app.py @@ -0,0 +1,22 @@ +import http.server +import socketserver + +# Puerto en el que se ejecutar谩 el servidor +PORT = 8000 + +# Creamos un manejador de solicitudes HTTP +class MyHandler(http.server.SimpleHTTPRequestHandler): + def do_GET(self): + # Establecemos el c贸digo de respuesta y el tipo de contenido + self.send_response(200) + self.send_header("Content-type", "text/html") + self.end_headers() + + # Enviamos la respuesta HTML + self.wfile.write(bytes("

Hola desde el Backend

Esta es una aplicacion de ejemplo con el servidor web de Python.

", "utf-8")) + +# Configuramos el servidor +with socketserver.TCPServer(("", PORT), MyHandler) as httpd: + # Ahora el mensaje se imprime solo una vez, cuando el servidor se levanta correctamente + print(f"Servidor backend corriendo en el puerto {PORT}") + httpd.serve_forever() \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b57fad3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,39 @@ +# Versi贸n del formato de Docker Compose +# La versi贸n 3.8 es compatible con Docker Engine 19.03.0+ +# Actualmente especificar la versi贸n es opcional. +version: '3.8' + +# Secci贸n que define todos los servicios (contenedores) de la aplicaci贸n +services: + # Servicio para la aplicaci贸n frontend de Node.js + frontend: + # Configuraci贸n de construcci贸n de la imagen Docker + build: + # Directorio donde se encuentra el Dockerfile para construir la imagen + # En este caso, busca el Dockerfile en la carpeta ./frontend/build + context: ./frontend/build + # Mapeo de puertos entre el host y el contenedor + # Formato: "puerto_host:puerto_contenedor" + # El puerto 3000 del host se mapea al puerto 3000 del contenedor + ports: + - "3000:3000" + # Las l铆neas siguientes (comentadas) definen vol煤menes (bind mounts): + # montan archivos/carpetas del host dentro del contenedor + #volumes: + # - ./frontend/data/index.js:/usr/src/app/index.js + + # Servicio para la aplicaci贸n backend (Python/Flask) + backend: + # Configuraci贸n de construcci贸n de la imagen Docker + build: + # Directorio donde se encuentra el Dockerfile para construir la imagen + # En este caso, busca el Dockerfile en la carpeta ./backend/build + context: ./backend/build + # Mapeo de puertos entre el host y el contenedor + # El puerto 8000 del host se mapea al puerto 8000 del contenedor + ports: + - "8000:8000" + # Comando personalizado para ejecutar cuando se inicie el contenedor + # python -u: ejecuta Python con salida sin buffer (unbuffered) + # app.py: el archivo principal de la aplicaci贸n Python + command: python -u app.py diff --git a/dockerarchitecture.webp b/dockerarchitecture.webp new file mode 100644 index 0000000..611b803 Binary files /dev/null and b/dockerarchitecture.webp differ diff --git a/frontend/build/Dockerfile b/frontend/build/Dockerfile new file mode 100644 index 0000000..2e80426 --- /dev/null +++ b/frontend/build/Dockerfile @@ -0,0 +1,43 @@ +# =========================================== +# DOCKERFILE PARA APLICACI脫N FRONTEND NODE.JS +# =========================================== + +# Usamos una imagen base ligera de Node.js 18 basada en Alpine Linux +# Alpine es una distribuci贸n Linux muy peque帽a (~5MB) que reduce el tama帽o de la imagen +# node:18-alpine incluye Node.js 18 y npm, las herramientas necesarias para aplicaciones JavaScript +FROM node:18-alpine + +# Establecemos el directorio de trabajo dentro del contenedor +# Todas las operaciones posteriores (COPY, RUN, CMD) se ejecutar谩n desde este directorio +# /usr/src/app es una convenci贸n com煤n para aplicaciones en contenedores +WORKDIR /usr/src/app + +# Copiamos SOLO los archivos package.json y package-lock.json (si existe) +# El patr贸n package*.json copia ambos archivos: package.json y package-lock.json +# Esto se hace ANTES de copiar el resto del c贸digo para aprovechar la cach茅 de Docker +# Si solo cambia el c贸digo fuente (no las dependencias), Docker reutiliza la capa de npm install +COPY package*.json ./ + +# Instalamos las dependencias de Node.js definidas en package.json +# npm install lee package.json y descarga todas las dependencias listadas +# Se ejecuta en esta capa para que Docker pueda cachear el resultado +# Si las dependencias no cambian, esta capa se reutiliza en builds posteriores +RUN npm install + +# Copiamos TODO el resto del c贸digo de la aplicaci贸n al contenedor +# El primer punto (.) representa el directorio actual del host (donde est谩 el Dockerfile) +# El segundo punto (.) representa el directorio de trabajo del contenedor (/usr/src/app) +# Esto incluye index.js, archivos est谩ticos, etc. (excluyendo lo que est茅 en .dockerignore) +COPY . . + +# Exponemos el puerto 3000 que usar谩 la aplicaci贸n web +# Esta instrucci贸n es solo documentativa - no abre el puerto autom谩ticamente +# El puerto se abre realmente cuando se ejecuta el contenedor con -p o en docker-compose +# Es una buena pr谩ctica documentar qu茅 puertos usa la aplicaci贸n +EXPOSE 3000 + +# Comando por defecto para iniciar la aplicaci贸n cuando se ejecute el contenedor +# Se ejecuta autom谩ticamente cuando se inicia el contenedor (a menos que se sobrescriba) +# Formato de array: ["comando", "argumento1", "argumento2"] +# node index.js ejecutar谩 el archivo index.js con el runtime de Node.js +CMD ["node", "index.js"] \ No newline at end of file diff --git a/frontend/build/index.js b/frontend/build/index.js new file mode 100644 index 0000000..a94d7c9 --- /dev/null +++ b/frontend/build/index.js @@ -0,0 +1,14 @@ +// Importamos el m贸dulo express +const express = require('express'); +const app = express(); +const port = 3000; + +// Definimos la ruta ra铆z que enviar谩 una respuesta +app.get('/', (req, res) => { + res.send('

隆Hola desde el Frontend!

Esta es una aplicacion de ejemplo en Node.js.

'); +}); + +// El servidor escucha en el puerto definido +app.listen(port, () => { + console.log(`Aplicacion frontend corriendo en http://localhost:${port}`); +}); diff --git a/frontend/build/package.json b/frontend/build/package.json new file mode 100644 index 0000000..5a11e3e --- /dev/null +++ b/frontend/build/package.json @@ -0,0 +1,13 @@ +{ + "name": "frontend-app", + "version": "1.0.0", + "description": "Una aplicacion de ejemplo en Node.js para Docker", + "main": "index.js", + "scripts": { + "start": "node index.js" + }, + "dependencies": { + "express": "^4.18.2" + } + } + \ No newline at end of file diff --git a/frontend/data/index.js b/frontend/data/index.js new file mode 100644 index 0000000..bb7b19b --- /dev/null +++ b/frontend/data/index.js @@ -0,0 +1,14 @@ +// Importamos el m贸dulo express +const express = require('express'); +const app = express(); +const port = 3000; + +// Definimos la ruta ra铆z que enviar谩 una respuesta +app.get('/', (req, res) => { + res.send('

隆Hola desde el Frontend con los archivos residentes en el host!

Esta es una aplicacion de ejemplo en Node.js.

'); +}); + +// El servidor escucha en el puerto definido +app.listen(port, () => { + console.log(`Aplicacion frontend corriendo en http://localhost:${port}`); +});