JavaRush /Blog Java /Random-ES /Implementamos el despliegue de aplicaciones - "Proyecto J...

Implementamos el despliegue de aplicaciones - "Proyecto Java de la A a la Z"

Publicado en el grupo Random-ES
Hola a todos. Continuamos la serie de artículos sobre cómo escribir su proyecto. “Proyecto Java de la A a la Z”: Implementación del despliegue de aplicaciones - 1

ordenar las ramas

Lo importante es que, para no perderme en las ramas y su orden en el repositorio, decidí cambiarles el nombre agregando el prefijo STEP_{number} . Por ejemplo, tenemos tres sucursales además de la principal:
  • JRTB-0
  • JRTB-2
  • JRTB-3
No comprenderá de inmediato cuál debería ir después de cuál. Así que les cambiaré el nombre de la siguiente manera:
  • STEP_1_JRTB-0 - primer paso
  • STEP_2_JRTB-2 - segundo paso
  • STEP_3_JRTB-3 - tercer paso
Y así sucesivamente para los próximos artículos. Para cambiar el nombre de las ramas, vaya a la página del repositorio , busque el cuadro de ramas , sígalo: “Proyecto Java de la A a la Z”: Implementación de la implementación de aplicaciones - 2Debajo de cada rama, haga clic en el lápiz y cambie el nombre de la rama: “Proyecto Java de la A a la Z”: Implementación del despliegue de aplicaciones - 3Y como resultado obtenemos: “Proyecto Java de la A a la Z”: Implementación del despliegue de aplicaciones - 4Por cierto, todos los que se suscribieron a mi canal de Telegram encontraron Inmediatamente me di cuenta de que cambié el nombre de las ramas.

Un poco sobre Docker

¿Qué es Docker? En definitiva, es una herramienta con la que se pueden desplegar (implementar) aplicaciones de forma rápida y segura, creando para ellas una infraestructura cerrada, necesaria sólo para ellas. Todavía es difícil, lo entiendo. En general, Docker puede entenderse como una plataforma de desarrollo donde se puede trabajar de forma rápida y eficiente. Docker puede entenderse como un programa que se ejecuta en un servidor. Este programa tiene la capacidad de almacenar contenedores con aplicaciones. ¿Qué es un contenedor? Esta es una infraestructura separada a la que puede agregar todo lo que necesita. Por ejemplo, para una aplicación Java necesitamos un JRE para ejecutar la aplicación, el contenedor tendrá esto, necesitaremos algún otro software; podemos agregarlo. O tal vez necesitemos Linux y un contenedor de servlets Tomcat. Esto también se puede hacer. Los contenedores se crean en base a una imagen: es decir, se trata de una plantilla específica en la que está escrito todo lo necesario para crear un contenedor Docker. ¿Cómo crear esta imagen? En nuestro caso, necesitaremos crear un Dockerfile en la raíz del proyecto que describa lo que debería haber en el contenedor. Como no queremos exponer el token del bot en ninguna parte, tendremos que recurrir a pasarlo cada vez que queramos implementar la aplicación. Puedes leer más sobre este tema aquí y aquí .

Escribimos JRTB-13

Necesitamos configurar un proceso de implementación rápido y sencillo para nuestra aplicación en el servidor. Es decir, para una máquina que funciona 24 horas al día, 7 días a la semana. Tomemos Docker como base. Pero no hay ninguna tarea en nuestra lista que sea responsable de agregar esta funcionalidad. De alguna manera me lo perdí al crearlo. No hay problema, lo crearemos ahora. Vamos a la pestaña de creación de incidencias en GitHub y seleccionamos Solicitud de característica: “Proyecto Java de la A a la Z”: Implementación del despliegue de aplicaciones - 5Agrega una descripción de la tarea, criterios para su aceptación, establece a qué proyecto pertenece esta incidencia y puedes crear una nueva incidencia: “Proyecto Java de la A a la Z”: Implementación del despliegue de aplicaciones - 6Ahora, para mostrar que la tarea ha sido aceptado para trabajar, cambie el estado de la tarea de Por hacer a En progreso: “Proyecto Java de la A a la Z”: Implementación del despliegue de aplicaciones - 7este será un artículo difícil. Si tienes algún problema, escribe en los comentarios: los monitorearé y responderé lo mejor que pueda. Este será un pequeño servicio de atención al cliente :D

