Table of Contents
Despliegue de aplicaciones web
Aqui vamos a ver como poner en marcha una aplicación web hecha con Spring Boot como paquete jar, de forma que no necesitemos de un servidor de aplicaciones para desplegar y ponerla en marcha.
Crear una imagen docker de la API
Empaquetar la aplicación
El primer paso será empaquetar la aplicación en formato jar
santi@zenbook:$ mvn clean package
Eso hará que se genera un fichero jar del estilo a myshop-0.1.jar en la carpeta target del proyecto, dependiendo de como hayamos definido las propiedades artifactId y version en el fichero pom.xml. Será el fichero que tendremos que llevar a la máquina donde queramos desplegar la aplicación. Hay que tener en cuenta que necesitaremos instalar el JDK en esa máquina para que pueda ejecutarla.
Crear la imagen Docker
Creamos el fichero Dockerfile en la carpeta del proyecto. De acuerdo a nuestro proyecto y su fichero pom.xml
, nuestro artifactId es reactive-api
y la versión 0.1
, por lo que el paquete creado tras ejecutar mvn clean package
será reactive-api-0.1.jar
y estará ubicado en la carpeta target
que se habrá creado en nuestro proyecto.
- Dockerfile
FROM eclipse-temurin:17-jdk-alpine VOLUME /tmp COPY target/reactive-api-0.1.jar app.jar ENTRYPOINT ["java","-jar","app.jar"]
Para crear la imagen, abrimos una consola y lanzamos el siguiente comando. La imagen se creará con el nombre reactive-api
.
santi@zenbook:$ docker build -t reactive-api .
Crear un proyecto Docker Compose para pruebas en local
Nuestra API está realmente compuesta de dos partes: La propia API escrita en Java con Spring Boot y la base de datos MongoDB que utilizamos para almacenar/consultar la información. Asi, necesitaremos crear un proyecto docker compose con dos servicios (API + Bases de Datos) para lanzarlo en nuestro equipo y, por ejemplo, hacer pruebas.
Para eso, el primer paso será crear el fichero docker-compose.yaml
donde se definen ambos servicios. EN el caso de la API partiremos de la imagen que ya hemos creado anteriormente.
En cualquier caso, antes de eso, crearemos un fichero .env
para almacenar alli las variables de entorno que necesitemos para configurar nuestro proyecto docker compose:
- .env
MONGODB_DATABASE=reactiveapi MONGODB_PORT=27017 SPRING_PORT=8080
Y ahora el fichero docker-compose.yaml
:
- docker-compose.yaml
version: "3.4" name: reactive-api-mongodb services: mongodb: image: mongo:7.0.7 container_name: mongodb restart: unless-stopped env_file: ./.env ports: - $MONGODB_PORT:$MONGODB_PORT volumes: - db:/data/db app: image: reactive-api container_name: reactive-api env_file: ./.env ports: - $SPRING_PORT:$SPRING_PORT environment: SPRING_APPLICATION_JSON: '{ "spring.data.mongodb.uri" : "mongodb://mongodb:$MONGODB_PORT/$MONGODB_DATABASE?authSource=admin" }' depends_on: - mongodb restart: on-failure volumes: db:
Ahora podemos lanzar nuestra API junto con su base de datos ejecutando el siguiente comando:
santi@zenbook:$ docker compose up -d
Hemos mapeado los puertos de ambos contenedores a nuestro equipo local usando los mismos valores, por lo que podemos lanzar peticiones a la API haciéndolas directamente a http://localhost:8080
y también podemos conectarnos a MongoDB, por por ejemplo con Studio 3T, conectándonos a localhost:27017
Desplegar en AWS
Desplegar la API en un servidor
Asi, si suponemos que nuestra máquina remota ya está en marcha y tiene asociado un dominio como codeandcoke.com, tendremos que copiar ese fichero jar (únicamente) a dicha máquina. Tendremos que asegurarnos de que nuestro usuario en la máquina tenga permisos sobre la carpeta que lo copiemos (en mi caso lo dejaré en la carpeta /opt
)
santi@zenbook:$ scp target/myshop-0.0.1-SNAPSHOT.jar santi@codeandcoke.com:/opt
Ejecutar la aplicación en el servidor
Ahora, iniciaremos sesión en la máquina remota para lanzar la aplicación:
santi@zenbook:$ ssh santi@codeandcoke.com santi@codeandcoke.com:$ cd /opt santi@codeandcoke.com:$ nohup java -jar myshop-0.0.1-SNAPSHOT.jar > myshop.log 2>&1 &
- Utlizamos el comando
nohup
para evitar que la aplicación se detenga al cerrar la sesión de terminal desde donde la lanzamos java -jar myshop-0.0.1-SNAPSHOT.jar
lanza la aplicación> myshop.log
redirige toda la salida a un fichero que nos servirá de log de la aplicación2>&1 &
redirige toda la salida de error a la salida estándar (que irá al fichero log) y lo ejecuta en segundo plano, para dejar libre la terminal durante el resto de la sesión
También podemos prepararnos un script bash para evitar que escribir ese comando cada vez que queramos desplegar una nueva versión (puesto que además tendremos que detener la existente)
Acceder a la aplicación
Suponiendo que nuestra aplicación escucha en el puerto 8080, podremos comprobar que funciona sin problemas si accedemos, desde nuestro navegador a http://codeandcoke.com:8080
Modificar el puerto de acceso
El siguiente paso interesante sería evitar que el usuario tuviera que especificar el puerto a la hora de acceder a la aplicación desde el navegador. Eso podría evitarse, por ejemplo, modificando el puerto en el que ésta escucha (y pasarlo al 80). Esto no es ningún problema si la aplicación “vive” sola en la máquina remota.
Configurar Apache como Proxy para la aplicación
Si por el contrario tenemos algún servidor Apache funcionando, tendremos el puerto 80 ya ocupado. Si ocurre esto, podemos dejar que la aplicación siga escuchando en el puerto 8080 (o cualquier otro) y hacer que sea Apache quien nos haga de proxy. Podríamos definir un host virtual para el dominio codeandcoke.com
indicando a Apache que lo que tiene que hacer es llevar a los usuarios al puerto 8080 que es donde está la aplicación. Asi, los usuarios accederán a http://codeandcoke.com para acceder a nuestra aplicación.
Para eso, definimos el host virtual en Apache de forma habitual:
<VirtualHost *:80> ServerAdmin info@codeandcoke.com ServerName codeandcoke.com ServerAlias www.codeandcoke.com ErrorLog "codeandcoke.com-error.log" CustomLog "codeandcoke.com-access.log" combined </VirtualHost>
Y añadimos un par de líneas más para indicar que tiene que hacer de proxy con una aplicación ya desplegada:
. . . ProxyPass / ajp://localhost:8080/ ProxyPassReverse / ajp://localhost:8080/
Quedando la configuración del sitio virtual:
<VirtualHost *:80> ServerName codeandcoke.com ServerAlias www.codeandcoke.com ErrorLog "codeandcoke.com-error.log" CustomLog "codeandcoke.com-access.log" combined ProxyPass / ajp://localhost:8080/ ProxyPassReverse / ajp://localhost:8080/ </VirtualHost>
Puede que tengamos que activar el módulo AJP de Apache si no lo está ya:
santi@zenbook:$ sudo a2enmod proxy_ajp . . . santi@zenbook:$ sudo service apache2 restart . . .
Puedes ver aqui más información sobre cómo configurar Apache
Si estamos desplegando la aplicación como paquete war con un Apache Tomcat, necesitaremos configurar tanto Apache para que haga de Proxy como Tomcat para activar el protocolo AJP. Puedes ver cómo hacerlo aqui
© 2021-2023 Santiago Faci