Come creare un'infrastruttura di sviluppo in una macchina virtuale Linux in Azure con Jenkins, GitHub e DockerHow to create a development infrastructure on a Linux VM in Azure with Jenkins, GitHub, and Docker

Per automatizzare le fasi di compilazione e test dello sviluppo di un'applicazione, è possibile usare una pipeline per l'integrazione e la distribuzione continue (CI/CD).To automate the build and test phase of application development, you can use a continuous integration and deployment (CI/CD) pipeline. In questa esercitazione viene creata una pipeline CI/CD in una macchina virtuale di Azure e viene illustrato come:In this tutorial, you create a CI/CD pipeline on an Azure VM including how to:

  • Creare una macchina virtuale JenkinsCreate a Jenkins VM
  • Installare e configurare JenkinsInstall and configure Jenkins
  • Creare un'integrazione webhook tra GitHub e JenkinsCreate webhook integration between GitHub and Jenkins
  • Creare e attivare processi di compilazione Jenkins da commit GitHubCreate and trigger Jenkins build jobs from GitHub commits
  • Creare un'immagine Docker per l'appCreate a Docker image for your app
  • Verificare che i commit GitHub compilino una nuova immagine Docker e gli aggiornamenti che eseguono l'appVerify GitHub commits build new Docker image and updates running app

Avviare Azure Cloud ShellLaunch Azure Cloud Shell

Azure Cloud Shell è una shell Bash gratuita che può essere eseguita direttamente nel portale di Azure.The Azure Cloud Shell is a free Bash shell that you can run directly within the Azure portal. Include l'interfaccia della riga di comando di Azure preinstallata e configurata per l'uso con l'account.It has the Azure CLI preinstalled and configured to use with your account. Fare clic sul pulsante Cloud Shell nel menu nel riquadro in alto a destra nel portale di Azure.Click the Cloud Shell button on the menu in the upper-right of the Azure portal.

Cloud ShellCloud Shell

Il pulsante avvia una shell interattiva che è possibile usare per eseguire i passaggi di questo argomento:The button launches an interactive shell that you can use to run the steps in this topic:

Screenshot che mostra la finestra di Cloud Shell nel portaleScreenshot showing the Cloud Shell window in the portal

Se si sceglie di installare e usare l'interfaccia della riga di comando in locale, per questa esercitazione è necessario eseguire l'interfaccia della riga di comando di Azure versione 2.0.4 o successiva.If you choose to install and use the CLI locally, this tutorial requires that you are running the Azure CLI version 2.0.4 or later. Eseguire az --version per trovare la versione.Run az --version to find the version. Se è necessario eseguire l'installazione o l'aggiornamento, vedere Installare l'interfaccia della riga di comando di Azure 2.0.If you need to install or upgrade, see Install Azure CLI 2.0.

Creare l'istanza di JenkinsCreate Jenkins instance

In un'esercitazione precedente, How to customize a Linux virtual machine on first boot (Come personalizzare una macchina virtuale Linux al primo avvio), è stato descritto come personalizzare una macchina virtuale al primo avvio con cloud-init.In a previous tutorial on How to customize a Linux virtual machine on first boot, you learned how to automate VM customization with cloud-init. Questa esercitazione usa un file cloud-init per installare Jenkins e Docker in una macchina virtuale.This tutorial uses a cloud-init file to install Jenkins and Docker on a VM. Jenkins è un server di automazione open source molto diffuso che si integra uniformemente con Azure per consentire l'integrazione continua e il recapito continuo.Jenkins is a popular open source automation server that integrates seamlessly with Azure to enable continuous integration (CI) and continuous delivery (CD). Per altre esercitazioni sull'uso di Jenkins, vedere Jenkins in Azure.For more tutorials on how to use Jenkins, see the Jenkins in Azure hub.

Nella shell corrente creare un file denominato cloud-init.txt e incollare la configurazione seguente.In your current shell, create a file named cloud-init.txt and paste the following configuration. Ad esempio, creare il file in Cloud Shell anziché nel computer locale.For example, create the file in the Cloud Shell not on your local machine. Immettere sensible-editor cloud-init-jenkins.txt per creare il file e visualizzare un elenco degli editor disponibili.Enter sensible-editor cloud-init-jenkins.txt to create the file and see a list of available editors. Assicurarsi che l'intero file cloud-init venga copiato correttamente, in particolare la prima riga:Make sure that the whole cloud-init file is copied correctly, especially the first line:

#cloud-config
package_upgrade: true
write_files:
  - path: /etc/systemd/system/docker.service.d/docker.conf
    content: |
      [Service]
        ExecStart=
        ExecStart=/usr/bin/dockerd
  - path: /etc/docker/daemon.json
    content: |
      {
        "hosts": ["fd://","tcp://127.0.0.1:2375"]
      }
runcmd:
  - wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | apt-key add -
  - sh -c 'echo deb http://pkg.jenkins-ci.org/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
  - apt-get update && apt-get install jenkins -y
  - curl -sSL https://get.docker.com/ | sh
  - usermod -aG docker azureuser
  - usermod -aG docker jenkins
  - service jenkins restart

Per poter creare una macchina virtuale è prima necessario creare un gruppo di risorse con il comando az group create.Before you can create a VM, create a resource group with az group create. L'esempio seguente crea un gruppo di risorse denominato myResourceGroupJenkins nella posizione eastus:The following example creates a resource group named myResourceGroupJenkins in the eastus location:

az group create --name myResourceGroupJenkins --location eastus

Creare quindi una macchina virtuale con il comando az vm create.Now create a VM with az vm create. Usare il parametro --custom-data per specificare il file di configurazione di cloud-init.Use the --custom-data parameter to pass in your cloud-init config file. Se il file è stato salvato all'esterno della directory di lavoro corrente, specificare il percorso completo di cloud-init-jenkins.txt.Provide the full path to cloud-init-jenkins.txt if you saved the file outside of your present working directory.

az vm create --resource-group myResourceGroupJenkins \
    --name myVM \
    --image UbuntuLTS \
    --admin-username azureuser \
    --generate-ssh-keys \
    --custom-data cloud-init-jenkins.txt

Per creare e configurare la macchina virtuale sono necessari alcuni minuti.It takes a few minutes for the VM to be created and configured.

Per consentire al traffico Web di raggiungere la macchina virtuale, usare az vm open-port per aprire la porta 8080 per il traffico Jenkins e la porta 1337 per l'app Node.js che viene usata per eseguire un'app di esempio:To allow web traffic to reach your VM, use az vm open-port to open port 8080 for Jenkins traffic and port 1337 for the Node.js app that is used to run a sample app:

az vm open-port --resource-group myResourceGroupJenkins --name myVM --port 8080 --priority 1001
az vm open-port --resource-group myResourceGroupJenkins --name myVM --port 1337 --priority 1002

Configurare JenkinsConfigure Jenkins

Per accedere all'istanza di Jenkins, ottenere l'indirizzo IP pubblico della macchina virtuale:To access your Jenkins instance, obtain the public IP address of your VM:

az vm show --resource-group myResourceGroupJenkins --name myVM -d --query [publicIps] --o tsv

Per motivi di sicurezza, è necessario immettere la password amministratore iniziale che viene archiviata in un file di testo nella macchina virtuale per avviare l'installazione di Jenkins.For security purposes, you need to enter the initial admin password that is stored in a text file on your VM to start the Jenkins install. Usare l'indirizzo IP pubblico ottenuto nel passaggio precedente per la connessione SSH alla macchina virtuale:Use the public IP address obtained in the previous step to SSH to your VM:

ssh azureuser@<publicIps>

Visualizzare la password initialAdminPassword per l'installazione di Jenkins e copiarla:View the initialAdminPassword for your Jenkins install and copy it:

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

Se il file non è ancora disponibile, attendere ancora qualche minuto che cloud-init completi l'installazione di Jenkins e Docker.If the file isn't available yet, wait a couple more minutes for cloud-init to complete the Jenkins and Docker install.