Creando un archivo Docker

¿Qué es un archivo acoplable? Para Docker, este es un script (instrucciones paso a paso) sobre cómo crear una imagen para un contenedor Docker. Para que nuestra aplicación funcione, necesitamos el JDK, versión 11. Es decir, necesitamos encontrar la imagen de la ventana acoplable JDK 11 y agregarla a nuestra imagen. Esto es algo parecido a cómo agregamos una dependencia a una memoria. Docker tiene DockerHub para este propósito . Para descargar imágenes localmente, debe registrarse allí. Después del registro, busquemos JDK11. Por lo que encontré, este es el contenedor: adoptopenjdk/openjdk11 . La descripción de este contenedor tiene lo que se necesita para el dockerfile:
FROM adoptopenjdk/openjdk11:ubi
RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]
Arreglemos la carpeta de la que tomamos el archivo jar. Lo tenemos en la carpeta de destino después de ejecutar la tarea maven del paquete mvn. Antes de hacer todo esto, basándonos en la rama principal actualizada, creamos una nueva para nuestra tarea: STEP_4_JRTB-13 . Ahora puedes trabajar. En la raíz del proyecto, cree un archivo sin la extensión Dockerfile y agregue lo siguiente dentro:
FROM adoptopenjdk/openjdk11:ubi
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
La primera línea es en qué se basará la imagen: adoptopenjdk/openjdk11. La segunda línea es para agregar un argumento a la imagen llamada JAR_FILE, que se encuentra en la carpeta de destino. Además, la carpeta actual está determinada por la ubicación del Dockerfile. Tercera línea: copie el archivo jar de nuestro proyecto en la imagen de la ventana acoplable. La última línea contiene esencialmente una matriz creada a partir del comando en la terminal, que estaba separada por un espacio. Es decir, al final se ejecutará lo siguiente: “java -jar /app.jar” Para mantener el token del bot en secreto, al iniciar el contenedor necesitaremos pasar dos variables: el nombre del bot y su token. Para hacer esto, escribiremos una consulta que debería iniciar nuestro proyecto con variables. ¿Y, cómo hacerlo? Necesitas buscarlo en Google: aquí está el primer enlace con una descripción normal. ¿Qué queremos hacer? Tenemos dos variables en el archivo application.properties que definimos allí:
  • bot.nombre de usuario
  • token.bot
Quiero ejecutar un contenedor acoplable y pasar mi valor allí cada vez para que nadie pueda verlos. Sé que en SpringBoot, las variables de entorno que se configuran cuando se inicia el proyecto jar tendrán prioridad sobre las del archivo application.properties. Para pasar una variable en una solicitud, debe agregar la siguiente construcción: -D{nombre de variable}=”{valor de variable}” . No agregamos llaves;) Recibiremos una solicitud que iniciará nuestra aplicación con valores predefinidos: el nombre y el token del bot: java -jar -Dbot.username=”test.javarush.community_bot” -Dbot. token=”dfgkdjfglkdjfglkdjfgk” *.jar Ahora necesitamos pasar estas variables dentro del contenedor acoplable. Esta es una variable de entorno. Para asegurarnos de que en el futuro nuestra base de datos funcione fluidamente y sin problemas con nuestra aplicación, usaremos docker-compose. Esta es una herramienta independiente en la que puede organizar el trabajo, el inicio y las dependencias entre contenedores. En otras palabras, es un complemento de Docker para administrar contenedores de una infraestructura. Además, antes de ejecutar docker-compose, debemos asegurarnos de haber retirado todos los cambios de código del servidor, haber creado la aplicación y haber detenido la versión anterior. Para esto usaremos un script bash. Vaya... Todo suena difícil, estoy de acuerdo. Pero trabajar con la configuración de la implementación de aplicaciones es siempre un proceso tedioso y complejo. Por tanto, tenemos un esquema bastante bueno:
  1. Ejecutemos el script bash.
  2. El script bash ejecuta docker-compose.
  3. Docker-compose lanza un contenedor acoplable con nuestra aplicación.
  4. El contenedor Docker ejecuta nuestra aplicación.
