LAB : Setup Repo privé avec Harbor#
Présentation#
Objectifs:#
- Mise en place d'un repository privé d'hébergement d'images Docker avec Harbor
- Configuration des credentials de communication entre Jenkins et Harbor
- Test push image depuis Jenkins vers Harbor
Prérequis#
- Connaissance de Docker et GIT
- Instance docker fonctionnel
- Editeur de code
- Utilitaire installé sur la machine: git
- Avoir un proxy nginx fonctionnel (voir lab deploy reverse proxy sur la section 03-conteneurisation)
- Avoir un jenkins de fonctionnel voir lab du stage 6
Jenkins sur Docker - Avoir un repo Github hébergeant de façon privé le code springboot-react-app, voir lab du stage 6
Pipeline Jenkins avec Docker
Déroulement du Lab#
Etape 1 : Mise en place de Harbor#
Dans cette étape, on va mettre en place et configurer Harbor
- Télécharger et décompresser la dernière version de Harbor depuis le repo officiel sur Github
wget https://github.com/goharbor/harbor/releases/download/v2.12.2/harbor-online-installer-v2.12.2.tgz
tar xzvf harbor-online-installer-v2.12.2.tgz
- Se rendre dans le dossier de configuration de harbor et configurer le fichier
harbor.yml
cd harbor
mv harbor.yml.tmpl harbor.yml
vi harbor.yml
- Ouvrir le fichier et effectuer les changements ci-dessous :
--> Changer le hostname par registry.lcf.io
--> Modifier le port d'écoute de http à 8081
--> commenter les lignes relatives à https
On doit se retrouver avec ce contenu ci-dessous :
# Configuration file of Harbor
# The IP address or hostname to access admin UI and registry service.
# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
hostname: registry.lcf.io
# http related config
http:
# port for http, default is 80. If https enabled, this port will redirect to https port
port: 8081
# https related config
#https:
# https port for harbor, default is 443
# port: 443
# The path of cert and key files for nginx
# certificate: /your/certificate/path
#private_key: /your/private/key/path
# enable strong ssl ciphers (default: false)
# strong_ssl_ciphers: false
--> Ensuite dans le meme fichier, rechercher la ligne contenant l'instruction external_url, le décommenter et lui mettre la valeur http://registry.lcf.io. Ceci nous permettra d'utiliser notre propre proxy et configurer notre url d'accès à Harbor
# Uncomment external_url if you want to enable external proxy
# And when it enabled the hostname will no longer used
external_url: http://registry.lcf.io
Etape 2 : Lancement des services Harbor#
On va maintenant lancer la préparation pour que harbor puisse télécharger les images et dépendances nécessaires ainsi que les fichiers de configuration necessaires selon ce qui est défini dans le fichier harbor.yml
- Lancer cette commande dans le meme répertoire harbor
sudo ./prepare --with-trivy
- Lancer l'installation avec la commande ci-dessous :
sudo ./install.sh --with-trivy
- Afin de pouvoir utiliser notre proxy, il faudra modifier le fichier
docker-compose.ymlde harbor pour mettre son nginx dans le meme networkfrontendque celui de notre proxy. Pour cela faire ces modifications ci-dessous :
--> Rajouter ces lignes dans le bloc networks à la fin du fichier :
frontend:
external: true
--> rajouter le network frontend au niveau du service proxy
networks:
- harbor
- frontend
A la fin on aura ce contenu de notre fichier docker-compose.yml (vous pourrez mettre ce contenu à la place du contenu existant)
services:
log:
image: goharbor/harbor-log:v2.12.2
container_name: harbor-log
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- SETGID
- SETUID
volumes:
- /var/log/harbor/:/var/log/docker/:z
- type: bind
source: ./common/config/log/logrotate.conf
target: /etc/logrotate.d/logrotate.conf
- type: bind
source: ./common/config/log/rsyslog_docker.conf
target: /etc/rsyslog.d/rsyslog_docker.conf
ports:
- 127.0.0.1:1514:10514
networks:
- harbor
registry:
image: goharbor/registry-photon:v2.12.2
container_name: registry
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
volumes:
- /data/registry:/storage:z
- ./common/config/registry/:/etc/registry/:z
- type: bind
source: /data/secret/registry/root.crt
target: /etc/registry/root.crt
- type: bind
source: ./common/config/shared/trust-certificates
target: /harbor_cust_cert
networks:
- harbor
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "registry"
registryctl:
image: goharbor/harbor-registryctl:v2.12.2
container_name: registryctl
env_file:
- ./common/config/registryctl/env
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
volumes:
- /data/registry:/storage:z
- ./common/config/registry/:/etc/registry/:z
- type: bind
source: ./common/config/registryctl/config.yml
target: /etc/registryctl/config.yml
- type: bind
source: ./common/config/shared/trust-certificates
target: /harbor_cust_cert
networks:
- harbor
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "registryctl"
postgresql:
image: goharbor/harbor-db:v2.12.2
container_name: harbor-db
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- SETGID
- SETUID
volumes:
- /data/database:/var/lib/postgresql/data:z
networks:
harbor:
env_file:
- ./common/config/db/env
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "postgresql"
shm_size: '1gb'
core:
image: goharbor/harbor-core:v2.12.2
container_name: harbor-core
env_file:
- ./common/config/core/env
restart: always
cap_drop:
- ALL
cap_add:
- SETGID
- SETUID
volumes:
- /data/ca_download/:/etc/core/ca/:z
- /data/:/data/:z
- ./common/config/core/certificates/:/etc/core/certificates/:z
- type: bind
source: ./common/config/core/app.conf
target: /etc/core/app.conf
- type: bind
source: /data/secret/core/private_key.pem
target: /etc/core/private_key.pem
- type: bind
source: /data/secret/keys/secretkey
target: /etc/core/key
- type: bind
source: ./common/config/shared/trust-certificates
target: /harbor_cust_cert
networks:
harbor:
depends_on:
- log
- registry
- redis
- postgresql
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "core"
portal:
image: goharbor/harbor-portal:v2.12.2
container_name: harbor-portal
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
- NET_BIND_SERVICE
volumes:
- type: bind
source: ./common/config/portal/nginx.conf
target: /etc/nginx/nginx.conf
networks:
- harbor
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "portal"
jobservice:
image: goharbor/harbor-jobservice:v2.12.2
container_name: harbor-jobservice
env_file:
- ./common/config/jobservice/env
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
volumes:
- /data/job_logs:/var/log/jobs:z
- type: bind
source: ./common/config/jobservice/config.yml
target: /etc/jobservice/config.yml
- type: bind
source: ./common/config/shared/trust-certificates
target: /harbor_cust_cert
networks:
- harbor
depends_on:
- core
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "jobservice"
redis:
image: goharbor/redis-photon:v2.12.2
container_name: redis
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
volumes:
- /data/redis:/var/lib/redis
networks:
harbor:
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "redis"
proxy:
image: goharbor/nginx-photon:v2.12.2
container_name: nginx
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
- NET_BIND_SERVICE
volumes:
- ./common/config/nginx:/etc/nginx:z
- type: bind
source: ./common/config/shared/trust-certificates
target: /harbor_cust_cert
networks:
- harbor
- frontend
ports:
- 8081:8080
depends_on:
- registry
- core
- portal
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "proxy"
trivy-adapter:
container_name: trivy-adapter
image: goharbor/trivy-adapter-photon:v2.12.2
restart: always
cap_drop:
- ALL
depends_on:
- log
- redis
networks:
- harbor
volumes:
- type: bind
source: /data/trivy-adapter/trivy
target: /home/scanner/.cache/trivy
- type: bind
source: /data/trivy-adapter/reports
target: /home/scanner/.cache/reports
- type: bind
source: ./common/config/shared/trust-certificates
target: /harbor_cust_cert
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "trivy-adapter"
env_file:
./common/config/trivy-adapter/env
networks:
harbor:
external: false
frontend:
external: true
- Redémarrer les services Harbor:
docker compose up -d
- Vérifier que les services ont bien démarré :
docker ps
Etape 3 : Mise à jour de la configuration du proxy#
Le répertoire lecloudfacile-devops-labs/nginx-proxy/conf.d/harbor contient un exemple de configuration du proxy pour la gestion des requêtes entrantes en ce qui concerne l'application harbor. Nous pourrons la copier dans le répertoire lecloudfacile-devops-labs/nginx-proxy/conf.d avec la bonne extension .conf
cd lecloudfacile-devops-labs/nginx-proxy/
cp conf.d/jenkins/harbor.scratch.conf.template conf.d/harbor.conf
N.B : Vous pourrez faire un git pull pour récupèrer les dernières mises à jour du repo github si tel n'est pas déjà le cas
Il faudra ensuite recharger la configuration du proxy pour prendre en compte les modifications apportées.
docker exec -ti proxy nginx -s reload
Enfin, modifier le fichier /etc/hosts pour rajouter notre url d'accès à harbor : registry.lcf.io
127.0.0.1 registry.lcf.io quality.lcf.io jenkins.lcf.io localhost app.moodboard.xyz adminer.moodboard.xyz api.moodboard.xyz
Etape 4 : Accès au service Harbor#
Ouvrir un navigateur et taper l'adresse suivante : http://registry.lcf.io
Les identifiants d'accès par défaut sont :
- login : admin
- Mot de passe : Harbor12345