Aprire un Web browser e passare a http://<publicIps>:8080.Now open a web browser and go to http://<publicIps>:8080. Completare la configurazione iniziale di Jenkins come segue:Complete the initial Jenkins setup as follows:

  • Immettere la password initialAdminPassword ottenuta dalla macchina virtuale nel passaggio precedente.Enter the initialAdminPassword obtained from the VM in the previous step.
  • Scegliere Select plugins to install (Selezionare il plug-in da installare)Choose Select plugins to install
  • Cercare GitHub nella casella di testo nella parte superiore, selezionare il plug-in GitHub e quindi fare clic su Install (Installa).Search for GitHub in the text box across the top, select the GitHub plugin, then select Install
  • Per creare un account utente di Jenkins, compilare il modulo secondo le esigenze.To create a Jenkins user account, fill out the form as desired. Dal punto di vista della sicurezza, è consigliabile creare questo primo utente Jenkins anziché continuare con l'account amministratore predefinito.From a security perspective, you should create this first Jenkins user rather than continuing as the default admin account.
  • Al termine, selezionare Start using Jenkins (Inizia a usare Jenkins).When finished, select Start using Jenkins

Creare webhook di GitHubCreate GitHub webhook

Per configurare l'integrazione con GitHub, aprire l'app di esempio Node.js Hello World dal repository di esempi di Azure.To configure the integration with GitHub, open the Node.js Hello World sample app from the Azure samples repo. Per creare il fork del repository nel proprio account GitHub, selezionare il pulsante Fork nell'angolo superiore destro.To fork the repo to your own GitHub account, select the Fork button in the top right-hand corner.

Creare un webhook all'interno del fork creato:Create a webhook inside the fork you created:

  • Selezionare Settings (Impostazioni) e quindi Integrations & services (Integrazioni e servizi) sul lato sinistro.Select Settings, then select Integrations & services on the left-hand side.
  • Scegliere Add service (Aggiungi servizio) e quindi immettere Jenkins nella casella del filtro.Choose Add service, then enter Jenkins in filter box.
  • Selezionare Jenkins (GitHub plugin) (Jenkins (plug-in GitHub)).Select Jenkins (GitHub plugin)
  • In Jenkins hook URL (URL hook Jenkins) immettere http://<publicIps>:8080/github-webhook/.For the Jenkins hook URL, enter http://<publicIps>:8080/github-webhook/. Assicurarsi di includere la barra finale (/).Make sure you include the trailing /
  • Selezionare Add service (Aggiungi servizio)Select Add service

Aggiunta del webhook di GitHub al repository con fork

Creare un processo di JenkinsCreate Jenkins job

Per fare in modo che Jenkins risponda a un evento in GitHub, ad esempio l'esecuzione del commit di codice, creare un processo di Jenkins.To have Jenkins respond to an event in GitHub such as committing code, create a Jenkins job.

Nel sito Web di Jenkins selezionare Create new jobs (Crea nuovi processi) dalla home page:In your Jenkins website, select Create new jobs from the home page:

  • Immettere HelloWorld come nome del processo.Enter HelloWorld as job name. Scegliere Freestyle project (Progetto Freestyle) e quindi selezionare OK.Choose Freestyle project, then select OK.
  • Nella sezione General (Generale) selezionare il progetto GitHub e immettere l'URL del repository con fork, ad esempio https://github.com/iainfoulds/nodejs-docs-hello-world.Under the General section, select GitHub project and enter your forked repo URL, such as https://github.com/iainfoulds/nodejs-docs-hello-world
  • Nella sezione Source code management (Gestione del codice sorgente) selezionare Git e immettere l'URL .git del repository con fork, ad esempio https://github.com/iainfoulds/nodejs-docs-hello-world.git.Under the Source code management section, select Git, enter your forked repo .git URL, such as https://github.com/iainfoulds/nodejs-docs-hello-world.git
  • Nella sezione Build Triggers (Trigger di compilazione) selezionare GitHub hook trigger for GITScm polling (Trigger di hook GitHub per polling GITScm).Under the Build Triggers section, select GitHub hook trigger for GITscm polling.
  • Nella sezione Build (Compilazione) scegliere Add build step (Aggiungi istruzione di compilazione).Under the Build section, choose Add build step. Selezionare Execute shell (Esegui shell) e quindi immettere echo "Testing" nella finestra di comando.Select Execute shell, then enter echo "Testing" in to command window.
  • Selezionare Save (Salva) nella parte inferiore della finestra dei processi.Select Save at the bottom of the jobs window.

