Tutorial: Creación de una infraestructura de desarrollo en una máquina virtual Linux en Azure con Jenkins, GitHub y DockerTutorial: Create a development infrastructure on a Linux VM in Azure with Jenkins, GitHub, and Docker

Para automatizar las fases de compilación y prueba del desarrollo de la aplicación, puede utilizar una canalización de integración e implementación continua (CI/CD).To automate the build and test phase of application development, you can use a continuous integration and deployment (CI/CD) pipeline. En este tutorial, creará una canalización de CI/CD en una máquina virtual de Azure, y aprenderá los siguientes temas:In this tutorial, you create a CI/CD pipeline on an Azure VM including how to:

  • Crear una máquina virtual de JenkinsCreate a Jenkins VM
  • Instalar y configurar JenkinsInstall and configure Jenkins
  • Crear la integración de webhook entre GitHub y JenkinsCreate webhook integration between GitHub and Jenkins
  • Crear y desencadenar trabajos de compilación de Jenkins desde confirmaciones de GitHubCreate and trigger Jenkins build jobs from GitHub commits
  • Crear una imagen de Docker para la aplicaciónCreate a Docker image for your app
  • Comprobar que GitHub confirma la imagen de Docker de nueva compilación y actualiza la aplicación en ejecuciónVerify GitHub commits build new Docker image and updates running app

Uso de Azure Cloud ShellUse Azure Cloud Shell

En Azure se hospeda Azure Cloud Shell, un entorno de shell interactivo que puede utilizar mediante el explorador.Azure hosts Azure Cloud Shell, an interactive shell environment that you can use through your browser. Cloud Shell le permite usar bash o PowerShell para trabajar con servicios de Azure.Cloud Shell lets you use either bash or PowerShell to work with Azure services. Puede usar los comandos preinstalados de Cloud Shell para ejecutar el código de este artículo sin tener que instalar nada en su entorno local.You can use the Cloud Shell pre-installed commands to run the code in this article without having to install anything on your local environment.

Para iniciar Azure Cloud Shell:To launch Azure Cloud Shell:

OpciónOption Ejemplo o vínculoExample/Link
Seleccione Probarlo en la esquina superior derecha de un bloque de código.Select Try It in the upper-right corner of a code block. Solo con seleccionar Probar no se copia automáticamente el código en Cloud Shell.Selecting Try It doesn't automatically copy the code to Cloud Shell. Ejemplo de Probarlo para Azure Cloud Shell
Vaya a https://shell.azure.com o seleccione el botón Iniciar Cloud Shell para abrir Cloud Shell en el explorador.Go to https://shell.azure.com or select the Launch Cloud Shell button to open Cloud Shell in your browser. Iniciar Cloud Shell en una nueva ventanaLaunch Cloud Shell in a new window
Seleccione el botón Cloud Shell en la barra de menús de la esquina superior derecha de Azure Portal.Select the Cloud Shell button on the top-right menu bar in the Azure portal. Botón Cloud Shell en Azure Portal

Para ejecutar el código de este artículo en Azure Cloud Shell:To run the code in this article in Azure Cloud Shell:

  1. Inicie Cloud Shell.Launch Cloud Shell.
  2. Seleccione el botón Copiar de un bloque de código para copiar el código.Select the Copy button on a code block to copy the code.
  3. Pegue el código en la sesión de Cloud Shell con Ctrl+Mayús+V en Windows y Linux, o Cmd+Mayús+V en macOS.Paste the code into the Cloud Shell session with Ctrl+Shift+V on Windows and Linux, or Cmd+Shift+V on macOS.
  4. Presione ENTRAR para ejecutar el código.Press Enter to run the code.

Si decide instalar y usar la CLI localmente, en este tutorial es preciso que ejecute la CLI de Azure de la versión 2.0.30, u otra posterior.If you choose to install and use the CLI locally, this tutorial requires that you are running the Azure CLI version 2.0.30 or later. Ejecute az --version para encontrar la versión.Run az --version to find the version. Si necesita instalarla o actualizarla, vea Instalación de la CLI de Azure.If you need to install or upgrade, see Install Azure CLI.

Creación de la instancia de JenkinsCreate Jenkins instance