Etape 5 : Configuration du projet#
Dans cette étape on va créer un projet pour héberger de façon privé nos images springboot précèdemment pushé sur DockerHub lors du lab Pipeline Jenkins avec Docker du Stage 6
- Cliquer sur
New projectpour créer de nouveaux projets

- Créer un projet avec comme nom
moodboard

- Activer le scan automatique avec trivy sur l'ensemble du projet
Se rendre sur le projet moodboard

Puis se rendre dans configuration, cocher Automatically scan images on push et cliquer sur Save tout en bas.
Ceci permettra d'avoir un scan sécurité automatisé à chaque fois qu'on va pousser des images sur ce projet.

Etape 5 : Push d'images depuis Jenkins#
Dans cette étape, on va créer un pipeline jenkins permettant de pusher des images vers Harbor
- Créer un credential avec les identifiants de connexion à harbor
Se rendre sur la page d'administration de jenkins --> Credentials --> Global --> Add Credentials --> créer un credential de type Username with password avec les informations ci-dessous :
-> Renseigner le nom d'utilisateur admin dans le champs Nom d'utilisateur
--> Renseigner Harbor12345dans le champs Mot de passe
--> Dans le champ ID, renseigner token-harbor
--> Dans le champ Description, renseigner Identifiant de connexion à Harbor
--> Enfin cliquer sur Create

