Configurare Jenkins su Windows 11
Possiamo installare facilmente Jenkins su Linux e macOS. Tuttavia, su Windows l’installazione richiede diversi passaggi. Tra questi: installare il Java Development Kit, impostare la politica di sicurezza locale, installare Jenkins con un utente di dominio e avviare il server Jenkins.
Installare OpenJDK
Iniziamo installando Java. Dobbiamo andare sul sito Adoptium e scaricare l’ultima release LTS per Windows 11.
Perché dobbiamo installare OpenJDK? Jenkins è un’applicazione basata su Java che richiede una Java Runtime Environment (JRE) o un Java Development Kit (JDK) per essere eseguita.

Fonte immagine: Adoptium
Installa OpenJDK con i valori predefiniti, tranne che devi spuntare la voce “Set or override JAVA_HOME variable”.

Al termine dell’installazione, possiamo verificare che sia tutto corretto digitando java -version nel terminale:

Configurare un account utente per “Log on as service”
Per installare Jenkins, devi modificare la “Local Security Policy” per abilitare l’accesso dell’utente per l’installer. Per farlo, premi i tasti Win + R, digita “secpol.msc” e premi Invio. Poi vai su “Local Policies” > “User Rights Assignments” > “Log on as a service”.

Verrai reindirizzato a una nuova finestra, dove inserirai il tuo nome utente di Windows e cliccherai sul pulsante “Check Names”. Poi premi il pulsante “OK” ed esci dalla finestra “Local Security Policy”.

Installare Jenkins
Vai sul sito jenkins.io e scarica il pacchetto Windows Installer per Jenkins.

Fonte immagine: jenkins.io
Quando arrivi alla finestra che dice "Run service as a local or domain user", inserisci nome utente e password di Windows, poi premi il pulsante “Test Credentials”. Se l’esito è positivo, clicca su “Next”.

Lascia tutto il resto come predefinito e completa l’installazione. Potrebbero volerci alcuni minuti per il setup.

Avviare il server Jenkins
Avviare il server Jenkins è semplice. Basta premere il tasto Windows e cercare "Services". Nella finestra Servizi, cerca Jenkins e clicca il pulsante play in alto.

Per impostazione predefinita, Jenkins è in esecuzione su https://localhost:8080/. Incolla semplicemente quell’URL nel browser per accedere alla dashboard. Per entrare nella dashboard di Jenkins, devi inserire la password dell’amministratore.

Per ottenere la password amministratore predefinita, vai nella directory Jenkins e individua e apri il file Jenkins.err.log.

Scorri il file degli errori di Jenkins per trovare la password generata. Copiala e incollala nel campo della password amministratore.

Dopodiché, il server impiegherà alcuni minuti per installare gli strumenti e le estensioni necessarie.

Una volta completata la configurazione del server, ci verrà chiesto di creare un nuovo utente. Inserisci tutte le informazioni necessarie e clicca su "Save and Continue".

Verremo indirizzati alla dashboard, dove potremo creare, visualizzare ed eseguire varie pipeline Jenkins.

Creare un agent in Jenkins
Gli agent, noti anche come nodi, sono macchine configurate per eseguire i job inviati dal server master di Jenkins. Questi agent forniscono l’ambiente e la capacità di calcolo per eseguire le pipeline. Un agent Windows 11 è disponibile per impostazione predefinita, ma possiamo sempre creare un nostro agent con opzioni personalizzate.
Configurare gli agent
Dalla dashboard principale, clicca su “Manage Jenkins” e poi sul pulsante “Set up agent” come mostrato sotto. In alternativa, puoi cliccare sul pulsante “Nodes” per creare e gestire gli agent.

Inserisci il nome dell’agent e seleziona il tipo “Permanent Agent”.

Assicurati di indicare una directory per l’agent dove verranno salvati tutti i file e i log. Aggiungi un’etichetta e lascia il resto delle impostazioni predefinite. In fase di creazione della pipeline useremo l’etichetta dell’agent per eseguire i task.

