From 11660cb2b2bfe24a6f1ccbc942108cfa6a857051 Mon Sep 17 00:00:00 2001 From: Isidoro Nevares Date: Fri, 20 Mar 2026 17:30:41 +0100 Subject: [PATCH] Commit inicial --- .project | 2 +- Dockerfile | 4 + README.md | 274 +++++++++++------- docker-compose.yml | 10 +- pom.xml | 2 +- .../gestores/GestorConexionJDBC.java | 4 +- src/main/resources/config.properties | 4 +- 7 files changed, 180 insertions(+), 120 deletions(-) diff --git a/.project b/.project index 4fcf5f3..ac37574 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - aaee_ra4_proy1 + aaee_ra4_proy2 diff --git a/Dockerfile b/Dockerfile index 32e642a..f170eb9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,10 @@ WORKDIR /app # LA idea es simplificar el comando de arranque COPY --from=imagen_construccion /app/target/*.jar app.jar +# Variables de entorno (se cargan en fichero .env) +ENV DB_USER="nombre_usuario_bbdd" +ENV DB_PASSWORD="contraseña_usuario_bbdd" + # Puerto típico de Spring Boot (se podría cambiar si la aplicación usa otro) EXPOSE 8080 diff --git a/README.md b/README.md index 3a63d0f..7211888 100644 --- a/README.md +++ b/README.md @@ -1,113 +1,169 @@ -# Uso de Docker +# Gestión de secretos en distintos entornos (Java + Docker + CI/CD) -Este proyecto utiliza Docker para empaquetar y ejecutar la aplicación Spring Boot de forma aislada, garantizando que funcione igual en cualquier entorno. - -## Conceptos principales - -### Docker Engine -Es el motor de Docker, el servicio que construye imágenes, ejecuta contenedores y gestiona recursos (redes, volúmenes, etc.). Es el "runtime" que hace que todo funcione. - -### Imagen (`image`) -Plantilla inmutable que contiene el sistema base, el entorno de ejecución (JDK/JRE) y la aplicación (`.jar`). Se crea a partir de un `Dockerfile`. - -### Contenedor (`container`) -Instancia en ejecución de una imagen. Es aislado del sistema, ligero (comparte el kernel del host) y efímero (se puede borrar y recrear fácilmente). - -### Dockerfile -Un [Dockerfile](./Dockerfile) es un fichero de texto que contiene las instrucciones para construir una imagen Docker. - -- Define el entorno de ejecución de la aplicación: sistema base, dependencias y cómo arrancar la app. -- Es reproducible y versionable, lo que garantiza que la imagen se construya igual en cualquier máquina. -- En proyectos Spring Boot, suele usar multi-stage build para separar la fase de compilación de la de ejecución. - -#### Dockerfile (multi-stage) - -- **Etapa 1 (construcción):** compila la aplicación con Maven -- **Etapa 2 (ejecución):** ejecuta solo el `.jar` con un entorno ligero - -```dockerfile -# Etapa 1: construcción -FROM maven:3.9-eclipse-temurin-23 AS imagen_construccion - -WORKDIR /app -COPY pom.xml . -COPY src ./src - -RUN mvn clean package - -# Etapa 2: ejecución -FROM eclipse-temurin:23-jre AS imagen_ejecucion - -WORKDIR /app - -COPY --from=imagen_construccion /app/target/*.jar app.jar - -EXPOSE 8080 - -ENTRYPOINT ["java", "-jar", "app.jar"] -``` - -**Qué está pasando:** - -1. **Build:** se compila el proyecto y se genera el `.jar` -2. **Separación de responsabilidades:** Maven y el código fuente quedan solo en la etapa de build; el runtime solo contiene JRE y el `.jar` -3. **Optimización:** la imagen final es más ligera, con menor superficie de error y mayor seguridad - -## Ejecución y conceptos prácticos - -**Puertos** — permiten acceder a la aplicación desde fuera del contenedor: -```bash --p 8080:8080 -``` - -**Variables de entorno** — configuran la aplicación sin modificar el código: -```bash --e SPRING_DATASOURCE_URL=... -``` - -**Volúmenes** — persisten datos fuera del contenedor: -```bash --v /ruta/local:/ruta/contenedor -``` - -## Comandos básicos - -```bash -# Construir la imagen Docker a partir del Dockerfile -# -t mapamundi-app → asigna un nombre (tag) a la imagen -# . → indica el contexto de construcción (directorio actual, donde está el Dockerfile) -docker build -t mapamundi-app . - -# Ejecutar un contenedor a partir de la imagen creada -# -p 8080:8080 → mapea el puerto 8080 del host al 8080 del contenedor -# --name mapamundi_sb → asigna un nombre al contenedor para poder gestionarlo fácilmente -# mapamundi-app → nombre de la imagen que se va a ejecutar -docker run -p 8080:8080 --name mapamundi_sb mapamundi-app - -# Ver contenedores (en ejecución / todos) -docker ps -docker ps -a - -# Ver logs -docker logs -f mapamundi_sb - -# Detener y eliminar contenedores -docker stop mapamundi_sb -docker rm mapamundi_sb - -# Eliminar imagen -docker rmi mapamundi-app -``` - -## Resumen rápido - -| Concepto | Descripción | -|---|---| -| Docker Engine | Ejecuta y gestiona todo | -| Imagen | Plantilla inmutable de la aplicación | -| Contenedor | Instancia en ejecución de una imagen | -| Dockerfile | Instrucciones para construir la imagen | -| Multi-stage | Imágenes más ligeras y eficientes | +Este documento resume cómo manejar de manera segura credenciales y secretos en distintos entornos: desarrollo local, Docker, docker-compose y CI/CD (GitHub Actions). +--- + +## 1. Desarrollo local (Java) + +Leer secretos usando `System.getenv()`: + +```java +String user = System.getenv("DB_USER"); +String password = System.getenv("DB_PASSWORD"); + +if (user == null || password == null) { + throw new RuntimeException("Faltan variables de entorno DB_USER / DB_PASSWORD"); +} +``` + +Definir las variables en la sesión activa: + +**Windows (PowerShell):** +```powershell +$env:DB_USER="mi_usuario" +$env:DB_PASSWORD="mi_password" +``` + +**Linux / Mac / WSL:** +```bash +export DB_USER=mi_usuario +export DB_PASSWORD=mi_password +``` + +> Las variables solo existen en la sesión activa. Configura persistencia si es necesario (`.bashrc`, `.zshrc`, variables de entorno del sistema). + +--- + +## 2. Dockerfile + +Nunca incluir secretos directamente. Solo se declaran variables vacías como documentación: + +```dockerfile +# Documentación de variables esperadas en runtime +ENV DB_USER="" +ENV DB_PASSWORD="" +``` + +Los valores reales se pasan al ejecutar el contenedor. La aplicación sigue usando `System.getenv()` para leerlos. + +--- + +## 3. Docker (runtime) + +**Opción A — En línea:** +```bash +docker run -e DB_USER=mi_usuario -e DB_PASSWORD=mi_password -p 8080:8080 mi-imagen +``` + +**Opción B — Archivo `.env` (recomendado):** + +Archivo `.env`: +``` +DB_USER=mi_usuario +DB_PASSWORD=mi_password +``` + +```bash +docker run --env-file .env -p 8080:8080 mi-imagen +``` + +> Añade `.env` a `.gitignore` para que nunca se suba al repositorio. + +--- + +## 4. Docker Compose + +**Opción A — `env_file`:** +```yaml +version: "3.8" + +services: + app: + build: . + ports: + - "8080:8080" + env_file: + - .env + depends_on: + - db + + db: + image: mysql:8 + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: mi_base_datos + ports: + - "3306:3306" +``` + +**Opción B — Interpolación de variables:** +```yaml +services: + app: + build: . + ports: + - "8080:8080" + environment: + - DB_USER=${DB_USER} + - DB_PASSWORD=${DB_PASSWORD} +``` + +> `depends_on` solo espera a que el contenedor arranque, no a que MySQL esté listo para aceptar conexiones. Considera usar healthchecks o lógica de retry en la aplicación. + +--- + +## 5. CI/CD — GitHub Actions + +Definir los secretos en el repositorio: **Settings → Secrets and variables → Actions**. + +```yaml +name: Build & Deploy + +on: + push: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Build Docker image + run: docker build -t mi-app . + + - name: Run container with secrets + run: | + docker run \ + -e DB_USER=${{ secrets.DB_USER }} \ + -e DB_PASSWORD=${{ secrets.DB_PASSWORD }} \ + mi-app +``` + +> Nunca uses `echo ${{ secrets.DB_PASSWORD }}` en los logs: GitHub lo enmascara, pero es una mala práctica. + +--- + +## 6. Buenas prácticas generales + +- No subir `.env` al repositorio. +- No hardcodear credenciales en `config.properties` ni en el código. +- No incluir secretos en la imagen Docker. +- Documentar las variables necesarias sin poner valores reales (p. ej., en el `README`). +- Para producción avanzada: considerar **Secret Manager** (AWS Secrets Manager, HashiCorp Vault, Azure Key Vault). + +--- + +## 7. Tabla comparativa por entorno + +| Entorno | Mecanismo | Dónde se definen | ¿Se sube al repo? | +|---|---|---|---| +| Desarrollo local | `System.getenv()` | Variables de sesión / sistema | No | +| Dockerfile | `ENV` (vacío) | El propio Dockerfile | Sí (sin valores) | +| Docker runtime | `-e` / `--env-file` | Línea de comandos / `.env` | No (`.env` en `.gitignore`) | +| Docker Compose | `env_file` / `environment` | `.env` / `docker-compose.yml` | No (`.env` en `.gitignore`) | +| GitHub Actions | `secrets.*` | Settings del repositorio | No (gestionado por GitHub) | --- Fuentes: [ChatGPT](https://chat.openai.com) + [Claude](https://claude.ai) \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 6729cc1..39d2842 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,10 +15,12 @@ services: hostname: mysql.vdlp ports: - "3306:3306" - environment: - MYSQL_ROOT_PASSWORD: mysql_123 - MYSQL_USER: isidoronm - MYSQL_PASSWORD: mm123 + env_file: + - .env + environment: + MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} + MYSQL_USER: ${DB_USER} + MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_DATABASE: mapa_mundi volumes: - ./mysql/conf.d:/etc/mysql/conf.d diff --git a/pom.xml b/pom.xml index ab6c06d..3dc0b54 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.lapaloma.mapamundi aaee_mapamundi - 0.0.1 + 0.0.2 Prueba de Springboot Proyecto para poder probar el funcionamiento de SpringBoot diff --git a/src/main/java/org/lapaloma/mapamundi/gestores/GestorConexionJDBC.java b/src/main/java/org/lapaloma/mapamundi/gestores/GestorConexionJDBC.java index 6d3b856..c1b6020 100644 --- a/src/main/java/org/lapaloma/mapamundi/gestores/GestorConexionJDBC.java +++ b/src/main/java/org/lapaloma/mapamundi/gestores/GestorConexionJDBC.java @@ -15,8 +15,8 @@ public class GestorConexionJDBC { // Datos URL String urlBBDD = GestorFicheroConfiguracion.obtenerValor("jdbc.url"); - String usuario = GestorFicheroConfiguracion.obtenerValor("jdbc.usuario"); - String contrasenya = GestorFicheroConfiguracion.obtenerValor("jdbc.password"); + String usuario = System.getenv("DB_USER"); + String contrasenya = System.getenv("DB_PASSWORD"); String claseDriver = GestorFicheroConfiguracion.obtenerValor("jdbc.driver"); Class.forName(claseDriver); diff --git a/src/main/resources/config.properties b/src/main/resources/config.properties index 03930a1..d41c651 100644 --- a/src/main/resources/config.properties +++ b/src/main/resources/config.properties @@ -1,6 +1,4 @@ # Parámetros de conexión a la base de datos MapaMundi en SGDB MySQL jdbc.driver = com.mysql.cj.jdbc.Driver -jdbc.url = jdbc:mysql://192.168.1.36:3306/mapa_mundi -jdbc.usuario = isidoronm -jdbc.password = 1234 +jdbc.url = jdbc:mysql://172.16.0.181:3306/Mapa_Mundi