diff --git a/MF05-PRA05.md b/MF05-PRA05.md index 327509b8..185c03aa 100644 --- a/MF05-PRA05.md +++ b/MF05-PRA05.md @@ -11,39 +11,95 @@ This practical exercise will guide you through setting up a Jenkins CI/CD pipeli Pull the official Jenkins Docker image from DockerHub: ```bash -docker pull jenkins/jenkins:lts +sudo docker pull jenkins/jenkins:lts ``` +![](PRA05_ANSWER/screenshots/1-pull-jenkins-docker-image.png) #### 2. Build and Run Jenkins Container -Create and run a Jenkins container: +Create and run a Jenkins container **with privileges**: ```bash -docker run -d -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home --name jenkins jenkins/jenkins:lts +sudo docker run --privileged -d -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home --name jenkins jenkins/jenkins:lts ``` +![](PRA05_ANSWER/screenshots/2-0-build-and-run-jenkins-container.png) + To pause the container: ```bash docker pause jenkins ``` +![](PRA05_ANSWER/screenshots/2-1-pause-the-container.png) To resume: ```bash docker unpause jenkins ``` +![](PRA05_ANSWER/screenshots/2-2-to-resume.png) #### 3. Configure Jenkins Account -Access Jenkins at `http://localhost:8080` and follow the setup wizard. Retrieve the initial admin password from the Docker logs: +Access Jenkins at `http://localhost:8081` and follow the setup wizard. Retrieve the initial admin password from the Docker logs: ```bash docker logs jenkins ``` +![](PRA05_ANSWER/screenshots/3-0-retrieve-initial-admin-pwd.png) Create an admin account during the setup process. +![](PRA05_ANSWER/screenshots/3-1-creation-admin-account-during-setup-process.png) + + +#### 3.1 Install Docker inside Jenkins: bash from host + +Here's a summary of the steps to install Docker in a Jenkins container: + +1. On the Linux host: + + ```bash + sudo docker exec -it --user root jenkins bash + ``` + This command accesses the Jenkins container's bash console. + +2. Inside the Jenkins container: + + ```bash + curl https://get.docker.com/ > dockerinstall && chmod 777 dockerinstall && ./dockerinstall + ``` + This downloads and runs the Docker installation script. + ![](PRA05_ANSWER/screenshots/3-2-installation-docker-in-jenkins.png) + +3. Still inside the Jenkins container: + + ```bash + usermod -aG docker jenkins + ``` + + This adds the Jenkins user to the Docker group. + ![](PRA05_ANSWER/screenshots/3-3-jenkins-docker-group.png) + +4. If permission issues persist, inside the Jenkins container: + + ```bash + chmod 666 /var/run/docker.sock + ``` + + This changes the permissions of the Docker socket. + ![](PRA05_ANSWER/screenshots/3-4-permissions-docker-socket.png) + +5. Back on the Linux host: + + ```bash + docker restart jenkins2 + ``` + + This restarts the Jenkins container to apply the changes. + +Note that steps 2-4 are executed within the Jenkins container's bash, while steps 1 and 5 are performed on the Linux host machine. + #### 4. Install Basic Plugins In Jenkins, go to "Manage Jenkins" > "Manage Plugins" and install these plugins: @@ -54,23 +110,59 @@ In Jenkins, go to "Manage Jenkins" > "Manage Plugins" and install these plugins: - SSH - SonarQube Scanner +**Plugins** that are **already installed**: Git Client, Pipeline and Pipeline: Graph View. + +**Available** plugins to **install**: + +- Maven Integration +- Docker +- Docker Pipeline +- SSH +- SonarQube Scanner +- JDK Tool +- AWS Java SDK Secrets Manager +- AWS Java SDK ECS +- Amazon ECR + +![](PRA05_ANSWER/screenshots/4-0-basic-public-installation.png) + +#### 4.1 Configure tools +JDK + +![](PRA05_ANSWER/screenshots/4-3-jdk-tool.png) + +Git + +![](PRA05_ANSWER/screenshots/4-4-git-tool.png) + +Maven + +![](PRA05_ANSWER/screenshots/4-5-maven-tool.png) + #### 5. Create a Pipeline for Spring Boot Project -Create a new pipeline job in Jenkins and use this script: +Create a new pipeline job in Jenkins: ```groovy pipeline { agent any + + environment { + DOCKERHUB_CREDENTIALS = credentials('dockerhub_id') + IMAGE_NAME = 'marcius02/bookspageable' + IMAGE_TAG = "${BUILD_NUMBER}" + } + tools { - maven 'Maven' - jdk 'JDK' + maven 'M3' + jdk 'JDK21' } stages { stage('Checkout') { steps { - git 'https://github.com/yourusername/PageableBooks.git' + git 'https://github.com/AlbertProfe/BooksPageable.git' } } @@ -80,64 +172,66 @@ pipeline { } } - stage('Docker Build') { + stage('Archive') { + steps { + archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true + } + } + + stage('Build Docker Image') { steps { script { - docker.build("pageablebooks:${env.BUILD_ID}") + // Build the Docker image and tag it with both BUILD_NUMBER and latest + sh "docker build -t ${IMAGE_NAME}:${IMAGE_TAG} -t ${IMAGE_NAME}:latest ." } } } - - stage('Docker Run') { + + stage('Push to DockerHub') { steps { script { - docker.image("pageablebooks:${env.BUILD_ID}").run('-p 8080:8080') + // Login to DockerHub + sh "echo ${DOCKERHUB_CREDENTIALS_PSW} | docker login -u ${DOCKERHUB_CREDENTIALS_USR} --password-stdin" + + // Push both the specific tag and the latest tag + sh "docker push ${IMAGE_NAME}:${IMAGE_TAG}" + sh "docker push ${IMAGE_NAME}:latest" } } } } -} + + post { + always { + // Logout from DockerHub and remove images + sh "docker logout" + sh "docker rmi ${IMAGE_NAME}:${IMAGE_TAG} || true" + sh "docker rmi ${IMAGE_NAME}:latest || true" + } + } + } ``` -Ensure your Spring Boot project (PageableBooks) has a Dockerfile in its root directory: - -```dockerfile -FROM openjdk:11-jre-slim -ARG JAR_FILE=target/*.jar -COPY ${JAR_FILE} app.jar -ENTRYPOINT ["java","-jar","/app.jar"] -``` -This pipeline will checkout your code, build the Spring Boot application, create a Docker image, and run it[1][2][3][4][5]. +This Jenkins pipeline automates the process of building a Docker image for a Java project, pushing the image to DockerHub, and cleaning up afterward. -### Additional Notes +Docker Hub +![](PRA05_ANSWER/screenshots/5-0-dockerhub.png) -- Ensure Docker is installed on the Jenkins server. -- Configure Docker permissions for the Jenkins user. -- Adjust the pipeline script according to your project structure and requirements. +Status +![](PRA05_ANSWER/screenshots/5-1-status.png) -### Submission Guidelines +Timings +![](PRA05_ANSWER/screenshots/5-2-timings.png) -- Fork the repository or create a new one on GitHub. -- Create a branch named `MF05-PRA05-YourNameAndSurname`. -- Implement the required changes and add the Jenkins pipeline script. -- Commit with clear messages. -- Push your branch and create a pull request titled `MF05-PRA05-YourNameAndSurname-JenkinsPipeline`. -- Create a `PRA05_ANSWER` folder to save the answer, docs, and images. +Build Data +![](PRA05_ANSWER/screenshots/5-3-build-data.png) -### Evaluation Criteria +Pipe Overview +![](PRA05_ANSWER/screenshots/5-4-pipe-overview.png) -- Successful setup of Jenkins in Docker. -- Correct installation and configuration of required plugins. -- Proper implementation of the Jenkins pipeline for the Spring Boot project. -- Successful Docker integration within the pipeline. -- Clear documentation and commit messages. +Pipe console +![](PRA05_ANSWER/screenshots/5-5-pipe-console.png) -Citations: -[1] https://dev.to/hackmamba/jenkins-in-docker-running-docker-in-a-jenkins-container-1je?comments_sort=top -[2] https://www.red-gate.com/simple-talk/devops/containers-and-virtualization/deploying-a-dockerized-application-to-the-kubernetes-cluster-using-jenkins/ -[3] https://devopscube.com/docker-containers-as-build-slaves-jenkins/ -[4] https://www.youtube.com/watch?v=RKaxATb2kz8 -[5] https://www.jenkins.io/doc/book/installing/docker/ -[6] https://github.com/jenkinsci/docker -[7] https://phoenixnap.com/kb/how-to-configure-docker-in-jenkins \ No newline at end of file +Workspace +![](PRA05_ANSWER/screenshots/5-6-workspace.png) \ No newline at end of file diff --git a/PRA05_ANSWER/output.txt b/PRA05_ANSWER/output.txt new file mode 100644 index 00000000..e62a627a --- /dev/null +++ b/PRA05_ANSWER/output.txt @@ -0,0 +1,257 @@ +Started by user Marc Fernández +[Pipeline] Start of Pipeline +[Pipeline] node +Running on Jenkins in /var/jenkins_home/workspace/Spring Boot +[Pipeline] { +[Pipeline] withCredentials +Masking supported pattern matches of $DOCKERHUB_CREDENTIALS or $DOCKERHUB_CREDENTIALS_PSW +[Pipeline] { +[Pipeline] withEnv +[Pipeline] { +[Pipeline] stage +[Pipeline] { (Declarative: Tool Install) +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] } +[Pipeline] // stage +[Pipeline] withEnv +[Pipeline] { +[Pipeline] stage +[Pipeline] { (Checkout) +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] withEnv +[Pipeline] { +[Pipeline] git +The recommended git tool is: NONE +No credentials specified + > git rev-parse --resolve-git-dir /var/jenkins_home/workspace/Spring Boot/.git # timeout=10 +Fetching changes from the remote Git repository + > git config remote.origin.url https://github.com/AlbertProfe/BooksPageable.git # timeout=10 +Fetching upstream changes from https://github.com/AlbertProfe/BooksPageable.git + > git --version # timeout=10 + > git --version # 'git version 2.39.5' + > git fetch --tags --force --progress -- https://github.com/AlbertProfe/BooksPageable.git +refs/heads/*:refs/remotes/origin/* # timeout=10 + > git rev-parse refs/remotes/origin/master^{commit} # timeout=10 +Checking out Revision 9a7a31ad1a82a34a4c870b6aaf5f506c832f968b (refs/remotes/origin/master) + > git config core.sparsecheckout # timeout=10 + > git checkout -f 9a7a31ad1a82a34a4c870b6aaf5f506c832f968b # timeout=10 + > git branch -a -v --no-abbrev # timeout=10 + > git branch -D master # timeout=10 + > git checkout -b master 9a7a31ad1a82a34a4c870b6aaf5f506c832f968b # timeout=10 +Commit message: "Dockerfile" + > git rev-list --no-walk 9a7a31ad1a82a34a4c870b6aaf5f506c832f968b # timeout=10 +[Pipeline] } +[Pipeline] // withEnv +[Pipeline] } +[Pipeline] // stage +[Pipeline] stage +[Pipeline] { (Build) +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] withEnv +[Pipeline] { +[Pipeline] sh ++ mvn clean package +[INFO] Scanning for projects... +[INFO] +[INFO] ----------------------< io.company:BooksPageable >---------------------- +[INFO] Building library6 0.0.1-SNAPSHOT +[INFO] from pom.xml +[INFO] --------------------------------[ jar ]--------------------------------- +[INFO] +[INFO] --- clean:3.2.0:clean (default-clean) @ BooksPageable --- +[INFO] Deleting /var/jenkins_home/workspace/Spring Boot/target +[INFO] +[INFO] --- resources:3.3.1:resources (default-resources) @ BooksPageable --- +[INFO] Copying 1 resource from src/main/resources to target/classes +[INFO] Copying 1 resource from src/main/resources to target/classes +[INFO] +[INFO] --- compiler:3.11.0:compile (default-compile) @ BooksPageable --- +[INFO] Changes detected - recompiling the module! :source +[INFO] Compiling 7 source files with javac [debug release 21] to target/classes +[INFO] Annotation processing is enabled because one or more processors were found + on the class path. A future release of javac may disable annotation processing + unless at least one processor is specified by name (-processor), or a search + path is specified (--processor-path, --processor-module-path), or annotation + processing is enabled explicitly (-proc:only, -proc:full). + Use -Xlint:-options to suppress this message. + Use -proc:none to disable annotation processing. +[INFO] +[INFO] --- resources:3.3.1:testResources (default-testResources) @ BooksPageable --- +[INFO] skip non existing resourceDirectory /var/jenkins_home/workspace/Spring Boot/src/test/resources +[INFO] +[INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ BooksPageable --- +[INFO] No sources to compile +[INFO] +[INFO] --- surefire:3.0.0:test (default-test) @ BooksPageable --- +[INFO] No tests to run. +[INFO] +[INFO] --- jar:3.3.0:jar (default-jar) @ BooksPageable --- +[INFO] Building jar: /var/jenkins_home/workspace/Spring Boot/target/BooksPageable-0.0.1-SNAPSHOT.jar +[INFO] +[INFO] --- spring-boot:3.1.12:repackage (repackage) @ BooksPageable --- +[INFO] Replacing main artifact /var/jenkins_home/workspace/Spring Boot/target/BooksPageable-0.0.1-SNAPSHOT.jar with repackaged archive, adding nested dependencies in BOOT-INF/. +[INFO] The original artifact has been renamed to /var/jenkins_home/workspace/Spring Boot/target/BooksPageable-0.0.1-SNAPSHOT.jar.original +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 9.134 s +[INFO] Finished at: 2024-12-10T10:52:11Z +[INFO] ------------------------------------------------------------------------ +[Pipeline] } +[Pipeline] // withEnv +[Pipeline] } +[Pipeline] // stage +[Pipeline] stage +[Pipeline] { (Archive) +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] withEnv +[Pipeline] { +[Pipeline] archiveArtifacts +Archiving artifacts +Recording fingerprints +[Pipeline] } +[Pipeline] // withEnv +[Pipeline] } +[Pipeline] // stage +[Pipeline] stage +[Pipeline] { (Build Docker Image) +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] withEnv +[Pipeline] { +[Pipeline] script +[Pipeline] { +[Pipeline] sh ++ docker build -t marcius02/bookspageable:11 -t marcius02/bookspageable:latest . +#0 building with "default" instance using docker driver + +#1 [internal] load build definition from Dockerfile +#1 transferring dockerfile: 168B done +#1 DONE 0.0s + +#2 [internal] load metadata for docker.io/library/openjdk:21-slim +#2 DONE 1.9s + +#3 [internal] load .dockerignore +#3 transferring context: 2B done +#3 DONE 0.0s + +#4 [1/3] FROM docker.io/library/openjdk:21-slim@sha256:7072053847a8a05d7f3a14ebc778a90b38c50ce7e8f199382128a53385160688 +#4 DONE 0.0s + +#5 [internal] load build context +#5 transferring context: 49.46MB 0.5s done +#5 DONE 0.5s + +#6 [2/3] WORKDIR /app +#6 CACHED + +#7 [3/3] COPY target/*.jar app.jar +#7 DONE 2.1s + +#8 exporting to image +#8 exporting layers +#8 exporting layers 0.3s done +#8 writing image sha256:9e62ba638aca9de6384e59859aa03b88fab952a5b08225f50ebb66dd7d18a5ce done +#8 naming to docker.io/marcius02/bookspageable:11 0.0s done +#8 naming to docker.io/marcius02/bookspageable:latest 0.0s done +#8 DONE 0.4s +[Pipeline] } +[Pipeline] // script +[Pipeline] } +[Pipeline] // withEnv +[Pipeline] } +[Pipeline] // stage +[Pipeline] stage +[Pipeline] { (Push to DockerHub) +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] tool +[Pipeline] envVarsForTool +[Pipeline] withEnv +[Pipeline] { +[Pipeline] script +[Pipeline] { +[Pipeline] sh +Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure. + Affected argument(s) used the following variable(s): [DOCKERHUB_CREDENTIALS_PSW] + See https://jenkins.io/redirect/groovy-string-interpolation for details. ++ echo **** ++ docker login -u marcius02 --password-stdin +WARNING! Your password will be stored unencrypted in /var/jenkins_home/.docker/config.json. +Configure a credential helper to remove this warning. See +https://docs.docker.com/engine/reference/commandline/login/#credential-stores + +Login Succeeded +[Pipeline] sh ++ docker push marcius02/bookspageable:11 +The push refers to repository [docker.io/marcius02/bookspageable] +1ba9c4872624: Preparing +dda09200380e: Preparing +659a8c4ba776: Preparing +0ac7ecf8a41c: Preparing +d310e774110a: Preparing +dda09200380e: Pushed +0ac7ecf8a41c: Pushed +d310e774110a: Pushed +1ba9c4872624: Pushed +659a8c4ba776: Pushed +11: digest: sha256:da609cbe772f3c1a4857429f97f7d11b8e739cc41d6ba048ddb343e511ae8325 size: 1371 +[Pipeline] sh ++ docker push marcius02/bookspageable:latest +The push refers to repository [docker.io/marcius02/bookspageable] +1ba9c4872624: Preparing +dda09200380e: Preparing +659a8c4ba776: Preparing +0ac7ecf8a41c: Preparing +d310e774110a: Preparing +d310e774110a: Layer already exists +659a8c4ba776: Layer already exists +0ac7ecf8a41c: Layer already exists +dda09200380e: Layer already exists +1ba9c4872624: Layer already exists +latest: digest: sha256:da609cbe772f3c1a4857429f97f7d11b8e739cc41d6ba048ddb343e511ae8325 size: 1371 +[Pipeline] } +[Pipeline] // script +[Pipeline] } +[Pipeline] // withEnv +[Pipeline] } +[Pipeline] // stage +[Pipeline] stage +[Pipeline] { (Declarative: Post Actions) +[Pipeline] sh ++ docker logout +Removing login credentials for https://index.docker.io/v1/ +[Pipeline] sh ++ docker rmi marcius02/bookspageable:11 +Untagged: marcius02/bookspageable:11 +[Pipeline] sh ++ docker rmi marcius02/bookspageable:latest +Untagged: marcius02/bookspageable:latest +Untagged: marcius02/bookspageable@sha256:da609cbe772f3c1a4857429f97f7d11b8e739cc41d6ba048ddb343e511ae8325 +Deleted: sha256:9e62ba638aca9de6384e59859aa03b88fab952a5b08225f50ebb66dd7d18a5ce +[Pipeline] } +[Pipeline] // stage +[Pipeline] } +[Pipeline] // withEnv +[Pipeline] } +[Pipeline] // withEnv +[Pipeline] } +[Pipeline] // withCredentials +[Pipeline] } +[Pipeline] // node +[Pipeline] End of Pipeline +Finished: SUCCESS diff --git a/PRA05_ANSWER/pipeline.groovy b/PRA05_ANSWER/pipeline.groovy new file mode 100644 index 00000000..ab29f1e6 --- /dev/null +++ b/PRA05_ANSWER/pipeline.groovy @@ -0,0 +1,66 @@ +pipeline { + agent any + + environment { + DOCKERHUB_CREDENTIALS = credentials('dockerhub_id') + IMAGE_NAME = 'marcius02/bookspageable' + IMAGE_TAG = "${BUILD_NUMBER}" + } + + + tools { + maven 'M3' + jdk 'JDK21' + } + + stages { + stage('Checkout') { + steps { + git 'https://github.com/AlbertProfe/BooksPageable.git' + } + } + + stage('Build') { + steps { + sh 'mvn clean package' + } + } + + stage('Archive') { + steps { + archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true + } + } + + stage('Build Docker Image') { + steps { + script { + // Build the Docker image and tag it with both BUILD_NUMBER and latest + sh "docker build -t ${IMAGE_NAME}:${IMAGE_TAG} -t ${IMAGE_NAME}:latest ." + } + } + } + + stage('Push to DockerHub') { + steps { + script { + // Login to DockerHub + sh "echo ${DOCKERHUB_CREDENTIALS_PSW} | docker login -u ${DOCKERHUB_CREDENTIALS_USR} --password-stdin" + + // Push both the specific tag and the latest tag + sh "docker push ${IMAGE_NAME}:${IMAGE_TAG}" + sh "docker push ${IMAGE_NAME}:latest" + } + } + } + } + + post { + always { + // Logout from DockerHub and remove images + sh "docker logout" + sh "docker rmi ${IMAGE_NAME}:${IMAGE_TAG} || true" + sh "docker rmi ${IMAGE_NAME}:latest || true" + } + } + } diff --git a/PRA05_ANSWER/screenshots/1-pull-jenkins-docker-image.png b/PRA05_ANSWER/screenshots/1-pull-jenkins-docker-image.png new file mode 100644 index 00000000..02bfec61 Binary files /dev/null and b/PRA05_ANSWER/screenshots/1-pull-jenkins-docker-image.png differ diff --git a/PRA05_ANSWER/screenshots/2-0-build-and-run-jenkins-container.png b/PRA05_ANSWER/screenshots/2-0-build-and-run-jenkins-container.png new file mode 100644 index 00000000..2fc23f5d Binary files /dev/null and b/PRA05_ANSWER/screenshots/2-0-build-and-run-jenkins-container.png differ diff --git a/PRA05_ANSWER/screenshots/2-1-pause-the-container.png b/PRA05_ANSWER/screenshots/2-1-pause-the-container.png new file mode 100644 index 00000000..f7e6bfac Binary files /dev/null and b/PRA05_ANSWER/screenshots/2-1-pause-the-container.png differ diff --git a/PRA05_ANSWER/screenshots/2-2-to-resume.png b/PRA05_ANSWER/screenshots/2-2-to-resume.png new file mode 100644 index 00000000..28e5ed3b Binary files /dev/null and b/PRA05_ANSWER/screenshots/2-2-to-resume.png differ diff --git a/PRA05_ANSWER/screenshots/3-0-retrieve-initial-admin-pwd.png b/PRA05_ANSWER/screenshots/3-0-retrieve-initial-admin-pwd.png new file mode 100644 index 00000000..d0acec66 Binary files /dev/null and b/PRA05_ANSWER/screenshots/3-0-retrieve-initial-admin-pwd.png differ diff --git a/PRA05_ANSWER/screenshots/3-1-creation-admin-account-during-setup-process.png b/PRA05_ANSWER/screenshots/3-1-creation-admin-account-during-setup-process.png new file mode 100644 index 00000000..c148a6d4 Binary files /dev/null and b/PRA05_ANSWER/screenshots/3-1-creation-admin-account-during-setup-process.png differ diff --git a/PRA05_ANSWER/screenshots/3-2-installation-docker-in-jenkins.png b/PRA05_ANSWER/screenshots/3-2-installation-docker-in-jenkins.png new file mode 100644 index 00000000..330c1f00 Binary files /dev/null and b/PRA05_ANSWER/screenshots/3-2-installation-docker-in-jenkins.png differ diff --git a/PRA05_ANSWER/screenshots/3-3-jenkins-docker-group.png b/PRA05_ANSWER/screenshots/3-3-jenkins-docker-group.png new file mode 100644 index 00000000..91c26698 Binary files /dev/null and b/PRA05_ANSWER/screenshots/3-3-jenkins-docker-group.png differ diff --git a/PRA05_ANSWER/screenshots/3-4-permissions-docker-socket.png b/PRA05_ANSWER/screenshots/3-4-permissions-docker-socket.png new file mode 100644 index 00000000..fb093b12 Binary files /dev/null and b/PRA05_ANSWER/screenshots/3-4-permissions-docker-socket.png differ diff --git a/PRA05_ANSWER/screenshots/4-0-basic-public-installation.png b/PRA05_ANSWER/screenshots/4-0-basic-public-installation.png new file mode 100644 index 00000000..e1ca7997 Binary files /dev/null and b/PRA05_ANSWER/screenshots/4-0-basic-public-installation.png differ diff --git a/PRA05_ANSWER/screenshots/4-3-jdk-tool.png b/PRA05_ANSWER/screenshots/4-3-jdk-tool.png new file mode 100644 index 00000000..d1a4f45f Binary files /dev/null and b/PRA05_ANSWER/screenshots/4-3-jdk-tool.png differ diff --git a/PRA05_ANSWER/screenshots/4-4-git-tool.png b/PRA05_ANSWER/screenshots/4-4-git-tool.png new file mode 100644 index 00000000..190fb353 Binary files /dev/null and b/PRA05_ANSWER/screenshots/4-4-git-tool.png differ diff --git a/PRA05_ANSWER/screenshots/4-5-maven-tool.png b/PRA05_ANSWER/screenshots/4-5-maven-tool.png new file mode 100644 index 00000000..b98b1b73 Binary files /dev/null and b/PRA05_ANSWER/screenshots/4-5-maven-tool.png differ diff --git a/PRA05_ANSWER/screenshots/5-0-dockerhub.png b/PRA05_ANSWER/screenshots/5-0-dockerhub.png new file mode 100644 index 00000000..94086508 Binary files /dev/null and b/PRA05_ANSWER/screenshots/5-0-dockerhub.png differ diff --git a/PRA05_ANSWER/screenshots/5-1-status.png b/PRA05_ANSWER/screenshots/5-1-status.png new file mode 100644 index 00000000..31517703 Binary files /dev/null and b/PRA05_ANSWER/screenshots/5-1-status.png differ diff --git a/PRA05_ANSWER/screenshots/5-2-timings.png b/PRA05_ANSWER/screenshots/5-2-timings.png new file mode 100644 index 00000000..4e033f30 Binary files /dev/null and b/PRA05_ANSWER/screenshots/5-2-timings.png differ diff --git a/PRA05_ANSWER/screenshots/5-3-build-data.png b/PRA05_ANSWER/screenshots/5-3-build-data.png new file mode 100644 index 00000000..32990b9d Binary files /dev/null and b/PRA05_ANSWER/screenshots/5-3-build-data.png differ diff --git a/PRA05_ANSWER/screenshots/5-4-pipe-overview.png b/PRA05_ANSWER/screenshots/5-4-pipe-overview.png new file mode 100644 index 00000000..9545502a Binary files /dev/null and b/PRA05_ANSWER/screenshots/5-4-pipe-overview.png differ diff --git a/PRA05_ANSWER/screenshots/5-5-pipe-console.png b/PRA05_ANSWER/screenshots/5-5-pipe-console.png new file mode 100644 index 00000000..5c1dc104 Binary files /dev/null and b/PRA05_ANSWER/screenshots/5-5-pipe-console.png differ diff --git a/PRA05_ANSWER/screenshots/5-6-workspace.png b/PRA05_ANSWER/screenshots/5-6-workspace.png new file mode 100644 index 00000000..3539ad43 Binary files /dev/null and b/PRA05_ANSWER/screenshots/5-6-workspace.png differ