Y ahora debemos asegurarnos de que dos variables, el nombre del bot y su token, vayan del punto 1 al punto 4. Y para que estas dos variables se utilicen al iniciar nuestra aplicación Java. Vayamos del final al principio. Ya sabemos qué comando se debe ejecutar para iniciar el jarnik. Por tanto, configuraremos el Dockerfile para que aprenda a aceptar dos variables y las pase a la solicitud. Para hacer esto, reduzcamos el Dockerfile a la siguiente forma:
FROM adoptopenjdk/openjdk11:ubi
ARG JAR_FILE=target/*.jar
ENV BOT_NAME=test.javarush_community_bot
ENV BOT_TOKEN=1375780501:AAE4A6Rz0BSnIGzeu896OjQnjzsMEG6_uso
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-Dbot.username=${BOT_NAME}", "-Dbot.token=${BOT_TOKEN}", "-jar", "/app.jar"]
Puede ver que agregamos dos líneas y actualizamos ENTRYPOINT. Líneas:
ENV BOT_NAME=test.javarush_community_bot
ENV BOT_TOKEN=1375780501:AAE4A6Rz0BSnIGzeu896OjQnjzsMEG6_uso
declarar variables dentro del archivo codificador. Por defecto tienen un valor especificado. Si, al crear una imagen a partir de este archivo acoplable, se pasan variables de entorno con dichos nombres, los valores serán diferentes. Y en ENTRYPOINT agregamos algunos elementos más que leerán estas variables de entorno:
"-Dbot.username=${BOT_NAME}", "-Dbot.token=${BOT_TOKEN}"
Aquí puedes ver que dentro de la línea, usando la construcción ${}, se pasarán los valores de BOT_NAME y BOT_TOKEN. A continuación, debemos enseñar cómo recibir y pasar estas variables a Docker-Compose.

Crear docker-compose.yml

Sería bueno que leyera sobre el formato YAML por separado; de lo contrario, el artículo ya está creciendo a pasos agigantados. Para nosotros, esta es solo otra descripción de variables del tipo .properties. Solo en las propiedades se escribe mediante un punto, pero en YAML esto se hace un poco más hermoso. Por ejemplo, así. Dos variables en .properties: javarush.telegram.bot.name=ivan javarush.telegram.bot.token=pupkin Pero en .yaml (igual que .yml) será así:
javarush:
	telegram:
		bot:
		  name: ivan
		  token: pupkin
La segunda opción es más bella y comprensible. Los espacios deben ser exactamente como se indica arriba. Traduzcamos nuestras application.properties y application.yml de alguna manera. Primero necesitas crearlo. En la raíz del proyecto, cree un archivo docker-compose.yml y escriba allí lo siguiente:
version: '3.1'

services:
 jrtb:
   build:
     context: .
   environment:
     - BOT_NAME=${BOT_NAME}
     - BOT_TOKEN=${BOT_TOKEN}
   restart: always
La primera línea es la versión de Docker-Compose. servicios: dice que todas las líneas siguientes después de esto (se desplazarán) se refieren a los servicios que estamos configurando. Hasta ahora sólo tenemos uno de ellos: una aplicación Java llamada jrtb . Y ya debajo estarán todas sus configuraciones. Por ejemplo, construir: contexto: . dice que buscaremos el Dockerfile en el mismo directorio que docker-compose.yml. Pero la sección entorno: será responsable de garantizar que pasemos las variables de entorno necesarias al Dockerfile. Justo lo que necesitamos. Por lo tanto, pasamos las variables a continuación. Docker-compose los buscará en las variables del entorno operativo del servidor. Agreguémoslos al script bash.

Creando scripts bash

El último paso es crear un script bash. Crea un archivo llamado start.sh en la raíz del proyecto y escribe lo siguiente allí:
#!/bin/bash

# Pull new changes
git pull

# Prepare Jar
mvn clean
mvn package

# Ensure, that docker-compose stopped
docker-compose stop

# Add environment variables
export BOT_NAME=$1
export BOT_TOKEN=$2

# Start new deployment
docker-compose up --build -d
La primera línea es necesaria para todos los scripts de bash: no funcionará sin ella. Y luego, solo un conjunto de comandos en la terminal que deben ejecutarse. Agregué comentarios en cada comando para que quede claro. Lo único que quiero explicar es qué significan $1 y $2. Estas son dos variables que se pasarán cuando se inicie el script bash. Usando el comando de exportación, se agregarán a las variables del servidor y se leerán en Docker-Compose. Esto funciona para Ubuntu, probablemente no para Windows, pero no estoy seguro. Ahora necesita agregar el script stop.sh, que detendrá el trabajo. Contendrá varias líneas:
#!/bin/bash

# Ensure, that docker-compose stopped
docker-compose stop

# Ensure, that the old application won't be deployed again.
mvn clean
Aquí detenemos Docker-Compose y limpiamos el proyecto jarnik, que ha estado por ahí desde la última compilación. Hacemos esto para garantizar que nuestro proyecto se reconstruya con precisión. Había precedentes, por eso agrego) Como resultado, terminamos con 4 archivos nuevos:
  • Dockerfile: un archivo para crear una imagen de nuestra aplicación;
  • docker-compose.yml: un archivo con configuraciones sobre cómo lanzaremos nuestros contenedores;
  • start.sh: script bash para implementar nuestra aplicación;
  • stop.sh es un script bash para detener nuestra aplicación.
También actualizaremos la versión de nuestra aplicación de 0.2.0-SNAPSHOT a 0.3.0-SNAPSHOT. Agreguemos una descripción de la nueva versión a RELEASE_NOTES y refactoricemos ligeramente lo que había allí:
# Notas de la versión ## 0.3.0-SNAPSHOT * JRTB-13: proceso de implementación agregado al proyecto ## 0.2.0-SNAPSHOT * JRTB-3: patrón de comando implementado para manejar los comandos de Telegram Bot ## 0.1.0-SNAPSHOT * JRTB -2: bot de telegrama auxiliar agregado * JRTB-0: proyecto esqueleto SpringBoot agregado
Y en el README agregaremos un nuevo párrafo que describe cómo implementar nuestra aplicación:
## Implementación El proceso de implementación es lo más sencillo posible: Software requerido: - terminal para ejecutar scripts bash - ventana acoplable - docker-compose para implementar la aplicación, cambie a la rama necesaria y ejecute el script bash: $ bash start.sh ${bot_username} ${bot_token } Eso es todo.
Por supuesto, todo está escrito en inglés. Como de costumbre, en nuestra rama recién creada STEP_4_JRTB-13 creamos una nueva confirmación con el nombre: JRTB-13: implementamos el proceso de implementación a través de Docker y lo enviamos. Dejo de detenerme en detalles sobre cosas que ya he descrito en artículos anteriores. No veo el sentido de repetir lo mismo. Además, aquellos que lo hayan descubierto y lo hayan hecho ellos mismos no tendrán preguntas. Este soy yo hablando sobre cómo crear una nueva rama, cómo crear una confirmación, cómo enviar una confirmación al repositorio.

Línea de fondo

Hoy he mostrado un montón de información nueva que debe considerarse cuidadosamente y ampliarse con lecturas adicionales. Lo más importante: con la ayuda de UN comando (!!!) se hará todo lo necesario para desplegar nuestra aplicación. Esto es tan genial que ni siquiera puedo decírtelo. Sí, tuve que dedicar una buena cantidad de tiempo a la documentación de Docker para comprender cómo reenviar variables correctamente. A partir de ahora, el bot de Telegram siempre funcionará en la última versión de la rama principal. Enlace al bot de Telegram. Hoy no habrá enlaces a materiales que sería bueno leer: la responsabilidad es tuya. Necesitas aprender a buscar información. Todos los que se suscribieron a mi canal de Telegram se enteraron de la implementación del bot casi de inmediato. Amigos, ¿les gusta el proyecto? ¡Dale una estrella ! De esta manera se volverá más popular y más personas podrán conocerlo y aprender de él. Como siempre, sugiero registrarse en GitHub y seguir mi cuenta para seguir esta serie y mis otros proyectos en los que trabajo allí. Ahora estamos listos para conectar la base de datos. El próximo artículo será más largo y en él haremos todo lo necesario para trabajar con la base de datos. Todas las descripciones están en JRTB-1 .

Al principio de este artículo encontrará una lista de todos los materiales de la serie.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION