Déployer des applications de manière efficace, rapide et reproductible dans des environnements hétérogènes peut sembler complexe. Dans cet article, nous allons déployer dans des conteneurs Docker une API .NET introduite dans un précédent article, couplée à une application Angular.
L'API .NET, via le connecteur NTi Data Provider, expose les données depuis DB2 for i. L'application Angular les consomme pour fournir l'interface utilisateur.
Prérequis et environnement de développement
- IDE : l'API .NET est développée avec Visual Studio, qui intègre nativement la gestion des conteneurs Docker. L'application Angular est développée sous Visual Studio Code.
- Système cible : les applications sont destinées à être déployées sur des Raspberry Pi 4 et 5, des nano-ordinateurs à processeur ARM connectés à un IBM i.
- Docker : Docker desktop installé sur la machine de développement, va me permettre de conteneuriser les applications, facilitant leur déploiement sur différentes architectures matérielles, notamment celles des Raspberry Pi.
Partie 1 - Déploiement de l’API .NET
Étape 1 - Création du Dockerfile avec Visual Studio
La première étape consiste à créer un Dockerfile pour l’API .NET.
Visual Studio facilite ce processus grâce à son intégration native Docker:
clic droit sur le projet > Ajouter > Prise en charge avec Docker
Visual Studio génère un Dockerfile multi-étapes adapté à l'application .NET :
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 8080
EXPOSE 8081
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["AccessDataAPI.csproj", "."]
RUN dotnet restore "./././AccessDataAPI.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "./AccessDataAPI.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./AccessDataAPI.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "AccessDataAPI.dll"]
- Base: image ASP.NET officielle avec les ports 8080 (HTTP) et 8081 (HTTPS) exposés.
- Build: compilation de l'application avec le SDK .NET.
- Publish: publication de l'application compilée, prête pour le déploiement.
- Final: image d'exécution finale avec uniquement les fichiers publiés.
Étape 2 - Ajout des CORS ( Cross Origin Resource Sharing )
Afin de permettre à l'API d’accepter les requêtes provenant de l'application Angular hébergée sur un serveur différent, les CORS sont configurés dans le program.cs.
using AccessDataAPI.Services;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
var builder = WebApplication.CreateBuilder(args);
// Add the CORS configuration to authorise requests from the Angular HotelAppManager application.
builder.Services.AddCors(options =>
{
options.AddPolicy("MyCorsPolicy", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
Étape 3 - Configuration du LaunchSettings.json
Ce fichier définit les profils de lancement de l’application: développement local en HTTP ou HTTPS, et Docker.
{
"profiles": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:7245"
},
"https": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:7246;http://localhost:7245"
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"environmentVariables": {
"ASPNETCORE_HTTPS_PORTS": "8081",
"ASPNETCORE_HTTP_PORTS": "8080"
},
"publishAllPorts": true,
"useSSL": true
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:24909",
"sslPort": 44315
}
}
}
- Profils HTTP & HTTPS: lancent l'application localement avec les ports 7245 et 7246.
- Le Profil Docker: indique à Visual Studio comment lancer l'application dans Docker, avec le mappage des ports et les variables d'environnement correspondant aux ports exposés dans le Dockerfile.
Étape 4 - Construction de l'image Docker
Une fois le Dockerfile, le launchSettings et les CORS configurés, on utilise Docker Buildx pour créer une image multi-architecture, essentielle pour le déploiement sur Raspberry Pi :
docker buildx build --platform linux/arm64/v8,linux/amd64 -t quentindaumerial/accessdataapi:latest --push -f Dockerfile .
L'image est directement poussée sur Docker Hub.

Pour valider le fonctionnement avant déploiement, on exécute l'image localement avec docker run :
docker run --rm -it -p 7245:8080 -p 7246:8081 \
-e ASPNETCORE_HTTPS_PORTS=8081 \
-e ASPNETCORE_HTTP_PORTS=8080 \
-e ASPNETCORE_Kestrel__Certificates__Default__Password="password" \
-e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx \
-v %USERPROFILE%\.aspnet\https:/https/ accessdataapi
En se rendant sur https://localhost:7246/HotelCustomer/clients les données exposées depuis DB2 for i sont bien accessibles.