- Création d'un pipeline Jenkins
Créer un nouveau job jenkins de type pipeline avec comme nom build-springboot-harbor

Ci-dessous le contenu du pipeline :
pipeline {
agent any
stages {
stage('clone Project') {
steps {
// Clone le repo Github pour récumèrer le code source
git branch: 'main', url: 'https://github.com/wingufactory/lecloudfacile-devops-labs.git'
}
}
stage('Build Docker Image') {
steps {
// Construction de l'image Docker pour le backend
sh 'docker build -t moodboard-backend-app:1.0.0 springboot-react-app/moodboard-backend'
// Construction de l'image Docker pour le frontend
sh 'docker build -t moodboard-frontend-app:1.0.0 springboot-react-app/moodboard-frontend'
}
}
stage('Tag Docker Image') {
steps {
// Tag des images Docker avec les noms de dépôt sur Docker Hub
sh 'docker image tag moodboard-frontend-app:1.0.0 registry.lcf.io/moodboard/moodboard-frontend-app:1.0.0'
sh 'docker image tag moodboard-backend-app:1.0.0 registry.lcf.io/moodboard/moodboard-backend-app:1.0.0'
}
}
stage('Push to DockerHub') {
steps {
echo "Pushing image to Harbor..."
// Utilisation des identifiants Jenkins pour se connecter à Docker Hub
withCredentials([usernamePassword(credentialsId: "token-harbor", usernameVariable: "DOCKER_USER", passwordVariable: "DOCKER_PASSWORD")]) {
// Connexion et push des images Docker vers Docker Hub
sh """
echo "$DOCKER_PASSWORD" | docker login registry.lcf.io -u "$DOCKER_USER" --password-stdin
docker push registry.lcf.io/moodboard/moodboard-frontend-app:1.0.0
docker push registry.lcf.io/moodboard/moodboard-backend-app:1.0.0
"""
}
}
}
}
}
- Executer le pipeline
Etape 6 : Vérification#
Se rendre sur harbor, puis dans le projet moodboard, on pourra constater les deux images poussés : backend et frontend

On peut constater également que les images ont été automatiquement scannées avec trivy