En un tutorial anterior sobre cómo personalizar una máquina virtual Linux en el primer arranque, aprendió a automatizar la personalización de máquinas virtuales 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. Este tutorial utiliza un archivo cloud-init para instalar Jenkins y Docker en una máquina virtual.This tutorial uses a cloud-init file to install Jenkins and Docker on a VM. Jenkins es un popular servidor de automatización de código abierto que se integra perfectamente con Azure para permitir la integración continua (CI) y la entrega continua (CD).Jenkins is a popular open-source automation server that integrates seamlessly with Azure to enable continuous integration (CI) and continuous delivery (CD). Para más tutoriales sobre cómo usar Jenkins, consulte el artículo sobre Jenkins en el concentrador de Azure.For more tutorials on how to use Jenkins, see the Jenkins in Azure hub.

En el shell actual, cree un archivo denominado cloud-init-jenkins.txt y pegue la siguiente configuración.In your current shell, create a file named cloud-init-jenkins.txt and paste the following configuration. Por ejemplo, cree el archivo en Cloud Shell, no en la máquina local.For example, create the file in the Cloud Shell not on your local machine. Escriba sensible-editor cloud-init-jenkins.txt para crear el archivo y ver una lista de editores disponibles.Enter sensible-editor cloud-init-jenkins.txt to create the file and see a list of available editors. Asegúrese de que todo el archivo cloud-init se copia correctamente, especialmente la primera línea: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:
  - apt install openjdk-8-jre-headless -y
  - wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
  - sh -c 'echo deb https://pkg.jenkins.io/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

Antes de poder crear una máquina virtual, cree un grupo de recursos con az group create.Before you can create a VM, create a resource group with az group create. En el ejemplo siguiente, se crea un grupo de recursos denominado "myResourceGroupJenkins" en la ubicación eastus:The following example creates a resource group named myResourceGroupJenkins in the eastus location:

az group create --name myResourceGroupJenkins --location eastus

Ahora cree una máquina virtual con el comando az vm create.Now create a VM with az vm create. Use el parámetro --custom-data para pasar su archivo de configuración cloud-init.Use the --custom-data parameter to pass in your cloud-init config file. Proporcione la ruta de acceso completa a la configuración de cloud-init-jenkins.txt si guardó el archivo fuera de su directorio de trabajo actual.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

La máquina virtual tarda unos minutos en crearse y configurarse.It takes a few minutes for the VM to be created and configured.

Con el objetivo de permitir que el tráfico web llegue a la máquina virtual, use az vm open-port para abrir el puerto 8080 para el tráfico de Jenkins, y el puerto 1337 para la aplicación Node.js que se usa para ejecutar una aplicación de ejemplo: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

Configuración de JenkinsConfigure Jenkins

Para acceder a la instancia de Jenkins, obtenga la dirección IP pública de la máquina virtual: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

Por motivos de seguridad, debe escribir la contraseña de administrador inicial que se almacena en un archivo de texto de la máquina virtual para iniciar la instalación de 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. Use la dirección IP pública que obtuvo en el paso anterior para acceder mediante SSH a la máquina virtual:Use the public IP address obtained in the previous step to SSH to your VM:

ssh azureuser@<publicIps>

Compruebe que se ejecuta Jenkins mediante el comando service:Verify Jenkins is running using the service command:

$ service jenkins status
● jenkins.service - LSB: Start Jenkins at boot time
   Loaded: loaded (/etc/init.d/jenkins; generated)
   Active: active (exited) since Tue 2019-02-12 16:16:11 UTC; 55s ago
     Docs: man:systemd-sysv-generator(8)
    Tasks: 0 (limit: 4103)
   CGroup: /system.slice/jenkins.service

Feb 12 16:16:10 myVM systemd[1]: Starting LSB: Start Jenkins at boot time...
...

Consulte el valor de initialAdminPassword de su instalación de Jenkins y cópielo:View the initialAdminPassword for your Jenkins install and copy it:

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

Si el archivo aún no está disponible, espere unos minutos más a que cloud-init complete la instalación de Jenkins y Docker.If the file isn't available yet, wait a couple more minutes for cloud-init to complete the Jenkins and Docker install.