Étape 5 - Envoyer l’image sur le Raspberry Pi 5
Après avoir poussé l'image sur Docker Hub, on se connecte au Raspberry Pi en SSH et on télécharge l'image :

docker image pull quentindaumerial/accessdataapi:latestÉtape 6 - Lancement du conteneur sur le Raspberry Pi 5
On lance le conteneur en mappant le port 8080 du conteneur au port 5040 du Raspberry Pi :
docker run -it -p 5040:8080 quentindaumerial/accessdataapi:latest
L'API est accessible à l'adresse http://192.168.46.34:5040/hotelcustomer/clients.

Partie 2 - Déploiement de l’application Angular
Étape 1 - Préparation du Dockerfile
Le Dockerfile Angular se compose de deux étapes : construction et exécution.
### STAGE 1:BUILD ###
FROM node:latest AS build
WORKDIR /app
COPY package.json ./
RUN npm install
RUN npm build --configuration=production
### STAGE 2:RUN ###
FROM nginx:latest
COPY dist/app-data-manager /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
- Build : utilise l'image
nodepour installer les dépendances et compiler l'application en mode production. - Run : utilise
nginxpour servir les fichiers compilés depuis/usr/share/nginx/html.
Étape 2 - Création du fichier nginx.conf
Ce fichier configure NGINX pour servir l'application Angular et gérer le routage côté client :
events{}
http {
include /etc/nginx/mime.types;
server {
root /usr/share/nginx/html/browser;
index /index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
}
La directive try_files indique à NGINX de renvoyer index.html pour toutes les routes gérées côté client, ce qui est indispensable pour le routage Angular.
Étape 3 - Configuration des environnements
Angular gère nativement les configurations de développement et de production, ce qui permet de pointer vers la bonne URL d'API selon le contexte.
- Développement
src/environments/environment.ts
export const environment = {
production: false,
apiBaseUrl: 'https://localhost:7246/'
};
- Production
src/environments/environment.prod.ts
export const environment = {
production: true,
apiBaseUrl: 'http://192.168.46.34:5040/'
};
La commande ng serve utilise automatiquement la configuration de développement sur localhost:4200.


Étape 4 - Construction de l’image Docker
Comme pour l'API, on utilise Docker Buildx pour une image multi-architecture :
docker buildx build --platform linux/amd64,linux/arm64,linux/arm64/v8 -t quentindaumerial/appdatamanager:latest --push --no-cache .


Étape 5 - Déploiement sur le Raspberry Pi 4
Connexion en SSH au Raspberry Pi 4 :

Téléchargement de l'image depuis Docker Hub :
docker image pull quentindaumerial/appdatamanager:latest

Étape 6 - Lancement du conteneur sur le Raspberry Pi 4
On mappe le port 80 du conteneur au port 5000 du Raspberry Pi :
docker run -it --platform linux/arm64/v8 -p 5000:80 quentindaumerial/appdatamanager:latest

L'application est accessible à l'adresse http://192.168.46.31:5000 et les données remontent bien depuis l'API, qui consomme DB2 for i via NTi :


Conclusion
Grâce à des Dockerfiles adaptés, à la configuration de NGINX pour Angular, et à l'ajustement des CORS et des profils de lancement de l'API .NET, les deux applications fonctionnent de manière isolée et communiquent sans problème dans un environnement conteneurisé.
Le connecteur NTi Data Provider joue ici un rôle central : il permet à une API .NET Core de dialoguer nativement avec DB2 for i, même depuis un conteneur Docker tournant sur un Raspberry Pi. Finalement, peu importe la machine sur laquelle tourne l'application, ce qui compte, c'est que les données arrivent au bon endroit, de manière fiable.
Quentin Destrade