Ciao a tutti. Continuiamo la serie di articoli sulla scrittura del tuo progetto.
Ordina i rami
Dell'importanza, per non perdermi nei rami e nel loro ordine nel repository, ho deciso di rinominarli aggiungendo il prefisso STEP_{numero} . Ad esempio abbiamo tre rami oltre a quello principale:- JRTB-0
- JRTB-2
- JRTB-3
- STEP_1_JRTB-0 - primo passo
- STEP_2_JRTB-2 - secondo passaggio
- STEP_3_JRTB-3 - terzo passaggio
Un po' di Docker
Cos'è Docker? In breve, è uno strumento con cui è possibile distribuire (deploy) applicazioni in modo rapido e sicuro, creando per loro un'infrastruttura chiusa, necessaria solo a loro. È ancora difficile, lo capisco. In generale, Docker può essere inteso come una piattaforma di sviluppo in cui è possibile lavorare in modo rapido ed efficiente. Docker può essere inteso come un programma che viene eseguito su un server. Questo programma ha la capacità di archiviare contenitori con applicazioni. Cos'è un contenitore? Questa è un'infrastruttura separata in cui puoi aggiungere tutto ciò di cui hai bisogno. Ad esempio, per un'applicazione Java abbiamo bisogno di un JRE per eseguire l'applicazione, il contenitore avrà questo, avremo bisogno di altro software: possiamo aggiungere questo. O forse abbiamo bisogno di Linux e di un contenitore servlet Tomcat. Anche questo può essere fatto. I contenitori vengono creati in base all'immagine: si tratta cioè di un template specifico in cui è scritto tutto il necessario per creare un contenitore Docker. Come creare questa immagine? Nel nostro caso, dovremo creare un Dockerfile alla radice del progetto che descriva cosa dovrebbe esserci nel contenitore. Dato che non vogliamo esporre il token del bot da nessuna parte, dovremo ricorrere a passarlo ogni volta che vogliamo distribuire l'applicazione. Puoi leggere di più su questo argomento qui e qui .Scriviamo JRTB-13
Dobbiamo impostare un processo di distribuzione rapido e semplice per la nostra applicazione sul server. Cioè, per una macchina che funziona 24 ore su 24, 7 giorni su 7. Prendiamo Docker come base. Ma nel nostro elenco non è presente alcuna attività responsabile dell'aggiunta di questa funzionalità. In qualche modo mi è mancato durante la creazione. Nessun problema, lo creeremo ora. Vai alla scheda di creazione del problema su GitHub e seleziona Richiesta di funzionalità: aggiungi una descrizione dell'attività, i criteri per la sua accettazione, imposta a quale progetto appartiene questo problema e puoi creare un nuovo problema: Ora, per mostrare che l'attività è stata accettata per lavoro, modifica lo stato dell'attività da Da fare a In corso: questo sarà un articolo difficile. Se hai problemi, scrivi nei commenti: li monitorerò e risponderò al meglio delle mie capacità. Questa sarà una piccola Assistenza Clienti :DCreazione di un Dockerfile
Cos'è un dockerfile? Per Docker, si tratta di uno script (istruzioni dettagliate) su come creare un'immagine per un contenitore Docker. Affinché la nostra applicazione funzioni, abbiamo bisogno del JDK, versione 11. Cioè, dobbiamo trovare l'immagine docker JDK 11 e aggiungerla alla nostra immagine. Questo è qualcosa di simile al modo in cui aggiungiamo una dipendenza a un ricordo. Docker dispone di DockerHub per questo scopo . Per scaricare le immagini localmente, è necessario registrarsi lì. Dopo la registrazione andiamo a cercare JDK11. Da quello che ho trovato, questo è il contenitore: adoptopenjdk/openjdk11 . La descrizione di questo contenitore contiene ciò che è necessario per il dockerfile:FROM adoptopenjdk/openjdk11:ubi
RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]
Sistemiamo la cartella da cui prendiamo il file jar. Lo abbiamo nella cartella di destinazione dopo aver eseguito l'attività maven del pacchetto mvn. Prima di fare tutto questo, in base al ramo principale aggiornato, ne creiamo uno nuovo per il nostro compito: STEP_4_JRTB-13 . Ora puoi lavorare. Nella root del progetto, crea un file senza l' estensione Dockerfile e aggiungi quanto segue al suo interno:
FROM adoptopenjdk/openjdk11:ubi
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
La prima riga indica su cosa si baserà l'immagine: adoptopenjdk/openjdk11. La seconda riga consiste nell'aggiungere un argomento all'immagine denominata JAR_FILE, che si trova nella cartella di destinazione. Inoltre, la cartella corrente è determinata dalla posizione del Dockerfile. Terza riga: copia il jar del nostro progetto nell'immagine della finestra mobile. L'ultima riga contiene essenzialmente un array creato dal comando nel terminale, separato da uno spazio. Cioè, alla fine verrà eseguito quanto segue: "java -jar /app.jar" Per mantenere segreto il token del bot, all'avvio del contenitore dovremo passare due variabili: il nome del bot e il suo token. Per fare ciò, scriveremo una query che dovrebbe avviare il nostro progetto con variabili. E come si fa? Bisogna cercarlo su Google: ecco il primo link con una descrizione normale. Cosa vogliamo fare? Abbiamo due variabili nel file application.properties che definiamo lì:
- bot.nomeutente
- bot.token
- Eseguiamo lo script bash.
- Lo script bash esegue docker-compose.
- Docker-compose avvia un contenitore docker con la nostra applicazione.
- Il contenitore Docker esegue la nostra applicazione.
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"]
Puoi vedere che abbiamo aggiunto due righe e aggiornato ENTRYPOINT. Linee:
ENV BOT_NAME=test.javarush_community_bot
ENV BOT_TOKEN=1375780501:AAE4A6Rz0BSnIGzeu896OjQnjzsMEG6_uso
dichiarare variabili all'interno del file del codificatore. Per impostazione predefinita hanno un valore specificato. Se, durante la creazione di un'immagine da questo dockerfile, vengono passate variabili di ambiente con tali nomi, i valori saranno diversi. E in ENTRYPOINT abbiamo aggiunto alcuni altri elementi che leggeranno queste variabili d'ambiente:
"-Dbot.username=${BOT_NAME}", "-Dbot.token=${BOT_TOKEN}"
Qui puoi vedere che all'interno della riga, utilizzando il costrutto ${}, verranno passati i valori di BOT_NAME e BOT_TOKEN. Successivamente, dobbiamo insegnare come ricevere e passare queste variabili a docker-compose.
Crea docker-compose.yml
Sarebbe bene che leggessi separatamente il formato YAML, altrimenti l'articolo sta già crescendo a passi da gigante. Per noi questa è solo un'altra descrizione delle variabili del tipo .properties. Solo nelle proprietà viene scritto attraverso un punto, ma in YAML questo viene fatto in modo un po' più bello. Ad esempio, così. Due variabili in .properties: javarush.telegram.bot.name=ivan javarush.telegram.bot.token=pupkin Ma in .yaml (lo stesso di .yml) sarà così:javarush:
telegram:
bot:
name: ivan
token: pupkin
La seconda opzione è più bella e comprensibile. Gli spazi dovrebbero essere esattamente come indicato sopra. Traduciamo in qualche modo application.properties e application.yml. Per prima cosa devi crearlo. Nella root del progetto, crea un file docker-compose.yml e scrivi lì quanto segue:
version: '3.1'
services:
jrtb:
build:
context: .
environment:
- BOT_NAME=${BOT_NAME}
- BOT_TOKEN=${BOT_TOKEN}
restart: always
La prima riga è la versione docker-compose. services: dice che tutte le righe successive a questa (verranno spostate) si riferiscono ai servizi che stiamo configurando. Finora ne abbiamo solo uno: un'applicazione Java chiamata jrtb . E già sotto ci saranno tutte le sue impostazioni. Ad esempio, build: contesto: . dice che cercheremo il Dockerfile nella stessa directory di docker-compose.yml. Ma la sezione Environment: sarà responsabile di garantire il passaggio delle variabili di ambiente necessarie al Dockerfile. Proprio quello di cui abbiamo bisogno. Pertanto, passiamo le variabili di seguito. Docker-compose li cercherà nelle variabili dell'ambiente operativo del server. Aggiungiamoli allo script bash.
Creazione di script bash
L'ultimo passaggio è creare uno script bash. Crea un file chiamato start.sh nella root del progetto e scrivi lì quanto segue:#!/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 prima riga è necessaria per tutti gli script bash: senza di essa non funzionerà. E poi - solo una serie di comandi nel terminale che devono essere eseguiti. Ho aggiunto commenti in ogni comando quindi dovrebbe essere chiaro. L’unica cosa che voglio spiegare è cosa significano $ 1 e $ 2. Queste sono due variabili che verranno passate all'avvio dello script bash. Utilizzando il comando export, verranno aggiunti alle variabili del server e letti in docker-compose. Funziona per Ubuntu, probabilmente non per Windows, ma non ne sono sicuro. Ora devi aggiungere lo script stop.sh, che interromperà il lavoro. Conterrà diverse righe:
#!/bin/bash
# Ensure, that docker-compose stopped
docker-compose stop
# Ensure, that the old application won't be deployed again.
mvn clean
Qui interrompiamo la composizione docker e puliamo il progetto jarnik, che è rimasto in giro dall'ultima build. Lo facciamo per garantire che il nostro progetto venga ricostruito accuratamente. C'erano dei precedenti, ecco perché aggiungo) Di conseguenza, ci ritroviamo con 4 nuovi file:
- Dockerfile: un file per creare un'immagine della nostra applicazione;
- docker-compose.yml - un file con le impostazioni su come lanceremo i nostri contenitori;
- start.sh - script bash per la distribuzione della nostra applicazione;
- stop.sh è uno script bash per arrestare la nostra applicazione.
# Note di rilascio ## 0.3.0-SNAPSHOT * JRTB-13: aggiunto processo di distribuzione al progetto ## 0.2.0-SNAPSHOT * JRTB-3: implementato modello di comando per la gestione dei comandi del Bot di Telegram ## 0.1.0-SNAPSHOT * JRTB -2: aggiunto stub telegram bot * JRTB-0: aggiunto progetto skeleton SpringBoot
E nel README aggiungeremo un nuovo paragrafo che descrive come distribuire la nostra applicazione:
## Distribuzione Processo di distribuzione il più semplice possibile: Software richiesto: - terminale per l'esecuzione degli script bash - docker - docker-compose per distribuire l'applicazione, passare al ramo necessario ed eseguire lo script bash: $ bash start.sh ${bot_username} ${bot_token } È tutto.
Ovviamente tutto è scritto in inglese. Come al solito, nel nostro ramo appena creato STEP_4_JRTB-13 creiamo un nuovo commit con il nome: JRTB-13: implementa il processo di distribuzione tramite docker e invialo. Mi fermo a soffermarmi nel dettaglio su cose che ho già descritto negli articoli precedenti. Non vedo il motivo di ripetere la stessa cosa. Inoltre, coloro che l'hanno capito e lo hanno fatto da soli non avranno domande. Sto parlando di come creare un nuovo ramo, come creare un commit, come inviare un commit al repository.
GO TO FULL VERSION