Compilation de vos projets
Avant de créer vos dockers, on va devoir compiler nos projets Angular et Springboot afin d’avoir le code compilé (si je puis dire).
Pour le côté Angular, on va générer le HTML, CSS et javascript avec les commandes suivantes :
$ cd FrontDemo/
$ ng build
Et votre code va se retrouver dans le dossier dist/front-demo
.
Pour le côté Springboot, on va générer le jar avec les commandes suivantes :
$ cd RaphlysDemo
$ ./gradlew build
Et votre fichier jar se trouvera, dans le dossier dist/libs
. Vous aurez remarqué que vous avez des soucis de compilation, ce sont les tests unitaires qui ne passent pas, vous pouvez ajouter -x test
, ce qui supprimera l’exécution des tests unitaires.
Docker-compose.yml
Docker-compose va nous permettre de paramétrer des machines dockers. On va donc créer un fichier docker-compose.yml, avec les différentes machines. Aujourd’hui il n’est plus nécessaire d’indiquer la version de docker-compose.
services:
nginx:
image: nginx:alpine
container_name: nginx_alpine
ports:
- "8080:80"
- "8443:443"
volumes:
- ./workspace/FrontDemo/dist/front-demo/browser/:/usr/share/nginx/html
- ./nginx/conf:/etc/nginx/conf.d
springboot-app:
image: openjdk:21-jdk-slim
container_name: springboot_container
volumes:
- ./workspace/RaphlysDemo/build/libs/:/app/
command: ["java", "-jar", "/app/RaphlysDemo-0.0.1-SNAPSHOT.jar"]
Donc comme on peut le voir, il y a deux services, un qui s’appuie sur Nginx et l’autre sur Openjdk. J’ai pris la décision de faire un Nginx et de compiler Angular, afin d’avoir du HTML, CSS et javascript, mais on aurait pu décider de lancer Angular comme un service.
Angular
On va décortiquer la partie concernant le service Nginx. Nginx est un serveur HTTP comme l’est apache. Prenons ligne par ligne :
nginx:
Ça c’est le nom de notre service, il sera utilisé par Docker compose, vous pouvez lui donner le nom que vous souhaitez, afin que vous puissiez identifier rapidement votre service dans le fichier docker-compose.yml.
image: nginx:alpine
Ici vous pouvez indiquer l’image que vous voulez utiliser. Ici l’image demander se base sur une distribution linux alpine ( comme l’A110, la distribution est légère et n’a pas besoin d’un moteur puissant pour aller vite) et intègre le service nginx (le serveur Http).
container_name: nginx_alpine
Là vous indiquer le nom de votre container, ce nom sera utilisé par docker. Par exemple si vous voulez redémarrer ce container, il faudra faire docker restart nginx_alpine
ports:
- "8080:80"
- "8443:443"
Ces 3 lignes permettent de dire que le port 80 de la machine docker est accessible sur le port 8080 de la machine hôte (votre PC) et que le port 443 de la machine docker est accessible sur le port 8443 de la machine hôte. Il ne faut pas que ces ports soient utilisés par un autre programme de la machine hôte. Les autres ports s’ils sont utilisés par la machine docker, sont accessibles dans un réseau interne de docker. Et d’ailleurs on va l’utiliser, je vous montre ça plus tard dans cet article…
volumes:
- ./workspace/FrontDemo/dist/front-demo/browser/:/usr/share/nginx/html
- ./nginx/conf:/etc/nginx/conf.d
Le dossier ./workspace/FrontDemo/dist/front-demo/browser/
de la machine hôte (vous noterez que ça fonctionne en relatif et en absolue) est monté sur le dossier /usr/share/nginx/html
de la machine docker. Ici, j’ai mis le dossier de distribution d’Angular dans le dossier exposé par Nginx. Donc dès que je compile mon code Angular, il est immédiatement disponible. Ceci n’est pas à faire en production.
Le dossier ./nginx/conf
de l’hôte est monté sur le dossier /etc/nginx/conf.d
de la machine docker. On va donc pouvoir modifier en direct, la configuration de Nginx sur la machine hôte, pour la prise en compte des modifications, soit on redémarre le docker, soit on se connecte au docker et on redémarre le service.
Springboot
springboot-app:
Comme nginx vue plus tôt.
image: openjdk:21-jdk-slim
Ici on utilise un docker avec openjdk 21. Il est basé sur debian, Debian qui devrait être un peu plus lourd qu’alpine. Il faut vérifier vos besoins si vous voulez passer à une autre distribution.
container_name: springboot_container
Le nom du container qui vous permettra par exemple de faire un docker logs springboot_container
, afin de voir les logs.
volumes:
- ./workspace/RaphlysDemo/build/libs/:/app/
Comme dans l’autre cas, ./workspace/RaphlysDemo/build/libs/
de la machine hôte est monté sur /app/
du Docker. Ici dans libs il y a les jar qui ont été générés.
command: ["java", "-jar", "/app/RaphlysDemo-0.0.1-SNAPSHOT.jar"]
Ceci permet d’indiquer quelle commande exécuter au démarrage de la machine. On a donc java -jar /app/RaphlysDemo-0.0.1-SNAPSHOT.jar
qui sera lancé au démarrage. C’est notre Springboot.
Nginx (./nginx/conf/something.conf)
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html;
}
location /api {
proxy_pass http://springboot-app:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
error_page 404 /404.html;
}
Pour les plus attentifs, vous aurez remarqué que le port 443, n’est pas configuré. On le ferra plus tard.
listen 80;
server_name localhost;
On écoute le port 80, qui est le port par défaut pour un serveur http, (on le redirigera sur le port 8080 grâce à docker, car mon port 80 est déjà utilisé). Le nom du serveur c’est localhost
, donc pour l’appeler dans le navigateur il suffit d’écrire http://localhost:8080
=> Parce qu’on a demandé à docker de rediriger le port.
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html;
}
Ça c’est pour la partie Angular, le root (la racine) c’est le dossier que l’on va exposer au monde, ici /usr/share/nginx/html
sur la machine docker, mais si vous avez suivi ça mène au dossier ./workspace/FrontDemo/dist/front-demo/browser/
de la machine hôte. On lui indique quel est l’index possible, le fichier à délivrer quand on tombe sur un dossier, ici on délivrera index.html
ou index.htm
.
indique que l’on va d’abord essayer d’envoyer la route à index.html avant de regarder si un dossier existe. Ça nous permet de gérer les routes pour angular. Sans ça si vous tappez http://localhost:8080/login vous tomberiez sur une 404 parce que le fichier
try_files./workspace/FrontDemo/dist/front-demo/browser/login/index.html
n’existe pas.
location /api {
proxy_pass http://springboot-app:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
Ça c’est pour springboot. Comment avec Nginx, angular et springboot sont accessible sur le même port, j’ai dû ajouter api au début de toutes les routes de springboot. Nous verrons plus loin, comment on a fait ça. Mais donc toutes les locations qui commencent par /api vont être redirigées.
proxy_pass vous permet d’indiquer vers où rediriger les appels, ici http://springboot-app:8080. On utilise le réseau interne des machines docker. Souvenez-vous dans le fichier docker-compose.yml, on a défini sur les premières lignes le nom des machines dockers (ce n’est pas le même que le nom des containers), c’est celui-là que l’on utilise ici.
On a ensuite la version de HTTP, et diverses configurations HTTP indispensables.
Angular
J’ai ajouté un menu pour naviguer plus facilement, mais ce n’est pas indispensable.
Ce qui compte, c’est que j’ai modifié les appels pour qu’ils ne tapent plus sûr localhost:8080/
mais sûr localhost:8080/api
. Ça, c’est encore parce que l’on passe par nginx. On est obligé d’avoir api devant les requêtes passées à l’api, pour qu’elles soient bien orientées.
Springboot
application.properties
spring.mvc.servlet.path=/api
logging.level.org.springframework.security=DEBUG
Il y a une ligne pour indiquer que les requêtes commencent par « api » et une autre pour mettre les logs sur springsecurity en DEBUG. Je vous laisse réfléchir à quelle ligne sert à quoi. Vous avez 2 heures.
SecurityConfig.java
form.loginProcessingUrl("/api/login")
...
logout.logoutUrl("/api/logout")
J’ai supprimé le code spécifique pour le CORS, car avec nginx nous n’en avons plus besoin. J’ai supprimé une partie du code pour CSRF, car ça fonctionne sans.
J’ai ajouté api pour les urls concernant le login et le logout, car sans ça ils ne sont pas accessibles sinon.
À noter : que l’on aurait pu ne pas configurer springboot pour avoir api au début et simplement configurer nginx afin qu’il ne transmette pas « api » à springboot mais uniquement la fin de l’url.
Conclusion
Nous avons maintenant un angular hébergé sur un docker avec springboot aussi hébergé sur un docker. Vous aurez besoin de docker compose. Mais grâce à ça, vous pourrez déployer votre application sur un serveur qui a docker-compose d’installé. Grâce à la commande docker compose up -d
que vous devrez lancer dans le dossier où se trouve votre fichier docker-compose.yml.
On peut donc faire, un git clone de notre projet, un docker compose up et on a un serveur opérationnel….
Protéger incroyablement votre application Angular/Springboot
Laisser un commentaire