Ahora, abra un explorador web y vaya a http://<publicIps>:8080.Now open a web browser and go to http://<publicIps>:8080. Complete la instalación inicial de Jenkins como sigue:Complete the initial Jenkins setup as follows:

  • Elija Select plugins to install (Seleccionar complementos para instalar).Choose Select plugins to install
  • Busque GitHub en el cuadro de texto de la parte superior.Search for GitHub in the text box across the top. Active la casilla GitHub y, luego, seleccione Install (Instalar).Check the box for GitHub, then select Install
  • Cree el primer usuario administrador.Create the first admin user. Escriba un nombre de usuario, por ejemplo, administrador y, luego, proporcione su propia contraseña segura.Enter a username, such as admin, then provide your own secure password. Por último, escriba un nombre completo y la dirección de correo electrónico.Finally, type a full name and e-mail address.
  • Seleccione Save and Finish (Guardar y finalizar).Select Save and Finish
  • Cuando esté listo Jenkins, seleccione Start using Jenkins (Comenzar a usar Jenkins).Once Jenkins is ready, select Start using Jenkins
    • Si el explorador web muestra una página en blanco cuando empiece a usar Jenkins, reinicie el servicio Jenkins.If your web browser displays a blank page when you start using Jenkins, restart the Jenkins service. En la sesión de SSH, escriba sudo service jenkins restart y, luego, actualice el explorador web.From your SSH session, type sudo service jenkins restart, then refresh you web browser.
  • Si fuera necesario, inicie sesión en Jenkins con el nombre de usuario y la contraseña que ha creado.If needed, log in to Jenkins with the username and password you created.

Creación de un webhook de GitHubCreate GitHub webhook

Para configurar la integración con GitHub, abra la aplicación de ejemplo Hello World de Node.js desde el repositorio de ejemplos de Azure.To configure the integration with GitHub, open the Node.js Hello World sample app from the Azure samples repo. Para bifurcar el repositorio en su propia cuenta de GitHub, seleccione el botón Fork (Bifurcar) de la esquina superior derecha.To fork the repo to your own GitHub account, select the Fork button in the top right-hand corner.

Cree un webhook dentro de la bifurcación que ha creado:Create a webhook inside the fork you created:

  • Seleccione Configuración y Webhooks en el lado izquierdo.Select Settings, then select Webhooks on the left-hand side.
  • Elija Agregar webhook y, luego, escriba Jenkins en el cuadro de filtro.Choose Add webhook, then enter Jenkins in filter box.
  • En Payload URL (Dirección URL de carga), escriba http://<publicIps>:8080/github-webhook/.For the Payload URL, enter http://<publicIps>:8080/github-webhook/. Asegúrese de incluir la barra diagonal final (/).Make sure you include the trailing /
  • En Content type (Tipo de contenido), seleccione application/x--www-form-urlencoded.For Content type, select application/x-www-form-urlencoded.
  • En Which events would you like to trigger this webhook? (¿Qué eventos desea que desencadene este webhook?), seleccione Just the push event (Solo el evento de inserción).For Which events would you like to trigger this webhook?, select Just the push event.
  • Establezca Active (Activo) en seleccionado.Set Active to checked.
  • Haga clic en Agregar webhook.Click Add webhook.

Incorporación del webhook de GitHub en el repositorio bifurcado

Creación de trabajos de JenkinsCreate Jenkins job

Para que Jenkins responda a un evento de GitHub como código de confirmación, cree un trabajo de Jenkins.To have Jenkins respond to an event in GitHub such as committing code, create a Jenkins job. Use las direcciones URL de su propia bifurcación de GitHub.Use the URLs for your own GitHub fork.