Eseguire l’agent in locale
Quando si preme il pulsante “Save”, comparirà un prompt che ci istruisce a copiare e incollare nel terminale il comando appropriato in base al nostro sistema operativo.
curl.exe -sO http://localhost:8080/jnlpJars/agent.jar & java -jar agent.jar -url http://localhost:8080/ -secret 1a30c62de92630dbcc1e2f19aaf482057e6170ced6835355447bc4ba4eefb76a -name "DC Agent 1" -webSocket -workDir "/home/Jenkins"
Dopo aver incollato ed eseguito il comando nel terminale, vedremo un messaggio di successo che indica che il nostro agent, nel mio caso DC Agent 1, è in esecuzione in background.

Per verificare che l’agent sia in esecuzione e pronto per eseguire un job, vai alla dashboard Jenkins, clicca su “Manage Jenkins” e poi sul pulsante “Nodes” per visualizzare lo stato dell’agent.

Creare una semplice pipeline Jenkins
Una pipeline Jenkins è una serie di passaggi automatizzati che aiutano ad addestrare, valutare e distribuire i modelli. Definisce questi processi tramite uno script semplice, rendendo più facile gestire e automatizzare i workflow di progetto.
In questa sezione creeremo un esempio di pipeline Jenkins e useremo il nostro agent appena creato come esecutore della pipeline.
Configurare una pipeline Jenkins
Nella dashboard, clicca sul pulsante “New Item”, digita il nome dell’elemento, seleziona l’opzione “Pipeline” e clicca “OK”.

Successivamente, un prompt ci chiederà di configurare la pipeline. Scorri fino alla sezione “Pipeline”, dove dobbiamo scrivere lo script della pipeline Jenkins.

Nello script della pipeline Jenkins, iniziamo impostando l’ambiente e l’agent. Nel nostro caso, impostiamo l’agent fornendogli l’etichetta dell’agent definita in precedenza.
Dopodiché, scriveremo una sezione stages dove aggiungere tutti i vari passaggi della pipeline (Build, Test, Deploy). Nel nostro caso, stampiamo con il comando echo ed eseguiamo comandi da terminale con il comando bat.
batè usato per Windows 11shper Linux
Tutto qui. È davvero così semplice. Ecco il codice dello script:
pipeline {
agent {
label 'MLAgent' // Ensure this label matches your Windows 11 agent
}
stages {
stage('Build') {
steps {
echo 'Building...'
// Add your Windows build commands here
bat 'echo Running build commands'
}
}
stage('Test') {
steps {
echo 'Testing...'
// Add your Windows test commands here
bat 'echo Running test commands'
}
}
stage('Deploy') {
steps {
echo 'Deploying...'
// Add your Windows deploy commands here
bat 'echo Running deploy commands'
}
}
}
}
Dopo aver aggiunto lo script, clicca sui pulsanti “Apply” e “Save”.
Eseguire la pipeline Jenkins
Clicca sul pulsante “Build Now” per testare ed eseguire la pipeline. Per vederne lo stato, clicca sul pulsante “Status”.

Al termine dell’esecuzione, possiamo visualizzare i log cliccando sulla specifica esecuzione nel menu "Status".
Clicca sul link "Last build (#2)" e poi sul pulsante "Console Output". Verrai portato alla finestra di output della console, dove troverai i log e i risultati della pipeline.

Possiamo anche cliccare sul pulsante “Pipeline Console” per vedere nel dettaglio ogni passaggio della pipeline. Questo include l’output, i tempi di avvio e fine, i comandi della pipeline e i log.

