DB2 for i & .NET: app Angular su Raspberry Pi con Docker

In questo articolo scoprirete il processo di distribuzione delle applicazioni in ambienti eterogenei utilizzando Docker. Esplorate un approccio dettagliato alla costruzione di una rete di applicazioni interoperabili e distribuite.

immagine illustrativa dell'articolo “DB2 for i & .NET: app Angular su Raspberry Pi con Docker”

Distribuire applicazioni in modo efficiente, rapido e riproducibile in ambienti eterogenei può sembrare complesso. In questo articolo vi invito a scoprire il processo dettagliato di distribuzione di un back-end .NET APi in container Docker, abbinato a un'applicazione front-end Angular che ho sviluppato e introdotto in un precedente articolo.

Insieme vedremo come utilizzare Docker per distribuire queste applicazioni in modo efficiente su computer Raspberry Pi. Ognuno di questi piccoli computer, che nella nostra architettura funziona come un server indipendente, sarà collegato a un server IBM i.

La nostra API .NET, utilizzando il provider di dati NTi, funge da livello di servizio, esponendo dati e funzionalità da un database DB2 for i ospitato su IBM i, nonché da un altro database Postgre SQL in esecuzione su un Raspberry 4. L'applicazione Angular consuma e utilizza questi servizi per fornire l'interfaccia utente.

Requisiti e ambiente di sviluppo

💻 IDE:

L'API .NET è stata sviluppata utilizzando Visual Studio, sfruttando le sue funzionalità integrate per la gestione dei container Docker.
L'applicazione ANGULAR è stata sviluppata utilizzando Visual Studio Code, apprezzato per la sua leggerezza e flessibilità, soprattutto per i progetti JavaScript / TypeScript.

🍓Sistema di destinazione:

Le applicazioni sono progettate per essere distribuite su Raspberry Pi 4 e 5. Questi nano computer con processore ARM sono collegati a un IBM i.

🐳 Docker:

Docker desktop, installato sulla mia macchina di sviluppo, mi consentirà di containerizzare le applicazioni, facilitando la loro distribuzione su architetture hardware diverse, in particolare quelle del Raspberry Pi.

PARTE 1 - Distribuzione dell'API .NET.

Passo 1 - Creare il file Docker con VISUAL STUDIO.

Il primo passo consiste nel creare un Dockerfile per l'API .NET. Visual Studio semplifica questo processo grazie all'integrazione nativa con Docker:

Fare clic con il tasto destro del mouse sul progetto > Aggiungi > Supportato da Docker.

Visual Studio genera un file Docker personalizzato per l'applicazione, preconfigurato per l'ambiente .NET.

Questo file definisce le istruzioni per la creazione dell'immagine Docker dell'applicazione, comprese le fasi di base, compilazione, pubblicazione e la fase finale per l'esecuzione dell'applicazione.

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"]
  • Fase di base:** Utilizzare l'immagine ufficiale ASP.NET Docker per creare un ambiente di runtime per l'applicazione. Le porte 8080 e 8081 sono esposte per il traffico HTTP e HTTPS.
  • Fase di compilazione:** Utilizza l'immagine SDK per compilare l'applicazione. La gestione delle dipendenze e la compilazione vengono eseguite in questa fase.
  • Fase di pubblicazione:** Pubblica l'applicazione compilata, pronta per la distribuzione.
  • Fase finale: ¨Prepara l'immagine finale copiando l'applicazione pubblicata nell'ambiente di runtime.

Passo 2 - Aggiunta di CORS (Cross Origin Resource Sharing).

using AccessDataAPI.Services;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;

var builder = WebApplication.CreateBuilder(args);

// Aggiungere la configurazione CORS per autorizzare le richieste dell'applicazione Angular HotelAppManager. 

builder.Services.AddCors(options =>
{
    options.AddPolicy("MyCorsPolicy", policy =>
    {
        policy.AllowAnyOrigin()
              .AllowAnyHeader()
              .AllowAnyMethod();
    });
});

Per consentire alla nostra API .NET di accettare richieste da altre origini, come la nostra applicazione Angular che sarà ospitata su un server diverso, configuriamo CORS (Cross Origin Resource Sharing) nel file "programma.cs".

I CORS sono essenziali e consentono alla nostra applicazione front-end di comunicare in modo semplice con il nostro back-end.

Passo 3 - Configurazione di LaunchSettings.json

LaunchSettings.json in Visual Studio