En el sitio web de Jenkins, seleccione Create new jobs (Crear trabajos nuevos) desde la página principal:In your Jenkins website, select Create new jobs from the home page:

  • Escriba HelloWorld como nombre del trabajo.Enter HelloWorld as job name. Seleccione Freestyle project (Proyecto de estilo libre) y elija OK (Aceptar).Choose Freestyle project, then select OK.
  • En la sección General, seleccione GitHub project (Proyecto de GitHub) y escriba la dirección URL del repositorio bifurcado, como https://github.com/cynthn/nodejs-docs-hello-world .Under the General section, select GitHub project and enter your forked repo URL, such as https://github.com/cynthn/nodejs-docs-hello-world
  • En la sección Source code management (Administración del código fuente), seleccione Git y escriba la dirección URL de su repositorio bifurcado .git, como https://github.com/cynthn/nodejs-docs-hello-world.git .Under the Source code management section, select Git, enter your forked repo .git URL, such as https://github.com/cynthn/nodejs-docs-hello-world.git
  • En la sección Build Triggers (Compilar desencadenadores), seleccione GitHub hook trigger for GITScm polling (Desencadenador de enlace de GitHub para sondeo de GITScm).Under the Build Triggers section, select GitHub hook trigger for GITscm polling.
  • En la sección Build (Compilación), seleccione Add build step (Agregar el paso de compilación).Under the Build section, choose Add build step. Seleccione Execute shell (Ejecutar shell) y escriba echo "Test" en la ventana de comandos.Select Execute shell, then enter echo "Test" in the command window.
  • Seleccione Save (Guardar) en la parte inferior de la ventana de trabajos.Select Save at the bottom of the jobs window.

Prueba de la integración de GitHubTest GitHub integration

Para probar la integración de GitHub con Jenkins, confirme un cambio en la bifurcación.To test the GitHub integration with Jenkins, commit a change in your fork.

En la interfaz de usuario web de GitHub, seleccione el repositorio bifurcado y, luego, seleccione el archivo index.js.Back in GitHub web UI, select your forked repo, and then select the index.js file. Seleccione el icono de lápiz para editar este archivo para que la línea 6 tenga este aspecto:Select the pencil icon to edit this file so line 6 reads:

response.end("Hello World!");

Para confirmar sus cambios, seleccione el botón Confirmar cambios situado en la parte inferior.To commit your changes, select the Commit changes button at the bottom.

En Jenkins, se inicia una nueva compilación en la sección Build history (Historial de compilaciones) de la esquina inferior izquierda de la página de trabajos.In Jenkins, a new build starts under the Build history section of the bottom left-hand corner of your job page. Elija el vínculo del número de compilación y seleccione Console output (Resultado de la consola) en la izquierda.Choose the build number link and select Console output on the left-hand side. Puede ver los pasos que realiza Jenkins cuando el código se ha extraído de GitHub y la acción de compilación genera el mensaje Test en la consola.You can view the steps Jenkins takes as your code is pulled from GitHub and the build action outputs the message Test to the console. Cada vez que se realiza una confirmación en GitHub, el webhook llega a Jenkins y desencadena una nueva compilación de este modo.Each time a commit is made in GitHub, the webhook reaches out to Jenkins and triggers a new build in this way.

Definición de la imagen de la compilación de DockerDefine Docker build image

Para ver la aplicación de Node.js en ejecución en función de las confirmaciones de GitHub, permita que se genere una imagen de Docker para ejecutar la aplicación.To see the Node.js app running based on your GitHub commits, lets build a Docker image to run the app. La imagen se crea a partir de un archivo Dockerfile que define cómo configurar el contenedor que ejecuta la aplicación.The image is built from a Dockerfile that defines how to configure the container that runs the app.

Desde la conexión SSH a la máquina virtual, cambie al directorio del área de trabajo de Jenkins denominado después del trabajo que creó en el paso anterior.From the SSH connection to your VM, change to the Jenkins workspace directory named after the job you created in a previous step. En nuestro ejemplo, se llama "HelloWorld".In this example, that was named HelloWorld.

cd /var/lib/jenkins/workspace/HelloWorld

Cree un archivo en este directorio de área de trabajo con sudo sensible-editor Dockerfile y pegue el contenido siguiente.Create a file in this workspace directory with sudo sensible-editor Dockerfile and paste the following contents. Asegúrese de que todo el archivo Dockerfile se copia correctamente, especialmente la primera línea: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/

Este archivo Dockerfile utiliza la imagen base de Node.js con Linux Alpine, expone el puerto 1337 que ejecuta la aplicación Hello World y, luego, copia los archivos de aplicación y la inicializa.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.

Creación de reglas de generación de JenkinsCreate Jenkins build rules

