Dockering av en Spring Boot-applikasjon

1. Oversikt

I denne artikkelen vil vi fokusere på hvordan du dockerize a Spring Boot Application å kjøre den i et isolert miljø, også kalt container.

Videre viser vi hvordan du lager en sammensetning av containere, som er avhengige av hverandre og er koblet mot hverandre i et virtuelt privat nettverk. Vi får også se hvordan de kan administreres sammen med enkeltkommandoer.

La oss starte med å lage et Java-aktivert, lett basisbilde som kjører Alpint Linux.

2. Buildpacks-støtte i Spring Boot 2.3

Spring Boot 2.3 la til støtte for buildpacks. Enkelt sagt, i stedet for å lage vår egen Dockerfile og bygge den ved å bruke noe lignende docker bygge, alt vi trenger er å utstede følgende kommando:

$ ./mvnw spring-boot: build-image

Eller i Gradle:

$ ./gradlew bootBuildImage

Hovedmotivasjonen bak buildpacks er å skape den samme distribusjonsopplevelsen som noen kjente skytjenester som Heroku eller Cloud Foundry tilbyr en stund. Vi kjører bare build-image mål og selve plattformen tar seg av å bygge og distribuere gjenstanden.

Videre kan det hjelpe oss med å endre måten vi bygger Docker-bilder mer effektivt på. I stedet for å bruke den samme endringen på mange Dockerfiles i forskjellige prosjekter, er alt vi trenger å gjøre å endre eller stille inn buildpacks 'image builder.

I tillegg til brukervennlighet og bedre generell utvikleropplevelse, kan det også være mer effektivt. For eksempel vil buildpacks-tilnærmingen lage et lagdukker-Docker-bilde og bruker den eksploderte versjonen av Jar-filen.

3. Felles basisbilde

Vi skal bruke Dockers eget build-filformat: a Dockerfil.

EN Dockerfil er i prinsippet en linevis batchfil som inneholder kommandoer for å bygge et bilde. Det er ikke absolutt nødvendig å legge disse kommandoene i en fil, fordi vi også kan sende dem til kommandolinjen - en fil er rett og slett mer praktisk.

Så la oss skrive vår første Dockerfil:

FRA alpine: edge MAINTAINER baeldung.com RUN apk add --no-cache openjdk8 COPY files / UnlimitedJCEPolicyJDK8 / * \ /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/
  • FRA: Nøkkelordet FRA, forteller Docker å bruke et gitt bilde med taggen som build-base. Hvis dette bildet ikke er i det lokale biblioteket, kan du søke på nettet på DockerHub, eller på et annet konfigurert fjernregister, utføres
  • VEDLIKEHOLDER: A VEDLIKEHOLDER er vanligvis en e-postadresse som identifiserer forfatteren av et bilde
  • LØPE: Med LØPE kommando, vi kjører en skallkommandolinje i målsystemet. Her bruker vi Alpine Linux pakkeleder apk å installere Java 8 OpenJDK
  • KOPIERE: Den siste kommandoen forteller Docker til KOPIERE noen få filer fra det lokale filsystemet, spesielt en undermappe til byggekatalogen, inn i bildet i en gitt bane

KRAV: For å kunne kjøre opplæringen vellykket, må du laste ned Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files fra Oracle. Bare hent ut det nedlastede arkivet i en lokal mappe som heter ‘Filer’.

For å endelig bygge bildet og lagre det i det lokale biblioteket, må vi kjøre:

docker build --tag = alpine-java: base --rm = true.

LEGGE MERKE TIL: De -stikkord alternativet vil gi bildet sitt navn og –Rm = sant fjerner mellomliggende bilder etter at de har blitt bygget. Det siste tegnet i denne skallkommandoen er en prikk som fungerer som et argument for build-katalog.

4. Dockerize en frittstående Spring Boot-applikasjon

Som et eksempel på et program som vi kan dockerize, tar vi spring-cloud-config / server fra vårskykonfigurasjonsveiledningen. Som et forberedelse-trinn, må vi sette sammen en kjørbar jar-fil og kopiere den til vår Docker build-katalog:

tutorials $> cd spring-cloud-config / server server $> mvn package spring-boot: repackage server $> cp target / server-0.0.1-SNAPSHOT.jar \ ../../spring-boot-docker/files /config-server.jar server $> cd ../../spring-boot-docker

Nå skal vi lage en Dockerfil heter Dockerfile.server med følgende innhold:

FRA alpine-java: base VEDLIKEHOLDER baeldung.com COPY files / spring-cloud-config-server.jar / opt / spring-cloud / lib / COPY files / spring-cloud-config-server-entrypoint.sh / opt / spring- sky / bin / ENV SPRING_APPLICATION_JSON = \ '{"spring": {"cloud": {"config": {"server": \ {"git": {"uri": "/ var / lib / spring-cloud / config-repo ", \" clone-on-start ": true}}}}}} 'ENTRYPOINT [" / usr / bin / java "] CMD [" -jar "," / opt / spring-cloud / lib / spring-cloud-config-server.jar "] VOLUME / var / lib / spring-cloud / config-repo EXPOSE 8888
  • FRA: Som base for vårt image tar vi Java-aktivert Alpint Linux, opprettet i forrige avsnitt
  • KOPIERE: Vi la Docker kopier jar-filen vår til bildet
  • ENV: Denne kommandoen lar oss definere noen miljøvariabler, som vil bli respektert av applikasjonen som kjører i containeren. Her definerer vi en tilpasset Spring Boot Application konfigurasjon, for å overlevere til jar-kjørbar senere
  • INNGANGSPUNKT/CMD: Dette vil være kjørbar for å starte når containeren starter. Vi må definere dem som JSON-Array, fordi vi vil bruke en INNGANGSPUNKT i kombinasjon med en CMD for noen applikasjonsargumenter
  • VOLUM: Fordi containeren vår vil kjøre i et isolert miljø uten direkte nettverkstilgang, må vi definere en monteringsplassholder for vårt konfigurasjonslager
  • AVDEKKE: Her forteller vi Docker, på hvilken port applikasjonen vår er oppført. Denne porten vil bli publisert til verten når containeren starter

Å lage et bilde fra vår Dockerfil, vi må løpe ‘Docker build’, som før:

$> docker build --file = Dockerfile.server \ --tag = config-server: siste --rm = true.

Men før vi skal kjøre en container fra bildet vårt, må vi lage et volum for montering:

$> docker-volum oppretter --navn = spring-cloud-config-repo

LEGGE MERKE TIL: Mens en container er uforanderlig, vil data lagret i et volum være vedvarende over flere containere når de ikke er forpliktet til et bilde etter at applikasjonen er avsluttet.

Endelig er vi i stand til å kjøre containeren fra bildet vårt:

$> docker run --name = config-server --publish = 8888: 8888 \ --volume = spring-cloud-config-repo: / var / lib / spring-cloud / config-repo \ config-server: siste
  • Først må vi -Navn vår container. Hvis ikke, blir en automatisk valgt
  • Så må vi -publisere vår utsatte havn (se Dockerfil) til en port på verten vår. Verdien er gitt i skjemaet 'Verts-port: container-port'. Hvis bare en containerport er gitt, vil en tilfeldig valgt vertsport brukes. Hvis vi utelater dette alternativet, vil beholderen være helt isolert
  • De -volum alternativet gir tilgang til enten en katalog på verten (når den brukes med en absolutt bane) eller en tidligere opprettet Docker volum (når det brukes med en volumnavn). Stien etter kolon angir monteringspunkt i containeren
  • Som argument må vi fortelle Docker, hvilket bilde som skal brukes. Her må vi gi bilde-navn fra den tidligere ‘docker bygge' steg
  • Noen flere nyttige alternativer:
    • -den - aktivere interaktiv modus og tildele en pseudo-tty
    • -d - løsner fra beholderen etter oppstart

Hvis vi kjører containeren i frittliggende modus, kan vi inspisere detaljene, stoppe den og fjerne den med følgende kommandoer:

$> docker inspect config-server $> docker stop config-server $> docker rm config-server

5. Dockerize avhengige applikasjoner i en kompositt

Docker kommandoer og Dockerfiler er spesielt egnet for å lage individuelle containere. Men hvis du vil operere på et nettverk av isolerte applikasjonerblir containerledelsen raskt rotete.

For å løse det, Docker gir et verktøy som heter Docker komponere. Dette kommer med en egen build-fil i YAML format og er bedre egnet til å administrere flere containere. For eksempel er den i stand til å starte eller stoppe en sammensetning av tjenester i en kommando, eller fletter loggeutgangen til flere tjenester sammen til en pseudo-tty.

La oss bygge et eksempel på to applikasjoner som kjører i forskjellige Docker-containere. De vil kommunisere med hverandre og presenteres som en "enhet" til vertssystemet. Vi skal bygge og kopiere spring-cloud-config / client eksempel beskrevet i vårskykonfigurasjonsveiledningen til vår filer mappen, som vi har gjort før med config-server.

Dette blir vårt docker-compose.yml:

versjon: '2' tjenester: config-server: container_name: config-server build: context:. dockerfile: Dockerfile.server image: config-server: siste eksponere: - 8888 nettverk: - spring-cloud-network volumes: - spring-cloud-config-repo: / var / lib / spring-cloud / config-repo logging: driver : json-file config-client: container_name: config-client build: context:. dockerfile: Dockerfile.client image: config-client: siste inngangspunkt: /opt/spring-cloud/bin/config-client-entrypoint.sh miljø: SPRING_APPLICATION_JSON: \ '{"spring": {"cloud": \ {"config ": {" uri ":" // config-server: 8888 "}}} 'expose: - 8080 porter: - 8080: 8080 nettverk: - vår-sky-nettverkslenker: - config-server: config-server avhengig av : - konfigurering av serverlogging: driver: json-filnettverk: vår-sky-nettverk: driver: brovolum: vår-sky-konfigurasjon-repo: ekstern: sann
  • versjon: Spesifiserer hvilken formatversjon som skal brukes. Dette er et obligatorisk felt. Her bruker vi den nyere versjonen, mens eldre format er ‘1’
  • tjenester: Hvert objekt i denne tasten definerer a service, a.k. en container. Denne delen er obligatorisk
    • bygge: Hvis gitt, docker-compose er i stand til å bygge et bilde fra en Dockerfil
      • kontekst: Hvis gitt, spesifiserer den build-katalogen, hvor Dockerfil blir slått opp
      • dockerfil: Hvis den er angitt, setter den et alternativt navn for en Dockerfil
    • bilde: Forteller Docker hvilket navn det skal gi bildet når build-funksjoner brukes. Ellers søker det etter dette bildet i biblioteket eller fjernregister
    • nettverk: Dette er identifikatoren for de navngitte nettverkene som skal brukes. En gitt navn-verdi må være oppført i nettverk seksjon
    • volumer: Dette identifiserer de navngitte volumene som skal brukes, og monteringspunktene som volumene skal monteres på, atskilt med et kolon. Likeledes i nettverk seksjon, a volumnavn må defineres separat volumer seksjon
    • lenker: Dette vil opprette en intern nettverkskobling mellom dette tjenesten og den oppførte tjenesten. Dette tjenesten vil være i stand til å koble til den oppførte tjenesten, der delen før kolon angir en tjenestenavn fra tjenester delen og delen etter kolon angir vertsnavnet som tjenesten lytter til i en eksponert port
    • kommer an på: Dette forteller Docker å starte en tjeneste bare hvis de listede tjenestene har startet. LEGGE MERKE TIL: Dette fungerer bare på containernivå! For en løsning for å starte den avhengige applikasjon først, se config-client-entrypoint.sh
    • hogst: Her bruker vi ‘Json-file ' driver, som er standard. Alternativt ‘Syslog’ med et gitt alternativ eller 'ingen' kan bli brukt
  • nettverk: I denne delen spesifiserer vi nettverk tilgjengelig for våre tjenester. I dette eksemplet la vi docker-compose lage et navngitt Nettverk av typen 'bro' for oss. Hvis alternativet utvendig er satt til ekte, vil den bruke en eksisterende med det gitte navnet
  • volumer: Dette ligner veldig på nettverk seksjon

Før vi fortsetter, vil vi sjekke build-filen for syntaksfeil:

$> docker-compose config

Dette blir vårt Dockerfile.client å bygge config-klient bilde fra. Det skiller seg fra Dockerfile.server ved at vi i tillegg installerer OpenBSD netcat (som er nødvendig i neste trinn) og lag inngangspunkt kjørbar:

FRA alpine-java: base MAINTAINER baeldung.com RUN apk --no-cache add netcat-openbsd COPY files / config-client.jar / opt / spring-cloud / lib / COPY files / config-client-entrypoint.sh / opt / spring-cloud / bin / RUN chmod 755 /opt/spring-cloud/bin/config-client-entrypoint.sh

Og dette blir tilpasset inngangspunkt for vår konfigureringsklienttjeneste. Her bruker vi netcat i en løkke for å sjekke om vår konfigurasjonsserver er klar. Du må legge merke til at vi kan nå vårt konfigurasjonsserver av sin lenkenavn, i stedet for en IP-adresse:

#! / bin / sh mens! nc -z konfigurasjonsserver 8888; gjør ekko "Venter på kommende Config Server" sove 2 ferdig java -jar /opt/spring-cloud/lib/config-client.jar

Til slutt kan vi bygge bildene våre, lage de definerte beholderne og starte den i en kommando:

$> docker-compose up --build

Fjern dem fra for å stoppe beholderne Docker og fjern den tilkoblede nettverk og volumer fra det kan vi bruke motsatt kommando:

$> docker-komponer ned

En fin funksjon av docker-compose er den evne til å skalere tjenester. For eksempel kan vi fortelle Docker å kjøre en container for konfigurasjonsserver og tre containere til config-klient.

Men for at dette skal fungere ordentlig, må vi fjerne container_name fra vår docker-compose.yml, for utleie Docker velg en, og vi må endre eksponert portkonfigurasjon, for å unngå sammenstøt.

Etter det kan vi skalere tjenestene våre slik:

$> docker-compose build $> docker-compose up -d $> docker-compose scale config-server = 1 config-client = 3

6. Konklusjon

Som vi har sett, er vi nå i stand til å lage tilpassede Docker bilder, kjører en Spring Boot Application som en Docker container, og skape avhengige containere med docker-compose.

For videre lesing om build-filene, henviser vi til den offisielle Dockerfil-referanse og docker-compose.yml referanse.

Som vanlig kan du finne kildekodene for denne opplæringen på Github.