Questo file definisce diversi profili per l'avvio dell'applicazione, compreso lo sviluppo locale tramite HTTP o HTTPS, nonché Docker.

  • I profili HTTP e HTTPS:** consentono di avviare l'applicazione in locale, con o senza SSL, specificando l'URL di avvio, le porte utilizzate e le variabili d'ambiente.
  • Il profilo Docker:** indica a Visual Studio come lanciare l'applicazione in Docker, compresa la mappatura delle porte e l'uso di SSL. Le variabili d'ambiente sono impostate qui per corrispondere alle porte esposte nel Dockerfile.

Passo 4 - Distribuzione su Docker

Una volta configurati il file Docker, le impostazioni di lancio e i CORS, è ora il momento di creare l'immagine DOCKER di .NET APi usando la riga di comando.

Nella cartella corrente della nostra applicazione, useremo Docker Buildx per creare un'immagine multi-architettura di .NET APi, essenziale per distribuire l'applicazione su Raspberry Pi.

docker buildx build --platform linux/arm64/v8,linux/amd64 -t quentindaumerial/accessdataapi:latest --push -f Dockerfile .

L'immagine viene inviata direttamente al mio Docker Hub, confermando che la compilazione è stata completata.

Docker Hub dopo la build dell’immagine API .NET

Per convalidare il funzionamento di .NET APi in un ambiente simile a quello di distribuzione, eseguo l'immagine localmente con "docker run".

Mappando le porte necessarie e configurando le variabili d'ambiente per SSL, simulo l'ambiente di produzione sulla mia macchina di sviluppo.

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

Collegandomi a https://localhost:7246/HotelCustomer/clients dal mio browser web, posso accedere ai dati esposti dalla mia API direttamente da DB2 for i. Questa convalida garantisce che la mia API .NET sia pronta per essere distribuita su Raspberry 5.

API .NET in esecuzione locale in Docker

Passo 5 - Inviare l'immagine al RASPBERRY Pi 5.

Dopo aver spinto l'immagine nel registro del mio hub Docker, è ora il momento di connettersi al Raspberry Pi in SSH, scaricare l'immagine direttamente dal mio hub e lanciarla in un contenitore.

  1. Connettersi al Raspberry 5 usando SSH:

Connessione SSH al Raspberry Pi 5

  1. Scaricare l'immagine dal mio Hub Docker:
docker image pull quentindaumerial/accessdataapi:latest

Passo 6 - Avviare il contenitore Docker sul Raspberry 5.

Lancio il mio contenitore mappando la porta 8080 sulla porta 5040 del mio Raspberry Pi 5:

docker run -it -p 5040:8080 quentindaumerial/accessdataapi:latest

Ed ecco fatto! La mia API .NET è ora in esecuzione in un contenitore Docker sul mio Raspberry Pi 5, che a sua volta è collegato al mio IBM i. Posso verificarlo direttamente andando su http://192.168.46.34:5040/hotelcustomer/clients.

API .NET distribuita su Raspberry Pi 5

PARTE 2 - Distribuzione dell'applicazione ANGULAR.

Passo 1 - Preparazione del file Docker.

Come per l'API .NET, per rendere docker la nostra applicazione ANGULAR, dovremo andare nella cartella dell'applicazione e creare un file chiamato Dockerfile senza estensione.

È composto da due fasi: build e run.

### 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

La fase di compilazione utilizzerà l'ultima versione dell'immagine "node" per installare le dipendenze e costruire l'applicazione Angular specificando una configurazione di produzione (dettagliata nella fase 4 ).

La fase di runtime utilizzerà l'ultima versione dell'immagine "nginx" per servire la nostra applicazione. I file di distribuzione generati vengono copiati in /usr/share/nginx/html, la cartella predefinita usata da NGINX per servire i contenitori web.

Passo 2 - Creare il file nginx.conf.

Questo file configura NGINX per servire correttamente la nostra applicazione ANGULAR, supportando il routing lato 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;
        }
    }
}
  • Il blocco "server" definisce dove trovare i file dell'applicazione e come rispondere alle richieste HTTP.

  • La direttiva "try_files" indica a NGINX di servire index.html per tutti i percorsi lato client.

Passo 3 - Configurazione degli ambienti di sviluppo e di produzione.

Come si può vedere dal file Docker, abbiamo specificato una build con "configurazione di produzione".

Questo perché Angular è in grado di differenziare e gestire in modo nativo le configurazioni specifiche per gli ambienti di sviluppo e di produzione, per garantire che l'applicazione si comporti come previsto in ogni contesto (in particolare la connessione alle mie API).

  • Per lo sviluppo ("src/environments/environment.ts"):**

Contiene la configurazione usata durante lo sviluppo, compreso l'URL di base dell'API che punta al server di sviluppo, configurato nel file launchsettings della nostra API .NET.