Dopo aver completato l’installazione di Jenkins, creare ed eseguire pipeline è stato facile e veloce. Mi ci è voluta meno di un’ora per capire lo script e come crearne uno mio. Userò Jenkins invece di GitHub Actions perché mi offre più flessibilità.
Creare una pipeline Jenkins per un progetto MLOPs
Dopo l’introduzione a Jenkins, è il momento di fare sul serio e lavorare al progetto MLOps.
Creeremo due pipeline: la prima pipeline sarà CI, caricherà ed elaborerà i dati, addestrerà il modello, valuterà il modello e poi testerà il server del modello. Successivamente, avvierà la pipeline di CD, avviando il server di inferenza del modello.
Per capire il processo nel dettaglio, segui il corso CI/CD for Machine Learning, che insegna a semplificare i processi di sviluppo del machine learning.
File di progetto
Come per qualsiasi progetto, dobbiamo creare i file del progetto, inclusi i file Python per il caricamento dei dati, l’addestramento del modello, la valutazione del modello e il serving del modello. Ci serve anche un file requirements .txt per installare i pacchetti Python necessari.
data_loading.py:
In questo script caricheremo un dataset di scikit-learn chiamato Wine e lo convertiremo in un DataFrame pandas. Poi suddivideremo il dataset in train e test. Infine, salveremo i dati elaborati come file pickle.
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
import pandas as pd
import joblib
def load_data():
# Load the wine dataset
wine = load_wine(as_frame=True)
data = pd.DataFrame(data=wine.data, columns=wine.feature_names)
data["target"] = wine.target
print(data.head())
return data
def split_data(data, target_column="target"):
X = data.drop(columns=[target_column])
y = data[target_column]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
return X_train, X_test, y_train, y_test
def save_preprocessed_data(X_train, X_test, y_train, y_test, file_path):
joblib.dump((X_train, X_test, y_train, y_test), file_path)
if __name__ == "__main__":
data = load_data()
X_train, X_test, y_train, y_test = split_data(data)
save_preprocessed_data(X_train, X_test, y_train, y_test, "preprocessed_data.pkl")
model_training.py:
In questo file, caricheremo i dati elaborati, addestreremo un classificatore random forest e salveremo il modello come file pickle.
from sklearn.ensemble import RandomForestClassifier
import joblib
def load_preprocessed_data(file_path):
return joblib.load(file_path)
def train_model(X_train, y_train):
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
return model
def save_model(model, file_path):
joblib.dump(model, file_path)
if __name__ == "__main__":
X_train, X_test, y_train, y_test = load_preprocessed_data("preprocessed_data.pkl")
model = train_model(X_train, y_train)
save_model(model, "model.pkl")
model_evaluation.py:
Per valutare il modello, caricheremo sia il modello sia il dataset preprocessato, genereremo un classification report e stamperemo l’accuracy.
import joblib
from sklearn.metrics import accuracy_score, classification_report
def load_model(file_path):
return joblib.load(file_path)
def load_preprocessed_data(file_path):
return joblib.load(file_path)
def evaluate_model(model, X_test, y_test):
predictions = model.predict(X_test)
accuracy = accuracy_score(y_test, predictions)
report = classification_report(y_test, predictions)
return accuracy, report
if __name__ == "__main__":
X_train, X_test, y_train, y_test = load_preprocessed_data("preprocessed_data.pkl")
model = load_model("model.pkl")
accuracy, report = evaluate_model(model, X_test, y_test)
print(f"Model Accuracy: {accuracy}")
print(f"Classification Report:\n{report}")
model_serving.py:
Per il serving del modello useremo FastAPI per creare una REST API in cui gli utenti possono inserire feature e ottenere previsioni. Normalmente le etichette sono generiche. Per rendere la cosa più interessante, cambieremo le categorie del vino in Verdante, Rubresco e Floralis.
Quando eseguiamo questo file, avviamo il server FastAPI, a cui possiamo accedere tramite il comando curl o usando la libreria requests in Python.
from typing import List
import joblib
import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# Define the labels corresponding to the target classes
LABELS = [
"Verdante", # A vibrant and fresh wine, inspired by its balanced acidity and crisp flavors.
"Rubresco", # A rich and robust wine, named for its deep, ruby color and bold taste profile.
"Floralis", # A fragrant and elegant wine, known for its floral notes and smooth finish.
]
class Features(BaseModel):
features: List[float]
def load_model(file_path):
return joblib.load(file_path)
model = load_model("model.pkl")
@app.post("/predict")
def predict(features: Features):
# Get the numerical prediction
prediction_index = model.predict([features.features])[0]
# Map the numerical prediction to the label
prediction_label = LABELS[prediction_index]
return {"prediction": prediction_label}
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=9000)
requirements.txt:
Questo file ci aiuterà a scaricare e installare tutti i pacchetti necessari per eseguire i file Python sopra.
scikit-learn
pandas
fastapi
uvicorn
Pipeline principale MLOps (CI)
Ora creeremo le pipeline di integrazione continua in Jenkins. Proprio come abbiamo creato una pipeline semplice, creeremo “MLOps-pipe” e scriveremo lo script che copre tutto, dall’elaborazione dei dati alla valutazione del modello.

