- Dette repoet inneholder en veldig enkel Spring Boot applikasjon som sier "hello" når en request kommer til context root (/)
- I denne øvingen skal dere bli bedre kjent med Docker og hvordan vi lager et Docker container Image av en Spring boot applikasjon.
- Vi skal bli kjent med både Docker hub og AWS ECR
- Vi skal også sette opp en CI pipeline for å automatisk bygge et nytt container image på hver push til main branch.
Du må start med å lage en fork av dette repoet til din egen GitHub konto.
- URL for innlogging er https://244530008913.signin.aws.amazon.com/console
- Logg på med brukernavn og passord gitt i klassrommet
- Gå til tjenesten Cloud9 (Du nå søke på Cloud9 uten mellomrom i søket)
- Velg "My environments" - pass på at du er i Ireland region.
- Velg "Open IDE"
git clone https://github.com/≤github bruker>/spring-docker-dockerhub.git
Får du denne feilmeldingen bash: /spring-docker-dockerhub: Permission denied
- så glemte du å bytte ut med
ditt eget Github brukernavn :-)
Du kan hoppe over dette steget hvis du allerede har laget et Token
- Når du skal autentisere deg mot din GitHub konto fra Cloud 9 trenger du et access token. Gå til https://github.com/settings/tokens og lag et nytt.
- Velg "Classic"
- Gi token et navn, det skal også ha "repository", og "workflow" rettigheter
- NB. Ta vare på tokenet et sted, du trenger dette senere når du skal gjøre
git push
(NB! Det kan hende du har gjort dette før, du kan da hoppe over stegene)
Følgende steg trenger du bare gjøre en gang i Cloud9 miljøet ditt. Du kan hoppe over hele steget hvis du har gjort det tidligere. For å slippe å autentisere seg hele tiden kan man få git til å cache nøkler i et valgfritt antall sekunder på denne måten.
git config --global credential.helper "cache --timeout=86400"
Konfigurer også brukernavnet og eposten din for GitHub CLI. Da slipepr du advarsler i terminalen når du gjør commit senere.
git config --global user.name <github brukernavn>
git config --global user.email <email for github bruker>
Verifiser at Docker er installert i Cloud 9
docker run hello-world
Forventet resultat
Pulling repository hello-world
91c95931e552: Download complete
a8219747be10: Download complete
Status:
Downloaded newer image for hello-world:latest
Hello from Docker.
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker Engine CLI client contacted the Docker Engine daemon.
2. The Docker Engine daemon pulled the "hello-world" image from the Docker Hub.
(Assuming it was not already locally available.)
3. The Docker Engine daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker Engine daemon streamed that output to the Docker Engine CLI client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
For more examples and ideas, visit:
https://docs.docker.com/userguide/
Kjør kommandoen
docker images
Du vil se at Docker har lastet ned et hello-world container image til Cloud 9 miljøet ditt. Vi skal nå slette dette, men vi må først fjerne en stoppet container som er basert på dette imaget
Kjør først kommandoen docker ps
for å se hvilke containere som kjører. Du vil få en tom liste
docker ps
Legger du på -a argumentet, vil du også se stoppede containere
docker ps -a
Du kan få output som for eksempel
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5a89931c5af6 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago fervent_bell
Slet den stoppede containeren med
docker rm <container id> - i eksemplet over 5a89931c5af6
Docker-kommandoen docker rm brukes til å fjerne en eller flere stoppede containere. Kommandoen fjerner ikke kjørende containere; den fungerer kun på stoppede containere, men du kan overstyre dette med
docker rm -f [container_id]
Kjør docker images
igjen, og kjør kommandoen
docker image rm <REPOSITORY>
Docker-kommandoen docker images rm brukes til å slette et container image.
Installer maven i Cloud 9. Vi skal forsøke å kjøre Spring Boot applikasjonen fra Maven i terminalen
sudo wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
sudo sed -i s/\$releasever/6/g /etc/yum.repos.d/epel-apache-maven.repo
sudo yum install -y apache-maven
Sjekk at du kan kjøre Spring Boot applikasjonen med Maven
cd spring-docker-dockerhub
mvn spring-boot:run
Sjekk at applikasjonen kjører. Åpne en ny terminal i Cloud 9 og kjør
curl localhost:8080
Hvis du vil kan du også velge Tools/Preview running application fra menyen i Cloud 9 istedet.
Nå skal vi lage en Dockerfile for Spring Boot-applikasjonen. Vi skal bruke en "multi stage" Docker fil, som først lager en container som har alle verktøy til å bygge applikasjonen, maven osv. Spring boot applikasjonen blir kompilert og bygget i denne containeren. Deretter bruker den resultatet fra byggeprosessen, JAR filen til å lage en runtime container for applikasjonen.
Ta gjerne en pause og les gjerne mer om multi stage builds her; https://docs.docker.com/develop/develop-images/multistage-build/
Kopier dette innholder inn i en Dockerfile
i rotkatalogen
# Build the Maven project using Java 17
FROM maven:3.8-eclipse-temurin-17 as builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn package
# Use a base image with Java 17
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar /app/application.jar
ENTRYPOINT ["java", "-jar", "/app/application.jar"]
Prøv å bygge en Docker container
docker build . --tag <give the image a name>
Du må først huske å avslutte (Ctrl+c) applikasjonen du started med maven. Prøv å starte en container basert dette container image.
docker run <image tag used above>
Når du starter en container, så lytter ikke applikasjonen i Cloud 9 på port 8080. Hvorfor ikke ? Hint; port mapping Kan du start to versjoner av samme container, hvor en lytter på port 8080 og den andre på 8081?
!Viktig! Passordet ditt til Dockerhub blir liggende på EC2 Instansen (Serveren) i AWS, og i utgangspunktet kan alle dine medstudenter logge seg inn i ditt Cloud9 miljø, siden vi deler passord. Jeg vil derfor anbefale å lage en helt ny DockerHub bruker for PGR301, og ikke bruke et passord du vanligvis bruker.
Når du autentiserer deg mot Dockerhub fra Cloud9, er det beste praksis å ikke benytte passord men et Token. Et token kan du lage ved å klikke på ditt profilbilde (øverst til høyre) - og deretter "Account Settings", Personal Access tokens, og Generate Token.
- Gi tokenet et navn og read/write/delete permissions.
docker login
docker tag <tag> <dockerhub_username>/<tag_remote>
docker push <username>/<tag_remote>
Example:
docker login
docker tag fantasticapp glennbech/fantasticapp
docker push glennbech/fantasticapp
Gå til dockerhub.com og se på container image du nettopp lastet opp.
Del gjerne Docker hub container image navnet med andre, så de kan forsøke å kjøre det med docker run
mitt container image heter glennbech/shaky
Finn ut av det selv :-) Kan du gjøre det fra AWS CLI istedet for UI? Velg et navn med dine initialer, så vi ikke får navnekonflikter.
Fra dit Cloud9 miljøe, autentiser docker mot AWS ECR med kommandoen
aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin 244530008913.dkr.ecr.eu-west-1.amazonaws.com
Denne ser kanskje litt kryptisk ut, dette er hva som skjer steg for steg
Denne delen av kommandoen bruker AWS CLI (aws) til å hente et midlertidig innloggingspassord for ECR (Elastic Container Registry). get-login-password er en AWS-kommando som returnerer et passord som er nødvendig for å autentisere Docker mot ECR. --region eu-west-1 spesifiserer hvilken region du vil hente passordet for. I dette tilfellet er regionen eu-west-1 (Vest-Europa, Irland).
- Symbolet | er en pipe som brukes til å sende output fra den første kommandoen (passordet) som input til den neste kommandoen.
- docker login --username AWS --password-stdin 244530008913.dkr.ecr.eu-west-1.amazonaws.com er kommandoen for å logge inn på Docker, hvor --username AWS angir at brukernavnet er AWS. --password-stdin gjør det mulig for Docker å lese passordet fra standard input (stdin), som i dette tilfellet kommer fra den første kommandoen via pipen.
- 244530008913.dkr.ecr.eu-west-1.amazonaws.com er URL-en til ECR-registeret du prøver å logge inn på.
- Dette spesifiserer nøyaktig hvilket ECR-register Docker skal autentisere mot.
Eksempel:
docker build -t <ditt tagnavn> .
docker tag <ditt tagnavn> 244530008913.dkr.ecr.eu-west-1.amazonaws.com/<ditt ECR repo navn>
docker push 244530008913.dkr.ecr.eu-west-1.amazonaws.com/<ditt ECR repo navn>
Gå til tjenesten ECR i AWS og se at du har fått et container image i ditt registry
Få GitHub Actions til å bygge & pushe et nytt Image hver gang noen lager en ny commit på main branch
For å lage github actions workflows lager du en fil under .github/workflows katalogen i repsoitory.
Her er et eksempel på en workflow tatt fra foreleser sitt miljø, du må gjøre endringer for å tilpasse den ditt eget? Lykke til!
NB. Du må først legge til Repository secrets for å gi GitHub actions AWS nøkler!
name: Publish Docker image
on:
push:
branches:
- main
jobs:
push_to_registry:
name: Push Docker image to ECR
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v2
- name: Build and push Docker image
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin 244530008913.dkr.ecr.eu-west-1.amazonaws.com
rev=$(git rev-parse --short HEAD)
docker build . -t hello
docker tag hello 244530008913.dkr.ecr.eu-west-1.amazonaws.com/glenn:$rev
docker push 244530008913.dkr.ecr.eu-west-1.amazonaws.com/glenn:$rev
Gjør endringer på koden i main branch - se at GitHub actions lager et nytt container image og laster opp til ECR.
- Kan du laste opp image til både AWS ECR, men også Docker Hub fra GitHub Actions workflowen?
- Kan du kjøre Spring boot applikasjonen din på tjenesten AWS Apprunner ? https://docs.aws.amazon.com/apprunner/latest/dg/what-is-apprunner.html