Testare l'integrazione di GitHubTest GitHub integration

Per testare l'integrazione di GitHub con Jenkins, eseguire il commit di una modifica nel fork.To test the GitHub integration with Jenkins, commit a change in your fork.

Nell'interfaccia utente Web di GitHub selezionare il repository con fork e quindi fare clic sul file index.js.Back in GitHub web UI, select your forked repo, and then select the index.js file. Selezionare l'icona a forma di matita per modificare il file in modo che la riga 6 corrisponda a:Select the pencil icon to edit this file so line 6 reads:

response.end("Hello World!");

Per eseguire il commit delle modifiche, selezionare il pulsante Commit changes (Esegui il commit delle modifiche) nella parte inferiore.To commit your changes, select the Commit changes button at the bottom.

In Jenkins viene avviata una nuova compilazione nella sezione Build history (Cronologia compilazione) nell'angolo inferiore sinistro della pagina del processo.In Jenkins, a new build starts under the Build history section of the bottom left-hand corner of your job page. Scegliere il collegamento del numero di build e selezionare Console output (Output console) sul lato sinistro.Choose the build number link and select Console output on the left-hand size. È possibile visualizzare i passaggi eseguiti in Jenkins mentre viene eseguito il pull del codice da GitHub e l'azione di compilazione genera il messaggio Testing nella console.You can view the steps Jenkins takes as your code is pulled from GitHub and the build action outputs the message Testing to the console. Ogni volta che si esegue un'operazione di commit in GitHub, il webhook contatta Jenkins e attiva una nuova compilazione in questo modo.Each time a commit is made in GitHub, the webhook reaches out to Jenkins and trigger a new build in this way.

Definire l'immagine di compilazione di DockerDefine Docker build image

Per visualizzare l'app Node.js in esecuzione sulla base dei commit GitHub, è necessario creare un'immagine Docker per l'esecuzione dell'app.To see the Node.js app running based on your GitHub commits, lets build a Docker image to run the app. L'immagine viene creata da un file Dockerfile che definisce come configurare il contenitore che esegue l'app.The image is built from a Dockerfile that defines how to configure the container that runs the app.

Dalla connessione SSH alla macchina virtuale, passare alla directory dell'area di lavoro di Jenkins denominata sulla base del processo creato in un passaggio precedente.From the SSH connection to your VM, change to the Jenkins workspace directory named after the job you created in a previous step. In questo esempio è stata denominata HelloWorld.In our example, that was named HelloWorld.

cd /var/lib/jenkins/workspace/HelloWorld

Creare un file con sudo sensible-editor Dockerfile in questa directory dell'area di lavoro e incollare il contenuto seguente:Create a file with in this workspace directory with sudo sensible-editor Dockerfile and paste the following contents. Assicurarsi che l'intero file Docker venga copiato correttamente, in particolare la prima riga:Make sure that the whole Dockerfile is copied correctly, especially the first line:

FROM node:alpine

EXPOSE 1337

WORKDIR /var/www
COPY package.json /var/www/
RUN npm install
COPY index.js /var/www/

Questo file Dockerfile usa l'immagine di base Node.js con Alpine Linux, espone la porta 1337 in cui viene eseguita l'app Hello World, quindi copia i file dell'app e la inizializza.This Dockerfile uses the base Node.js image using Alpine Linux, exposes port 1337 that the Hello World app runs on, then copies the app files and initializes it.

Creare regole di compilazione di JenkinsCreate Jenkins build rules

In un passaggio precedente è stata creata una regola di compilazione di base di Jenkins che genera un messaggio nella console.In a previous step, you created a basic Jenkins build rule that output a message to the console. Ora è necessario creare l'istruzione di compilazione per usare il file Dockerfile ed eseguire l'app.Lets create the build step to use our Dockerfile and run the app.

