Java în cloud: Tutorial de configurare a integrării continue
Publicat: 2022-03-11An de an, suntem martori la evoluția din ce în ce mai rapidă a industriei IT. Au trecut acum mai bine de două decenii de când sloganul revoluționar „Scrie o dată, rulează oriunde” a stabilit un nivel cu totul nou de așteptări pentru comunitatea de dezvoltare de software. Și iată-ne astăzi, cu un set rezultat, în continuă expansiune de instrumente, care au dus în mod colectiv dezvoltarea Java în special și dezvoltarea software în general, într-un univers cu totul nou de posibilități.
Metodologii precum Agile, DevOps și Integrarea și Implementarea continuă – împreună cu evoluția microserviciilor – au sporit în mod colectiv productivitatea procesului de dezvoltare a software-ului până la un punct în care este o plăcere să dezvoltați software mai mult ca niciodată. Utilizarea automatizării și configurarea setului corect de instrumente poate face dezvoltarea și livrarea de produse software surprinzător de nedureroasă.
Acest articol va arunca o privire asupra acestui nou univers din perspectiva unui dezvoltator Java care intră în DevOps și caută pentru a optimiza dezvoltarea și livrarea produselor la maximum.
Astăzi, termeni precum Spring Boot, Docker, Cloud, Amazon Web Services, Continuous Delivery sunt folosiți pe scară largă, dar mai puțin înțeleși. Acest articol va lua cea mai ușoară cale posibilă pentru a prezenta toate aceste tehnologii și a explica acești termeni și îl va încheia sub forma unui tutorial în care vom dezvolta o mică bucată de software și o vom pregăti pentru livrarea în producție folosind toate instrumentele menționate.
De ce aceste instrumente?
Simplificați implementările cu Docker
„Scrie o dată, rulează oriunde” a fost descoperirea conceptuală care a produs tehnologii precum Java Virtual Machine (JVM), care a permis codului tău să ruleze oriunde. Și acum iată-ne, câteva decenii mai târziu, cu ceva numit Docker fiind prezentat comunității IT. Docker este un instrument de izolare în care vă puteți plasa software-ul și îl puteți rula fără durere, aproape oriunde doriți.
Cu toate acestea, un dezvoltator Java se poate uita la Docker și spune „De ce am avea nevoie de asta, avem deja JVM, care este bine recunoscut ca soluție portabilă principală”. Dar este?
„Scrie o dată, fugi oriunde“ sună bine și se joacă bine... cel puțin de cele mai multe ori. Până când întâlniți mai mulți furnizori de JVM, mai multe versiuni Java, mai multe sisteme de operare și diverse permutări și combinații ale tuturor celor de mai sus. Apoi, treci de la paradigma elegantă „Scrie o dată, alergă oriunde” la capcana contraproductivă „Scrie o dată, depanează peste tot”.
Și aici intervine Docker pentru a ajuta la salvarea zilei.
Docker simplifică dezvoltarea, testarea și livrarea software-ului. Dacă aveți software-ul pe care doriți să-l testați, puneți-l în containerul Docker și acesta va rula și va fi instalat fără probleme pentru toate părțile implicate.
Accelerează dezvoltarea cu Spring Boot
La mai puțin de un deceniu de la introducerea sloganului „a alerga oriunde”, a apărut pe scenă cadrul de primăvară. Astăzi, ecosistemul Spring continuă să înflorească și a produs o mulțime de proiecte valoroase bazate pe Spring, poate cel mai important Spring Boot. După cum se menționează pe site-ul Spring Boot:
Spring Boot facilitează crearea de aplicații autonome, bazate pe Spring, de nivel de producție, pe care pur și simplu le puteți rula.
Spring Boot vă permite să activați și să rulați aplicația în câteva minute. Dezvoltatorii de software se pot concentra pe dezvoltarea de software și apoi pot beneficia de un instrument care face toată configurația pentru ei.
În acest tutorial, vom folosi Spring Boot pentru a dezvolta microserviciul nostru.
Integrare continuă (CI) cu Jenkins
DevOps este o mișcare în creștere rapidă care integrează strâns echipele de dezvoltare de software și de administrare a sistemelor, cu scopul de a face un ciclu de viață de dezvoltare și livrare a software-ului cât mai nedureros, fără întreruperi și productiv posibil pentru toate părțile implicate: dezvoltatori, administratori de sistem, testeri și, în cele din urmă , utilizatori finali.
Integrarea continuă (CI) este una dintre pietrele de temelie ale revoluției DevOps. Ideea este că ori de câte ori un dezvoltator trimite cod în depozitul de cod, acesta este automat testat și împachetat pentru livrare (implementare) în producție.
CI merge mână în mână cu:
- Livrare continuă – Livrarea automată a pachetului pregătit pentru testarea afacerii utilizatorului final cu declanșare manuală pentru implementarea producției.
- Implementare continuă – Implementarea automată a produsului ambalat direct în producție.
Există mai mult de câteva instrumente care pot fi utilizate pentru implementarea procesului CI. Unul dintre cele mai populare este Jenkins, un instrument CI open source. Cu mai mult de o mie de plugin-uri și o comunitate imensă în spate, Jenkins este o alegere ușoară atunci când începeți să vă gândiți la implementarea integrării, livrării sau implementării continue.
În tutorialul nostru, Jenkins va fi folosit pentru a livra produsul nostru în cloud, mai precis, cloud-ul Amazon (AWS).
Cloud Computing cu AWS
Dacă aveți o anumită experiență de administrator de sistem, imaginați-vă că eliminați de pe umerii dumneavoastră unele dintre grijile legate de administrarea sistemului. Aveți câteva aplicații; ai o idee despre câte resurse vor avea nevoie, dar nu știi exact dimensionarea hardware-ului de care vei avea nevoie. Tu faci estimarea, resursele sunt cumpărate, iar sistemul trece în producție. Dacă ai noroc, vei descoperi că ai supraestimat și că ai mai multe resurse decât ai nevoie. Dar, având în vedere Legea lui Murphy, este mai probabil să descoperiți că ați subestimat cerințele de resurse și veți ajunge să vă amestecați pentru a obține puțin mai multă memorie sau putere de procesare sub o presiune enormă de timp. În schimb, dacă implementați în cloud, pur și simplu vă puneți sistemul acolo și îl dimensionați după cum este necesar, cu flexibilitatea oferită de furnizorii de cloud. Cu cloud-ul, nu trebuie să vă faceți griji că rămâneți fără resurse de sistem și nici nu trebuie să vă faceți griji că 90% din memorie sau CPU sunt inactiv.
Desigur, există provocarea de a decide ce furnizor să aleagă. Războaiele norilor sunt încă în desfășurare. Ciocnirea Microsoft, Amazon și Google pentru viitorul computerelor este un exemplu de titlu pe care îl puteți găsi în ultima vreme în știrile din lumea tehnologiei. Pentru acest blog, am ales Amazon Web Services (AWS), în mare parte pe baza popularității sale actuale și a cotei de piață.
Unul dintre avantajele AWS este că Amazon oferă o mulțime de servicii după ce vă înscrieți:
În acest tutorial vom folosi următoarele două servicii AWS: Elastic Compute Cloud EC2 (mai precis, Amazon EC2 Container Registry sau Amazon ECR) și Amazon S3 (Servicii de stocare simple).
Amazon ECR
Va trebui să stocăm undeva imaginile noastre Docker. Amazon ECR este un serviciu de registru AWS Docker gestionat. După cum se menționează pe site-ul web Amazon ECR:
… facilitează pentru dezvoltatori să stocheze, să gestioneze și să implementeze imaginile containerului Docker. Amazon ECR este integrat cu Amazon EC2 Container Service (ECS), simplificând fluxul de lucru de dezvoltare până la producție. Amazon ECR elimină nevoia de a opera propriile depozite de containere sau de a vă face griji cu privire la scalarea infrastructurii de bază.
Amazon S3
După cum am menționat, aplicația pe care o dezvoltăm va fi un microserviciu Spring Boot care va încărca fișiere pe Amazon S3. După cum se menționează pe site-ul web Amazon S3:
…oferă dezvoltatorilor și echipelor IT stocare în cloud securizată, durabilă și foarte scalabilă. Amazon S3 este stocarea obiectelor ușor de utilizat, cu o interfață simplă de serviciu web pentru a stoca și a prelua orice cantitate de date de oriunde pe web.
Un tutorial practic „Cum se face”.
Scopul este de a pregăti pentru implementarea unui microserviciu Spring Boot care va încărca fișiere pe Amazon S3. Pașii sunt următorii:
- Dezvoltați microserviciul
- Definiți procesul de construire în care serviciul va fi dockerizat
- Utilizați Bitbucket pentru a găzdui depozitul de coduri Git
- Integrați Bitbucket cu Jenkins pentru a împacheta aplicația folosind Gradle
- Împingeți-l către un Amazon ECR la distanță
Ceea ce urmează este un tutorial pentru configurarea tuturor componentelor necesare:
- Exemplu de aplicație Spring Boot – microserviciu împachetat și dockerizat folosind Gradle
- Instalarea Jenkins pe un nou server Ubuntu
- Integrarea Bitbucket cu Jenkins prin webhook
- Configurarea jobului Jenkins
- Amazon ECR pentru a stoca imaginile Docker care conțin aplicația noastră
Cerințe preliminare
Pentru a putea folosi resursele cloud AWS, trebuie să ne înregistrăm mai întâi la Amazon. Prin înregistrare, vom obține un cont cu beneficii imediate de utilizare a nivelului gratuit, în scopul de a permite o experiență practică în cele 12 luni de la înregistrare.
După cum am menționat, în acest tutorial vom folosi Amazon S3 și Amazon ECR. Pentru ambele, vom avea nevoie de chei de acces pentru a ne conecta la servicii.
După înregistrarea la AWS, mergem la contul nostru Acreditări de securitate , unde alegem Chei de acces și facem clic pe „Creează o cheie de acces nouă”. După ce faceți clic, o cheie este generată împreună cu ID-ul acesteia. Trebuie să-l stocați într-un loc în siguranță, deoarece îl vom folosi mai târziu atunci când configurați integrarea AWS Jenkins și dezvoltăm încărcarea fișierului nostru S3.
Următoarea condiție prealabilă este că avem nevoie de o găleată Amazon S3 (container de stocare). Serviciul nostru Spring Boot va încărca și descărca fișiere în și din stocarea Amazon S3. Crearea găleții este destul de simplă și necesită doar câteva clicuri. O descriere completă a modului în care se face acest lucru este furnizată în documentația Creați o găleată.
De asemenea, vom folosi Bitbucket pentru a găzdui codul nostru și a declanșa solicitări către Jenkins, așa că este necesar și un cont Bitbucket. Bitbucket este o opțiune excelentă pentru dezvoltatori, unul dintre principalele sale beneficii fiind cantitatea nelimitată de depozite private pe care le puteți crea.
Dezvoltarea aplicației
În loc să intru în toate detaliile adnotărilor Spring și cum funcționează ele, mă voi concentra, din perspectiva dezvoltatorului pur, pe partea mai provocatoare a întregii configurații; și anume, instalarea și configurarea Linux, Jenkins și a altor instrumente necesare pentru CI. Toate exemplele de cod utilizate în acest tutorial, inclusiv aplicația de microserviciu Spring Boot, sunt disponibile în depozitul Bickbucket pentru proiect.
Compoziția noastră de aplicare este simplă. Avem un punct de intrare pentru aplicația Spring Boot în fișierul nostru StorageWebserviceApplication.java
. Logica pentru încărcarea și descărcarea fișierelor este în StorageService.java
. StorageController.java
este un controler Rest, care conține puncte finale API utilizate pentru încărcarea și descărcarea fișierelor. Iată ierarhia proiectului:
Am ales Gradle ca instrument de compilare și va împacheta aplicația noastră și va compune imaginea Docker. Deci, în continuare, vom discuta despre fișierul de compilare Gradle, componenta de serviciu și fișierul Docker.
Pentru a putea folosi AWS API, trebuie să includem dependențe în fișierul nostru de compilare, așa cum este definit în documentația AWS pentru utilizarea Gradle.
În concluzie, partea de configurare a dependenței AWS a scriptului nostru Gradle va arăta astfel:
buildscript { ... repositories { mavenCentral() } dependencies { ... classpath("io.spring.gradle:dependency-management-plugin:0.5.4.RELEASE") } } .. apply plugin: "io.spring.dependency-management" dependencyManagement { imports { mavenBom ('com.amazonaws:aws-java-sdk-bom:1.10.47') } } dependencies { .. compile ('com.amazonaws:aws-java-sdk-s3') }
După cum sa menționat anterior, atunci când încărcăm fișiere pe Amazon S3, facem acest lucru încărcând fișiere într-o găleată S3 .
Pentru a se conecta la bucket, clientul nostru Amazon S3 trebuie să aibă acreditări furnizate. Acreditările sunt cheile de acces pe care le-am creat anterior. Definim ID-ul și valoarea cheii de acces în fișierul application.properties
; ne-am numit găleata toptal-s3-example
.
Componenta noastră principală de servicii este acum următoarea:
@Service public class StorageService { @Value("${aws.accesKeyId}") private String awsAccessKeyId; @Value("${aws.secretKey}") private String awsSecretKey; @Value("${aws.bucketName}") private String awsBucketName; private AWSCredentials credentials; private AmazonS3 s3client;; @PostConstruct public void init(){ credentials = new BasicAWSCredentials(awsAccessKeyId, awsSecretKey); s3client = new AmazonS3Client(credentials); } public void uploadFile(MultipartFile file) throws IOException { File fileForUpload = transformMultipartToFile(file); s3client.putObject(new PutObjectRequest(awsBucketName, file.getOriginalFilename(), fileForUpload)); } public InputStream downloadFile(String amazonFileKey) throws IOException { S3Object fetchFile = s3client.getObject(new GetObjectRequest(awsBucketName, amazonFileKey)); InputStream objectData = fetchFile.getObjectContent(); return objectData; } …
StorageService
citește acreditările din fișierul application.properties
și le folosește pentru a instanția obiectul BasicAWSCredentials
și, ulterior, obiectul AmazonS3Client
. Ceea ce urmează este o chestiune simplă de a invoca putObject
pentru încărcarea fișierului și getObject
pentru descărcarea fișierului, pe obiectul client Amazon S3.
Vom rula serviciul într-un container Docker și, în timpul procesului de construire Gradle, vom construi imaginea Docker. Vom face acest lucru prin configurarea suplimentară a fișierului build.gradle
, după cum urmează:
buildscript { ... dependencies { ... classpath('se.transmode.gradle:gradle-docker:1.2') } } ..... apply plugin: 'docker' ... task buildDocker(type: Docker, dependsOn: build) { push = false applicationName = "storageservice" dockerfile = file('src/main/docker/Dockerfile') doFirst { copy { from jar into stageDir } } }
Partea Buildscript
și apply plugin
sunt destul de standard. De asemenea, am definit o sarcină buildDocker
care citește configurația Docker stocată în src/main/docker/Dockerfile
și copiază fișierul JAR în versiunea Docker.
Dockerfile conține o listă de comenzi Docker pure cu care ne vom pregăti imaginea:
FROM frolvlad/alpine-oraclejdk8 ADD storageWebService-0.0.1-SNAPSHOT.jar storageService.jar EXPOSE 8080 CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/storageService.jar"]
O condiție prealabilă pentru rularea aplicației noastre este să aveți instalată o mașină virtuală Java (JVM). Docker oferă o listă de imagini cu Java instalat, iar noi vom alege una dintre cele mai mici, pe baza unui Linux Alpine de minim 5MB. frolvlad/alpine-oraclejdk8
are tot ce ne trebuie și este destul de mică (doar 170 MB).
Comanda FROM
setează imaginea menționată ca bază pe care va fi construită propria noastră. ADD
fișierul JAR construit la sistemul de fișiere container sub numele storageService.jar
. În continuare, definim ca containerul Docker să asculte pe portul 8080
în timpul execuției cu comanda EXPOSE
. Acest lucru, totuși, nu va permite comunicarea către 8080
de la gazdă. Când imaginea este terminată și dorim să o rulăm, va trebui să publicăm portul de pe container cu următoarea comandă docker run -p 8080:8080 amazonRepository/storageservice
, unde amazonRepository
este un depozit pe care îl vom configura mai târziu în acest articol. tutorial. Cu CMD
, definim ce comenzi vor fi executate atunci când rulăm containerul. Valorile dintre parantezele comenzii CMD
înseamnă pur și simplu că următoarele vor fi executate atunci când rulăm containerul:
java -Djava.security.egd=file:/dev/./urandom -jar /storageService.jar
Opțiunea -Djava.security.egd=file:/dev/./urandom
este necesară pentru a ajuta la atenuarea întârzierilor JVM în timpul pornirii. Dacă este omisă, aceasta va face ca aplicația să pornească extrem de lentă din cauza unui proces de generare de numere aleatorii necesar în timpul procesului de pornire.
Aceasta rezumă partea „Dezvoltare aplicație”. După ce am făcut acest lucru, serviciul pe care l-am creat aici va fi pornit automat atunci când rulăm un container Docker mai târziu. Deci, să începem instalarea și configurarea celorlalte instrumente necesare pentru a configura procesul de integrare continuă.
Aplicații și operațiuni de sistem
În primul rând, avem nevoie de un server Linux curat pe care să setăm instrumentul Jenkins CI. Rețineți că următoarele instrucțiuni sunt special pentru Ubuntu 14.04. Rețineți că instrucțiunile pot diferi ușor pentru alte distribuții Linux. Versiunea Jenkins utilizată este 2.7.1, iar ecranele și instrucțiunile pot diferi ușor în funcție de versiunea Jenkins utilizată.

Deci, mergem la consola serverului nostru Linux și începem să instalăm cerințele preliminare.
Cerință preliminară JDK
Trebuie să avem un JDK instalat. Următoarele sunt instrucțiuni pentru instalarea JDK8.
sudo add-apt-repository ppa:webupd8team/java sudo apt-get install python-software-properties sudo apt-get update sudo apt-get install oracle-java8-installer java -version
Instalați Docker
Pentru ca Jenkins să poată declanșa versiunile Docker, trebuie să instalăm docker-engine
după cum urmează:
sudo apt-get install apt-transport-https ca-certificates sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D #create a docker list file sudo vi /etc/apt/sources.list.d/docker.list #add the following entry in the docker.list file (change trusty to #the release you are running on if you are running on different, ie. #xenial, precise...): deb https://apt.dockerproject.org/repo ubuntu-trusty main #save and exit the file sudo apt-get update apt-cache policy docker-engine sudo apt-get install docker-engine
Deoarece acum am instalat motorul Docker, cu următoarea comandă vom porni o imagine hello-world
pentru a confirma că Docker funcționează corect.
sudo docker run hello-world
Ieșirea imaginii Hello-world
va arăta după cum urmează și, cu aceasta, putem confirma că motorul funcționează ok.
Instalați AWS Command Line Interface (CLI)
În continuare, vom instala AWS CLI. Mai târziu, în configurația jobului Jenkins, vom folosi CLI pentru a executa comenzi pentru autentificarea AWS și trimiterea imaginii Docker în registrul containerului Amazon EC2.
Pentru a instala AWS CLI, urmează instrucțiunile descrise în detalii în documentația Amazon CLI.
Dintre cele două opțiuni de instalare, vom alege instalarea folosind Pip, un sistem de gestionare a pachetelor folosit pentru instalarea și gestionarea programelor Python. Vom instala Pip și AWS CLI pur și simplu rulând următoarele trei comenzi:
#install Python version 2.7 if it was not already installed during the JDK #prerequisite installation sudo apt-get install python2.7 #install Pip package management for python sudo apt-get install python-pip #install AWS CLI sudo pip install awscli
AWS ECR
Ca ultimul pas al procesului de construire, vom împinge imaginea noastră Docker în registrul de containere Amazon. În consola de servicii web Amazon, găsim AWS EC2 Container Service.
Selectăm submeniul Repositories din stânga și facem clic pe Începeți .
Ni se prezintă apoi primul ecran de configurare a depozitului unde introducem numele depozitului și facem clic pe butonul Următorul Pas .
Făcând clic pe Pasul următor , ne arată un ecran cu instrucțiuni despre cum să împingem imaginile în depozit.
Ni se prezintă un exemplu despre cum să construim și să împingem o imagine Docker în registru, dar nu trebuie să ne preocupăm acum de asta. Cu aceasta, am creat un depozit.
Instalați și configurați Jenkins
Pentru a instala Jenkins, introducem următoarele comenzi în shell:
#Download Jenkins key and pipe it to apt-key tool, apt-key command #add will read from input stream, as defined by „–„. When added #apt will be able to authenticate package to be installed. wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add - #create a sources list for jenkins sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list' #update your local package list sudo apt-get update #install jenkins sudo apt-get install jenkins
Când instalarea se termină, Jenkins pornește automat. Verificați starea serviciului cu următoarea comandă:
sudo service jenkins status
Jenkins se va conecta la depozitul Bitbucket Git și, pentru a face acest lucru, trebuie să instalăm Git.
#install Git sudo apt-get install git
Jenkins va declanșa procesul de construire Gradle, în timpul căruia va fi creată o imagine Docker. Pentru a putea face acest lucru, utilizatorul Jenkins trebuie adăugat la grupul de utilizatori docker
:
#add Jenkins user to docker user group sudo usermod -aG docker jenkins
În timpul procesului de construire, Jenkins va trimite imagini Docker către Amazon ECR. Pentru a activa acest lucru, trebuie să configuram AWS pentru utilizatorul Jenkins.
În primul rând, trebuie să trecem la utilizatorul jenkins
. Pentru a face acest lucru, trebuie să setăm o parolă.
#change Jenkins password sudo passwd jenkins #switch to Jenkins user su – jenkins #configure AWS aws configure
După ce introducem comanda aws configure
, începem să introducem cheia secretă de acces generată și ID-ul cheii (acestea sunt acreditările pe care le-am generat mai devreme în proces). În cazul meu, regiunea contului este us-west-2
, așa că am introdus asta. De asemenea, am setat formatul de ieșire implicit pentru comenzile AWS să fie JSON.
Acum putem trece la configurarea Jenkins prin consola web accesibilă pe portul 8080.
Când accesăm adresa URL, ni se prezintă următorul ecran Introducere .
După cum se arată pe ecran, trebuie să introducem parola. După ce am făcut acest lucru, expertul de configurare ne solicită să facem următoarele:
- Alegeți ce pluginuri să instalați - vom alege Instalare pluginuri sugerate .
- Creați primul utilizator administrator introducând acreditările utilizatorului
Când ați terminat, faceți clic pe Salvare și Terminare . Cu aceasta, am terminat configurarea Jenkins.
Înainte de a începe definirea sarcinii de construire, trebuie să adăugăm câteva plugin-uri suplimentare. Vom merge la Manage Jenkins și vom face clic pe Manage plugins . În fila Disponibil , găsim mai întâi pluginul Bitbucket , bifăm caseta și facem clic pe Descărcare și instalare după repornire .
Apoi vi se va prezenta ceva de genul următor ecran.
După instalarea pluginului, repetăm procesul pentru următoarele plugin-uri suplimentare care vor fi necesare pentru configurarea sarcinii:
- Pluginul Gradle
- Pluginul pentru pasul de construcție Docker
- Plugin pentru mediul de construcție personalizat Cloudbees Docker
- Plugin Amazon ECR
Pluginul pentru pasul de compilare Docker pe care îl folosim va trimite cereri către demonul Docker. În acest scop, trebuie să activăm socket-ul TCP pe portul 2375. Pentru a face acest lucru, introducem fișierul de configurare Docker aflat la etc/default/docker
.
sudo vi /etc/default/docker
Aici adăugăm următoarea linie în configurație:
DOCKER_OPTS='-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock'
Salvăm și ieșim din fișier și repornim atât serviciul Docker, cât și Jenkins.
sudo service docker restart sudo service jenkins restart
După ce Jenkins repornește, mergem la consola Jenkins și, din Manage Jenkins , alegem Configurare sistem .
Găsim secțiunea Docker builder și introducem http://localhost:2375
pentru URL-ul API REST, faceți clic pe Aplicare pentru a confirma modificarea. Facem apoi clic pe Testare conexiune pentru a confirma că totul este în regulă.
Salvăm configurația și trecem la configurarea jobului Jenkins.
Configurare job
Mergem la pagina de pornire a lui Jenkins și creăm un articol nou .
Alegem un proiect Freestyle și introducem numele proiectului așa cum se arată în următorul ecran:
Făcând clic pe OK , ni se prezintă pagina de configurare a jobului. Dorim ca proiectul să fie construit la fiecare push către depozitul nostru Bitbucket Git. Pentru a realiza acest lucru, trebuie mai întâi să definim depozitul la care ne conectăm.
Pasul 1: Gestionarea codului sursă
În gestionarea codului sursă, alegem Git și introducem adresa URL a depozitului nostru Bitbucket. Adresa URL are forma https://bitbucket.org/bitbucketUsername/repositoryName
.
După ce introducem adresa URL, Jenkins va încerca automat să testeze conexiunea. Deoarece nu am introdus încă acreditările, va afișa o eroare care indică faptul că nu se poate conecta.
Deschideți lista verticală Adăugați și faceți clic pe Acreditări furnizor Jenkins .
Ni se prezintă următorul ecran, unde introducem numele de utilizator și parola pentru contul nostru Bitbucket.
După adăugarea noii înregistrări de acreditări, ne asigurăm că o selectăm în meniul drop-down de acreditări, iar aceasta termină configurarea de gestionare a codului sursă .
Pasul 2: Construiți declanșatoare
Verificați construirea Trigger de la distanță și definiți un simbol de autentificare. Asigurați-vă că definiți un simbol aleator și sigur.
Pasul 3: Bitbucket Webhook
Jenkins ne-a furnizat deja adresa URL pe care o vom folosi pe Bitbucket. Mergem la pagina noastră de depozit Bitbucket și, în meniul de setări, facem clic pe Web hooks . Ulterior, făcând clic pe Adaugă webhook , ne prezintă următorul ecran, pe care îl completăm după cum urmează:
Adresa URL are următoarea structură: http://JENKINS_URL _HOST:PORT/job/JOB_NAME/build?token=TOKEN
.
Introduceți valorile de mai sus respectiv cu adresa URL Jenkins, portul pe care rulează, numele jobului pe care l-ați creat și simbolul pe care l-ați definit anterior.
După salvarea Webhook-ului, vi se va oferi următorul ecran, pe care îl puteți edita dacă este necesar, sau puteți vizualiza cererile generate de fiecare dată când introducem un cod nou.
Cu această configurație, webhook-ul este declanșat la fiecare push din depozit, indiferent de ramură. Pe partea lui Jenkins, putem defini ce ramură va declanșa construirea.
Pentru ca Bitbucket să poată trimite cod la Jenkins, trebuie să reconfigurem securitatea globală Jenkins pentru a permite accesul anonim de citire. În plus, pentru configurarea noastră, trebuie să dezactivăm opțiunea implicită Jenkins, care împiedică falsificarea cererilor pe mai multe site-uri. Pentru a face acest lucru, accesați Manage Jenkins și alegeți Configurați securitatea globală . Bifați Permite accesul anonim la citire și bifați Preveniți exploatările de falsificare între site-uri . Apoi salvați configurația.
Vă rugăm să rețineți că acest lucru se face doar din motive de simplitate. Configurarea completă depășește acoperirea acestui tutorial și ar include securizarea suplimentară a lui Jenkins în spatele unui proxy invers, pe conexiunea TLS și activarea prevenirii CSRF.
Pasul 4: Gradle Build
Acum putem reveni la jobul Jenkins și continuăm să o configurăm. În secțiunea de compilare, adăugăm un pas de compilare: Invoke gradle script .
Pe acest formular, introducem următoarele:
După cum se arată pe ecran, vom folosi învelișul Gradle, o caracteristică Gradle convenabilă care nu necesită să aveți Gradle instalat pe gazdă. Asigurați-vă că bifați caseta Faceți executabil gradlew .
În sarcini, specificăm build
și buildDocker
.
Pasul 5: Imaginea etichetei Docker
Această parte a versiunii etichetează o imagine Docker pregătită anterior de sarcina dockerBuild a lui dockerBuild
. Pentru aceasta, adăugăm un nou pas de construire la job: Execute Docker command . Alegem comanda Tag image și setăm numele imaginii, depozitul țintă unde vom împinge imaginea și etichetăm:
Pasul 6: Docker Push către Amazon ECR
În cele din urmă, trebuie să definim cum să ne împingem imaginea către Amazon ECR. Pentru aceasta, adăugăm un nou pas Execute shell build și setăm comenzile să se autentifice la AWS și să împingă imaginea către Amazon ECR:
#region for our account is us-west-2 aws ecr get-login --region us-west-2 | bash #push the previously tagged image docker push 058432294874.dkr.ecr.us-west-2.amazonaws.com/springbootdocker:${BUILD_NUMBER}
Cu aceasta, ne-am încheiat procesul de construire. După împingerea unui cod nou în repo, acest job se va activa și vom avea o nouă imagine Docker încărcată în registrul Docker „auto-magic”.
Imaginea poate fi apoi trasă oriunde avem instalat docker-engine
și poate fi rulată cu următoarea comandă:
docker run -p 8080:8080 amazonRepository/springbootdocker
Această comandă va porni microserviciul nostru Spring Boot, cu următoarele puncte finale pentru încărcarea și descărcarea fișierelor noastre în compartimentul S3:
-
http://hostnameURL:8080/api/storage/upload
-
http://hostnameURL:8080/api/storage/download?fileName=xyz
Pași suplimentari cu Java și integrare continuă
Întotdeauna sunt mai multe lucruri de făcut. În acest tutorial a fost acoperit mult teren, dar aș considera acest lucru doar un punct de plecare de la care să înveți mai departe. Punerea lui Jenkins în spatele unui server proxy web, cum ar fi Nginx, și stabilirea unei conexiuni TLS, sunt doar două exemple despre ceea ce ar putea și, probabil, ar trebui făcut mai mult.
Imaginea noastră Docker este disponibilă pe Amazon ECR și gata de implementare. Acum îl putem lua și implementa manual. Cu toate acestea, o soluție mai bună ar fi automatizarea acesteia în continuare. CI este doar primul pas, iar pasul următor este livrarea continuă. Ce zici de o disponibilitate ridicată? Amazon AWS EC2 oferă caracteristici pentru înregistrarea containerelor în cloud într-un mediu cluster, care este obligatoriu pentru serviciul bazat pe producție. Un exemplu bun de lucru al dezvoltării unui proces de livrare continuă poate fi găsit în următoarea postare pe blogul AWS.
Concluzie
Una peste alta, am pus în aplicare un proces de dezvoltare software fără probleme și curat. Folosind instrumentele disponibile, am creat o infrastructură care ne ajută să ne maximizăm productivitatea. Acum, nu trebuie să ne facem griji cu privire la configurarea serviciului nostru Java, care este un serviciu web simplu cu un punct final REST. Lăsăm convenția Spring Boot să se ocupe de tot și să ne concentrăm doar pe logica serviciului. Folosim Jenkins pentru a construi o nouă imagine Docker de fiecare dată când împingem codul nostru în depozitul nostru Bitbucket Git și, în final, am setat cloud-ul să fie responsabil pentru stocarea imaginilor și fișierelor noastre Docker. Când implementăm serviciul nostru conținut într-o imagine Docker, nu vom avea grijă de orice restricții ale sistemului de operare (atâta timp cât sistemul de operare are instalat un docker-engine
).