Lo script della pipeline MLOps consiste in:
- Inizializzare l’
agentcon l’label“MLAgent”. - Impostare la directory di workspace in cui si trovano tutti i nostri file Python.
- Creare stage per ogni fase della pipeline di machine learning:
- Installare tutti i pacchetti Python necessari (
Initialize). - Elaborare il dataset caricato (
Load and Preprocess Data). - Addestrare il modello sul dataset elaborato (
Train Model). - Valutare il modello e generare il report (
Evaluate Model). - Testare il server del modello con il comando
curl(Test Serve Model). - Dopo aver superato il test del server, verrà attivata un’altra pipeline per distribuire il server. Ne parleremo nella prossima sezione.
- Nel post node, elaboreremo i dati e li salveremo come artifact fornendo l’estensione pickle.
Nota: il comando start /B avvia una nuova finestra di terminale in background ed esegue lo script di model serving. Inoltre, questo script di pipeline Jenkins funziona solo su Windows; per Linux o altri sistemi operativi è necessario modificare i comandi.
pipeline {
agent {
node {
label 'MLAgent'
customWorkspace 'C:\\Repository\\GitHub\\MLOps-Jenkins'
}
}
stages {
stage('Initialize') {
steps {
script {
// Install necessary Python packages
bat "pip install -r requirements.txt"
}
}
}
stage('Load and Preprocess Data') {
steps {
script {
// Run data loading script
bat "python data_loading.py"
}
}
}
stage('Train Model') {
steps {
script {
// Run model training script
bat "python model_training.py"
}
}
}
stage('Evaluate Model') {
steps {
script {
// Run model evaluation script
bat "python model_evaluation.py"
}
}
}
stage('Serve Model') {
steps {
script {
// Start FastAPI server in the background
bat 'start /B python model_serving.py'
// Wait for the server to start
sleep time: 10, unit: 'SECONDS'
}
}
}
stage('Test Serve Model') {
steps {
script {
// Test the server with sample values
bat '''
curl -X POST "http://127.0.0.1:9000/predict" ^
-H "Content-Type: application/json" ^
-d "{\\"features\\": [13.2, 2.77, 2.51, 18.5, 103.0, 1.15, 2.61, 0.26, 1.46, 3.0, 1.05, 3.33, 820.0]}"
'''
}
}
}
stage('Deploy Model') {
steps {
script {
// Trigger another Jenkins job for model serving
build job: 'ModelServingPipeline', wait: false
}
}
}
}
post {
always {
archiveArtifacts artifacts: '**.pkl', fingerprint: true
echo 'Pipeline execution complete.'
}
}
}
Pipeline di serving del modello (CD)
Ora creeremo una pipeline di deploy continuo per distribuire ed eseguire il server in locale.
Lo script della pipeline è semplice. Iniziamo definendo l’agent e cambiando la directory di lavoro al nostro progetto. Dopodiché, eseguiamo il server a tempo indeterminato.
Nota: eseguire un server in Jenkins a tempo indeterminato non è raccomandato, poiché le pipeline dovrebbero avere un inizio e una fine definiti. Per questo esempio, supponiamo di aver distribuito l’app; in pratica, è meglio integrare Docker ed eseguire l’app su un server Docker.
Se ti interessa imparare a pensare come un machine learning engineer, valuta di seguire il corso Developing Machine Learning Models for Production with an MLOps Mindset, che ti permetterà di addestrare, documentare, mantenere e scalare i tuoi modelli di machine learning al massimo del loro potenziale.
pipeline {
agent {
node {
label 'MLAgent'
customWorkspace 'C:/Repository/GitHub/MLOps-Jenkins/'
}
}
stages {
stage('Start FastAPI Server') {
steps {
script {
// Start the FastAPI server
bat 'python model_serving.py'
}
}
}
}
}
Eseguire le pipeline CI/CD
Vai alla pipeline “MLOps-pipe” e clicca sul pulsante “Build Now” per avviare la pipeline CI/CD.
Una volta eseguita con successo, la pipeline genera due artifact: uno per il modello e uno per il dataset elaborato.