export const environment = {
    production: false,
    apiBaseUrl: 'https://localhost:7246/'
};

Per la produzione ("src/environments/environment.prod.ts"):**

Contiene la configurazione utilizzata per la versione di produzione dell'applicazione con un URL che punta al server di produzione (in questo caso il nostro secondo Raspberry Pi, accessibile all'indirizzo 192.168.46.34, sulla porta 5040).

export const environment = {
  production: true,
  apiBaseUrl: 'http://192.168.46.34:5040/'
};

Questi file consentono di passare in modo semplificato dalla configurazione di sviluppo a quella di produzione, semplicemente cambiando il flag "production" durante la creazione dell'applicazione.

Il comando ng serve di Angular mi consente di accedere al mio server di sviluppo su localhost, porta 4200.

Applicazione Angular in sviluppo locale con ng serve

Applicazione Angular che mostra i dati DB2 for i

Passo 4 - Creare l'immagine Docker.

Come per le API .NET, è importante creare un'immagine multipiattaforma per garantire che l'applicazione Angular sia compatibile con diverse architetture.

Quindi, ancora una volta, usiamo Docker Buildx per creare un'immagine che funzioni sia su architetture amd64 (tipiche di PC e server) sia su arm64/v8 (dispositivi arm come Raspberry).

Il comando seguente avvia la creazione dell'immagine e la invia al mio Dockerhub:

docker buildx build --platform linux/amd64,linux/arm64,linux/arm64/v8 -t quentindaumerial/appdatamanager:latest --push --no-cache .

Build multi-architettura dell’applicazione Angular con Docker Buildx

La mia immagine è aggiornata su Dockerhub:

Immagine Angular aggiornata su Docker Hub

Passo 5 - Invio dell'immagine al Raspberry 4.

Dopo aver costruito e spinto l'immagine della mia applicazione Angular su Dockerhub, mi collego al Raspberry Pi 4 tramite SSH:

Connessione SSH al Raspberry Pi 4

Recupero l'ultima versione della mia immagine dal mio hub, per renderla disponibile sul Raspberry Pi:

docker image pull quentindaumerial/appdatamanager:latest

Download dell’immagine Angular su Raspberry Pi 4

Passo 6 - Avviare il contenitore Docker sul Raspberry 4.

Ora che l'immagine è stata scaricata, lancio un container Docker per distribuire l'applicazione Angular, mappando la porta 80 del container sulla porta 5000 del Raspberry pi 4:

docker run -it --platform linux/arm64/v8 -p 5000:80 quentindaumerial/appdatamanager:latest

Esecuzione dell’applicazione Angular su Raspberry Pi 4 con Docker

L'applicazione è ora accessibile tramite un browser web all'indirizzo "**http://192.168.46.31:5000**":

Applicazione Angular accessibile dal browser su Raspberry Pi 4

In particolare, possiamo vedere che i dati provengono effettivamente dal nostro APi, che consuma i dati esposti da DB2 for i e recuperati tramite NTi da .NET:

Applicazione Angular che utilizza l’API .NET e mostra i dati DB2 for i

CONCLUSIONE

Impostando Dockerfiles specifici, configurando nginx.conf in modo appropriato per Angular e regolando i CORS e i parametri di lancio del nostro APi .NET, è possibile creare semplicemente un ecosistema in cui le due applicazioni funzionano perfettamente in modo isolato. Il risultato? Un recupero dei dati semplice e senza problemi, che illustra l'interconnessione in un ambiente containerizzato.

L'uso del connettore NTi svolge un ruolo essenziale nella nostra API .NET, facilitando la connessione a DB2 for i. Dimostra che è possibile eseguire applicazioni .NET CORE in modo nativo, interagendo con i dati su IBM i, pur rimanendo in un ambiente Dockerizzato. La facilità di implementazione di un'API .NET e di un'applicazione client, unita alla capacità del nostro fornitore di dati NTi di operare in modo nativo in .NET, sottolinea non solo la semplicità di gestione di tali applicazioni, ma anche il loro potenziale di scalabilità. Questo progetto è solo un esempio dei molti modi in cui oggi possiamo ripensare l'uso della tecnologia per creare, innovare e ottimizzare i processi di sviluppo e distribuzione.

Spero che questa guida vi abbia fornito le conoscenze e l'ispirazione per esplorare nuovi metodi e strumenti per i vostri progetti. Docker è qui per rendere la distribuzione delle applicazioni più semplice, veloce e affidabile, consentendovi di concentrarvi su ciò che conta davvero: soddisfare efficacemente le esigenze specifiche di ogni progetto dei clienti.


Quentin Destrade