En un paso anterior, creó una regla de compilación de Jenkins básica que generó un mensaje en la consola.In a previous step, you created a basic Jenkins build rule that output a message to the console. Permite crear el paso de compilación para usar nuestro Dockerfile y ejecutar la aplicación.Lets create the build step to use our Dockerfile and run the app.

En la instancia Jenkins, seleccione el trabajo que creó en el paso anterior.Back in your Jenkins instance, select the job you created in a previous step. Seleccione Configure (Configurar) en el lado izquierdo y desplácese hacia abajo hasta la sección Build (Compilación):Select Configure on the left-hand side and scroll down to the Build section:

  • Quite el paso de compilación echo "Test".Remove your existing echo "Test" build step. Seleccione la cruz roja de la esquina superior derecha de la casilla del paso de compilación existente.Select the red cross on the top right-hand corner of the existing build step box.

  • Elija Add build step (Agregar paso de compilación) y seleccione Execute shell (Ejecutar shell).Choose Add build step, then select Execute shell

  • En el cuadro Command (Comando), escriba los comandos siguientes de Docker y, luego, seleccione Save (Guardar):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 &
    

Los pasos de compilación de Docker crean una imagen y etiqueta con el número de compilación de Jenkins para que pueda mantener un historial de imágenes.The Docker build steps create an image and tag it with the Jenkins build number so you can maintain a history of images. Los contenedores existentes que ejecutan la aplicación se detendrán y, luego, se quitarán.Any existing containers running the app are stopped and then removed. Después, un nuevo contenedor se inicia con la imagen y ejecuta la aplicación de Node.js en función de las confirmaciones más recientes de GitHub.A new container is then started using the image and runs your Node.js app based on the latest commits in GitHub.

Prueba de la canalizaciónTest your pipeline

Para ver toda la canalización en acción, edite el archivo index.js en el nuevo repositorio de GitHub bifurcado y seleccione Commit change (Confirmar cambio).To see the whole pipeline in action, edit the index.js file in your forked GitHub repo again and select Commit change. Un nuevo trabajo se inicia en Jenkins según el webhook de GitHub.A new job starts in Jenkins based on the webhook for GitHub. Tarda unos segundos en crearse la imagen de Docker e iniciarse la aplicación en un nuevo contenedor.It takes a few seconds to create the Docker image and start your app in a new container.

Si es necesario, vuelva a obtener la dirección IP pública de la máquina virtual:If needed, obtain the public IP address of your VM again:

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

Abra un explorador web y escriba http://<publicIps>:1337.Open a web browser and enter http://<publicIps>:1337. La aplicación de Node.js se muestra y refleja las confirmaciones más recientes en la bifurcación de GitHub como se indica a continuación:Your Node.js app is displayed and reflects the latest commits in your GitHub fork as follows:

Ejecución de la aplicación Node.js

Ahora, realice otra modificación en el archivo index.js de GitHub y confirme el cambio.Now make another edit to the index.js file in GitHub and commit the change. Espere unos segundos para que el trabajo se complete en Jenkins; luego, actualice el explorador web para ver la versión actualizada de la aplicación que se ejecuta en un nuevo contenedor como sigue: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:

Aplicación de Node.js en ejecución después de otra confirmación de GitHub

Pasos siguientesNext steps

En este tutorial, ha configurado GitHub para ejecutar un trabajo de compilación de Jenkins en cada confirmación de código y, luego, ha implementado un contenedor de Docker para probar la aplicación.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. Ha aprendido a:You learned how to:

  • Crear una máquina virtual de JenkinsCreate a Jenkins VM
  • Instalar y configurar JenkinsInstall and configure Jenkins
  • Crear la integración de webhook entre GitHub y JenkinsCreate webhook integration between GitHub and Jenkins
  • Crear y desencadenar trabajos de compilación de Jenkins desde confirmaciones de GitHubCreate and trigger Jenkins build jobs from GitHub commits
  • Crear una imagen de Docker para la aplicaciónCreate a Docker image for your app
  • Comprobar que GitHub confirma la imagen de Docker de nueva compilación y actualiza la aplicación en ejecuciónVerify GitHub commits build new Docker image and updates running app

Siga con el próximo tutorial para más información sobre cómo integrar Jenkins con Azure DevOps Services.Advance to the next tutorial to learn more about how to integrate Jenkins with Azure DevOps Services.