Clicca sul pulsante “Stages” nella dashboard di Jenkins per visualizzare la pipeline e vedere tutti i passaggi.

Per visualizzare i log dettagliati di ogni passaggio, consulta il menu "Pipeline Console".

Possiamo anche controllare la "ModelServingPipeline" per verificare che il nostro server sia in esecuzione all’URL locale http://127.0.0.1:9000.

Provare l’applicazione FastAPI nel browser
FastAPI include Swagger UI, accessibile aggiungendo /docs all’URL locale: http://127.0.0.1:9000/docs.
Swagger UI ci permette di testare l’app FastAPI nel browser. È semplice, e possiamo vedere che il nostro server del modello funziona correttamente. I valori di esempio previsti indicano che il tipo di vino è Rubresco.

Ricorda sempre di spegnere il server del modello dopo aver finito gli esperimenti. Puoi farlo andando nel menu “Status” nella dashboard di Jenkins e cliccando sulla croce, come mostrato sotto:

Tutto il codice, i dataset, i modelli e i metadati di questo tutorial sono disponibili nel repository GitHub per provarli: kingabzpro/MLOps-with-Jenkins.
Conclusione
Jenkins è un ottimo server di automazione per ogni tipo di attività MLOps. Si distingue come un’eccellente alternativa a GitHub Actions offrendo più funzionalità, maggiore controllo e una privacy superiore.
Uno degli aspetti più interessanti di Jenkins è la semplicità con cui si creano ed eseguono le pipeline, rendendolo accessibile sia ai principianti sia agli utenti esperti.
Se ti interessa esplorare funzionalità analoghe usando GitHub Actions, non perderti il tutorial A Beginner's Guide to CI/CD for Machine Learning. Per chi vuole approfondire l’MLOps, il corso Fully Automated MLOps è una risorsa fantastica. Offre una panoramica completa dell’architettura MLOps, delle tecniche CI/CD/CM/CT e dei pattern di automazione per distribuire sistemi di ML che possano fornire valore in modo costante nel tempo.
In quanto data scientist certificato, sono appassionato di sfruttare tecnologie all’avanguardia per creare applicazioni di machine learning innovative. Con una solida esperienza in riconoscimento vocale, analisi e reportistica dei dati, MLOps, AI conversazionale e NLP, ho affinato le mie competenze nello sviluppo di sistemi intelligenti in grado di avere un impatto concreto. Oltre alla mia expertise tecnica, sono anche un comunicatore efficace, con il talento di rendere chiari e sintetici concetti complessi. Di conseguenza, sono diventato un blogger molto seguito in ambito data science, condividendo idee ed esperienze con una community in crescita di professionisti dei dati. Attualmente mi concentro sulla creazione e sull’editing di contenuti, lavorando con large language model per sviluppare contenuti potenti e coinvolgenti che possano aiutare aziende e singoli a valorizzare al meglio i propri dati.



In questo tutorial impareremo a installare e usare Jenkins, a creare agent e pipeline e a eseguirle.
In particolare, vedremo come:
Se ti serve un ripasso, segui il corso breve e lineare MLOps Concepts per imparare a portare i modelli di machine learning dai notebook Jupyter a modelli funzionanti in produzione che generano reale valore di business.
Che cos’è Jenkins?
Jenkins è un server di automazione open-source che svolge un ruolo importante nel processo di sviluppo del machine learning facilitando l’integrazione continua (CI) e il deploy continuo (CD).
Scritto in Java, Jenkins aiuta ad automatizzare l’elaborazione dei dati, l’addestramento, la valutazione e il deploy dei progetti di machine learning, rendendolo uno strumento essenziale per le pratiche MLOps.
Funzionalità di Jenkins:
L’automazione dei task con Jenkins è solo una parte dell’ecosistema MLOps. Puoi scoprire altre attività leggendo il blog 25 Top MLOps Tools You Need to Know in 2024. Comprende strumenti per il tracciamento degli esperimenti, la gestione dei metadati dei modelli, l’orchestrazione dei workflow, il versioning di dati e pipeline, il deploy, il serving e il monitoraggio dei modelli in produzione.