Nell'istanza di Jenkins selezionare il processo creato in un passaggio precedente.Back in your Jenkins instance, select the job you created in a previous step. Selezionare Configure (Configura) sul lato sinistro e scorrere fino alla sezione Build (Compilazione):Select Configure on the left-hand side and scroll down to the Build section:

  • Rimuovere l'istruzione di compilazione echo "Test" esistente.Remove your existing echo "Test" build step. Selezionare la croce rossa nell'angolo superiore destro della casella dell'istruzione di compilazione esistente.Select the red cross on the top right-hand corner of the existing build step box.
  • Scegliere Add build step (Aggiungi istruzione di compilazione) e quindi selezionare Execute shell (Esegui shell).Choose Add build step, then select Execute shell
  • Nella casella Command (Comando) immettere i comandi Docker seguenti, quindi selezionare Save (Salva):In the Command box, enter the following Docker commands, then select Save:

    docker build --tag helloworld:$BUILD_NUMBER .
    docker stop helloworld && docker rm helloworld
    docker run --name helloworld -p 1337:1337 helloworld:$BUILD_NUMBER node /var/www/index.js &
    

Le istruzioni di compilazione Docker creano un'immagine contrassegnata con il numero di build Jenkins, in modo da mantenere una cronologia delle immagini.The Docker build steps create an image and tag it with the Jenkins build number so you can maintain a history of images. Gli eventuali contenitori esistenti che eseguono l'app vengono arrestati e quindi rimossi.Any existing containers running the app are stopped and then removed. Si avvia quindi un nuovo contenitore usando l'immagine e si esegue l'app Node.js in base agli ultimi commit in GitHub.A new container is then started using the image and runs your Node.js app based on the latest commits in GitHub.

Testare la pipelineTest your pipeline

Per visualizzare l'intera pipeline in azione, modificare nuovamente il file index.js nel repository GitHub con fork e selezionare Commit change (Esegui il commit della modifica).To see the whole pipeline in action, edit the index.js file in your forked GitHub repo again and select Commit change. Viene avviato un nuovo processo in Jenkins in base al webhook per GitHub.A new job starts in Jenkins based on the webhook for GitHub. Potrebbero essere necessari alcuni secondi per creare l'immagine Docker e avviare l'app in un nuovo contenitore.It takes a few seconds to create the Docker image and start your app in a new container.

Se necessario, ottenere nuovamente l'indirizzo IP pubblico della macchina virtuale:If needed, obtain the public IP address of your VM again:

az vm show --resource-group myResourceGroupJenkins --name myVM -d --query [publicIps] --o tsv

Aprire un Web browser e immettere http://<publicIps>:1337.Open a web browser and enter http://<publicIps>:1337. Viene visualizzata l'app Node.js che rispecchia gli ultimi commit nel fork GitHub come illustrato di seguito:Your Node.js app is displayed and reflects the latest commits in your GitHub fork as follows:

Esecuzione dell'app Node.js

Apportare un'altra modifica al file index.js in GitHub ed eseguire il commit della modifica.Now make another edit to the index.js file in GitHub and commit the change. Attendere alcuni secondi per il completamento del processo in Jenkins, quindi aggiornare il Web browser per visualizzare la versione aggiornata dell'app in esecuzione in un nuovo contenitore come segue:Wait a few seconds for the job to complete in Jenkins, then refresh your web browser to see the updated version of your app running in a new container as follows:

Esecuzione dell'app Node.js dopo un altro commit GitHub

Passaggi successiviNext steps

In questa esercitazione è stato configurato GitHub per eseguire un processo di compilazione Jenkins in ogni commit di codice e quindi distribuire un contenitore Docker per testare l'app.In this tutorial, you configured GitHub to run a Jenkins build job on each code commit and then deploy a Docker container to test your app. Si è appreso come:You learned how to:

  • Creare una macchina virtuale JenkinsCreate a Jenkins VM
  • Installare e configurare JenkinsInstall and configure Jenkins
  • Creare un'integrazione webhook tra GitHub e JenkinsCreate webhook integration between GitHub and Jenkins
  • Creare e attivare processi di compilazione Jenkins da commit GitHubCreate and trigger Jenkins build jobs from GitHub commits
  • Creare un'immagine Docker per l'appCreate a Docker image for your app
  • Verificare che i commit GitHub compilino una nuova immagine Docker e gli aggiornamenti che eseguono l'appVerify GitHub commits build new Docker image and updates running app

Passare all'esercitazione successiva per ottenere altre informazioni su come integrare Jenkins con Visual Studio Team Services.Advance to the next tutorial to learn more about how to integrate Jenkins with Visual Studio Team Services.