Uso de CI/CD para implementar una aplicación web de Python para Azure App Service en Linux
Azure Pipelines
En este artículo, usará Azure Pipelines integración continua y entrega continua (CI/CD) para implementar una aplicación web de Python para Azure App Service en Linux. Para empezar, ejecute el código de la aplicación desde GitHub repositorio localmente. A continuación, aprovisione un App Service a través del Azure Portal. Por último, cree una canalización de CI/CD de Azure Pipelines que compile automáticamente el código y lo implemente en el App Service siempre que haya una confirmación en el repositorio.
Creación de un repositorio para el código de la aplicación
Si ya tiene una aplicación web de Python para usar, asegúrese de que se ha confirmado en un repositorio GitHub aplicaciones.
Nota:
Si la aplicación usa Django y una base de datos sqlite, no funcionará en este tutorial. Para más información, consulte consideraciones sobre Django más adelante en este artículo. Si la aplicación de Django usa una base de datos independiente, puede usarla con este tutorial.
Si necesita una aplicación con la que trabajar, puede bifurcar y clonar el repositorio en https://github.com/Microsoft/python-sample-vscode-flask-tutorial . El código es del tutorial Flask en Visual Studio Code.
Para probar la aplicación de ejemplo localmente, desde la carpeta que contiene el código, ejecute los siguientes comandos adecuados para el sistema operativo:
# Mac/Linux
sudo apt-get install python3-venv # If needed
python3 -m venv .env
source .env/bin/activate
pip install -r requirements.txt
export set FLASK_APP=hello_app.webapp
python3 -m flask run
# Windows
py -3 -m venv .env
.env\scripts\activate
pip install -r requirements.txt
$env:FLASK_APP = "hello_app.webapp"
python -m flask run
Abra un explorador y vaya a http://localhost:5000 para ver la aplicación. Cuando haya terminado, cierre el explorador y detenga el servidor de Flask con CtrlC.
Aprovisionamiento del destino Azure App Service
La manera más rápida de crear una instancia App Service es usar la interfaz de la línea de comandos (CLI) de Azure a través de la interfaz Azure Cloud Shell. En los pasos siguientes, usará az webapp up para aprovisionar la aplicación App Service realizar la primera implementación de la aplicación.
Inicie sesión en Azure Portal en https://portal.azure.com.
Abra el CLI de Azure seleccionando el botón Cloud Shell en la barra de herramientas del portal:

El Cloud Shell aparece en la parte inferior del explorador. Seleccione Bash en la lista desplegable:

En la Cloud Shell, clone el repositorio mediante
git clone. Para la aplicación de ejemplo, use:git clone https://github.com/<your-alias>/python-sample-vscode-flask-tutorialReemplace
<your-alias>por el nombre de la cuenta GitHub que usó para bifurcar el repositorio.Sugerencia
Para pegar en la Cloud Shell, use CtrlMayús V o haga clic con el botón derecho y seleccione Pegar en el menú contextual.
Nota:
La Cloud Shell cuenta está Azure Storage cuenta en un grupo de recursos denominado cloud-shell-storage- your-region >. Esa cuenta de almacenamiento contiene una imagen del sistema de Cloud Shell del usuario, que almacena el repositorio clonado. Este almacenamiento tiene un costo pequeño. Puede eliminar la cuenta de almacenamiento al final de este artículo, junto con otros recursos que cree.
En la Cloud Shell, cambie los directorios a la carpeta del repositorio que tiene la aplicación de Python, por lo que el comando reconocerá la aplicación
az webapp upcomo Python.cd python-sample-vscode-flask-tutorialEn la Cloud Shell, use
az webapp uppara crear un App Service e implementar inicialmente la aplicación.az webapp up -n <your-appservice>Cambie
<your-appservice>por un nombre para el servicio de aplicaciones que sea único en Azure. Normalmente, se usa un nombre personal o de empresa junto con un identificador de aplicación, como<your-name>-flaskpipelines. La dirección URL de la aplicación se convierte en el > archivo .azurewebsites.net.Cuando se completa el comando, muestra la salida JSON en el Cloud Shell.
Sugerencia
Si se produce un error "Permiso denegado" con un archivo .zip, es posible que haya intentado ejecutar el comando desde una carpeta que no contiene una aplicación de Python. A
az webapp upcontinuación, el comando intenta crear una Windows plan de App Service y se produce un error.Si la aplicación usa un comando de inicio personalizado, establezca la propiedad az webapp config. Por ejemplo, la aplicación python-sample-vscode-flask-tutorial contiene un archivo denominado startup.txt que contiene su comando de inicio específico, por lo que debe establecer la propiedad en .
En la primera línea de salida del comando anterior, copie el nombre del grupo de recursos, que es similar a su
az webapp upaz webapp upEscriba el siguiente comando, con el nombre del grupo de recursos, el nombre de App Service ( ) y
<your-appservice>el archivo o comando de inicio (startup.txt).az webapp config set -g <your-resource-group> -n <your-appservice> --startup-file <your-startup-file-or-command>Una vez más, cuando se completa el comando, muestra la salida JSON en el Cloud Shell.
Para ver la aplicación en ejecución, abra un explorador y vaya a http:// your-appservice > .azurewebsites.net. Si ve una página genérica, espere unos segundos a que se inicie App Service y actualice la página.
Nota:
Para obtener una descripción detallada de las tareas específicas realizadas por el comando, vea Aprovisionamiento de un App Service con comandos
az webapp upaz webapp upal final de este artículo.
Creación de un Azure DevOps proyecto y conexión a Azure
Para implementar en Azure App Service desde Azure Pipelines, debe establecer una conexión de servicio entre los dos servicios.
En un explorador, vaya a dev.azure.com. Si aún no tiene una cuenta en Azure DevOps, seleccione Iniciar gratis y obtener una cuenta gratuita. Si ya tiene una cuenta, seleccione Iniciar sesión para Azure DevOps.
Importante
Para simplificar la conexión de servicio, use la misma dirección de correo electrónico Azure DevOps que usa para Azure.
Una vez que inicie sesión, el explorador mostrará el Azure DevOps, en la dirección URL nombre-organización. > Una Azure DevOps puede pertenecer a una o varias organizaciones,que se muestran en el lado izquierdo del panel Azure DevOps datos. Si aparece más de una organización, seleccione la que desea usar para este tutorial. De forma predeterminada, Azure DevOps crea una nueva organización con el alias de correo electrónico que usó para iniciar sesión.
Un proyecto es una agrupación para paneles, repositorios, canalizaciones y otros aspectos de Azure DevOps. Si su organización no tiene ningún proyecto, escriba el nombre del proyecto Flask Pipelines en Crear un proyecto para empezar y, acontinuación, seleccione Crear proyecto.

Si su organización ya tiene proyectos, seleccione Nuevo proyecto en la página de la organización. En el cuadro de diálogo Crear nuevo proyecto, escriba el nombre del proyecto Flask Pipelinesy seleccione Crear.
En la página del nuevo proyecto, seleccione Project configuración en el panel de navegación izquierdo.

En la página Project Configuración, seleccione Pipelines Service connections (Conexiones de servicio), seleccioneNew service connection (Nueva conexión de servicio) y, a continuación, seleccione Azure Resource Manager en la lista desplegable.

En el cuadro de diálogo Agregar Azure Resource Manager conexión de servicio de servidor:
- Asigne un nombre a la conexión. Anote el nombre que se usará más adelante en la canalización.
- En Nivel de ámbito,seleccione Suscripción.
- Seleccione la suscripción de su App Service en la lista desplegable Suscripción.
- En Grupo de recursos,seleccione el grupo de recursos en la lista desplegable.
- Asegúrese de que está seleccionada la opción Permitir que todas las canalizaciones usen esta conexión y, a continuación, seleccione Aceptar.

La nueva conexión aparece en la lista Conexiones de servicio y está lista para Azure Pipelines usar desde el proyecto.
Nota:
Si necesita usar una suscripción de Azure desde otra cuenta de correo electrónico, siga las instrucciones de Creación de una conexión de servicio de Azure Resource Manager con una entidad de servicio existente.
Creación de una canalización específica de Python para implementarla en App Service
En el panel de navegación izquierdo de la página del proyecto, seleccione Pipelines.

Seleccione Crear canalización:
En la pantalla Where is your code (Dónde está el código), seleccione GitHub. Es posible que se le pida que inicie sesión GitHub.

En la pantalla Seleccionar un repositorio, seleccione el repositorio que contiene la aplicación, como la bifurcación de la aplicación de ejemplo.

Es posible que se le pida que vuelva GitHub contraseña como confirmación y, a continuación, GitHub que instale la extensión Azure Pipelines aplicación:

En esta pantalla, desplácese hacia abajo hasta la sección Acceso al repositorio, elija si desea instalar la extensión en todos los repositorios o solo en los seleccionados y, a continuación, seleccione Aprobar e instalar:

En la pantalla Configure your pipeline (Configurar la canalización), seleccione Python to Linux Web App on Azure (Aplicación web de Python a Linux en Azure).
Aparece la nueva canalización. Cuando se le solicite, seleccione la suscripción de Azure en la que creó la aplicación web.
- Selección de la aplicación web
- Seleccione Validar y configurar.
Azure Pipelines crea un archivo azure-pipelines.yml que define la canalización de CI/CD como una serie de fases, trabajos y pasos ,donde cada paso contiene los detalles de las diferentes tareas y scripts. Eche un vistazo a la canalización para ver lo que hace. Asegúrese de que todas las entradas predeterminadas son adecuadas para el código.
Explicación de la canalización de YAML
El archivo YAML contiene los siguientes elementos clave:
En
triggerla parte superior se indican las confirmaciones que desencadenan la canalización, como confirmaciones en lamainrama.que
variablesparametriza la plantilla de YAMLSugerencia
Para evitar codificar de forma rígida valores de variable específicos en el archivo YAML, puede definir variables en la interfaz web de la canalización en su lugar. Para obtener más información, vea Variables: secretos.
El
stages- Compile , que compila el proyecto, y una fase de implementación, que
stagelo implementa en Azure como una aplicación web de Linux. - Implementación
stageque también crea un entorno con el mismo nombre predeterminado que la aplicación web. Puede optar por modificar el nombre del entorno.
- Compile , que compila el proyecto, y una fase de implementación, que
Cada fase tiene un elemento que especifica una o varias máquinas virtuales (VM) en las
poolque la canalización ejecutasteps. De forma predeterminada,poolel elemento contiene solo una entrada para una máquina virtual Ubuntu. Puede usar un grupo para ejecutar pruebas en varios entornos como parte de la compilación, como el uso de diferentes versiones de Python para crear un paquete.El elemento puede contener elementos secundarios como , que ejecuta una tarea específica tal como se define en la referencia de tarea Azure Pipelines y , que ejecuta un conjunto arbitrario
stepstaskdestepsscriptcomandos.La primera tarea de la fase de compilación es UsePythonVersion, que especifica la versión de Python que se va a usar en el agente de compilación. El
@<n>sufijo indica la versión de la tarea. indica@0la versión preliminar. A continuación, tenemos una tarea basada en scripts que crea un entorno virtual e instala las dependencias desde el archivo (requirements.txt).steps: - task: UsePythonVersion@0 inputs: versionSpec: '$(pythonVersion)' displayName: 'Use Python $(pythonVersion)' - script: | python -m venv antenv source antenv/bin/activate python -m pip install --upgrade pip pip install setup pip install -r requirements.txt workingDirectory: $(projectRoot) displayName: "Install requirements"El paso siguiente crea el.zip que implementan los pasos de la fase de implementación de la canalización. Para crear el .zip, agregue una tarea ArchiveFiles al final del archivo YAML:
- task: ArchiveFiles@2 inputs: rootFolderOrFile: '$(Build.SourcesDirectory)' includeRootFolder: false archiveType: 'zip' archiveFile: '$(Build.ArtifactStagingDirectory)/Application$(Build.BuildId).zip' replaceExistingArchive: true verbose: # (no value); this input is optional - publish: $(Build.ArtifactStagingDirectory)/Application$(Build.BuildId).zip displayName: 'Upload package' artifact: dropSe usa
$()en un valor de parámetro para hacer referencia a variables. La variable integrada contiene laBuild.SourcesDirectoryubicación en el agente de compilación donde la canalización clonó el código de la aplicación. ElarchiveFileparámetro indica dóndearchiveFilecolocar el.ziparchivo. En este caso,archiveFileel parámetro usa la variable integradaBuild.ArtifactsStagingDirectory.Importante
Al implementar en Azure App Service, asegúrese de usar
includeRootFolder: false. De lo contrario, el contenido del archivo.zip se coloca en una carpeta denominada s, para "sources", que se replica en el App Service. El App Service en Linux contenedor no puede encontrar el código de la aplicación.A continuación, tenemos la tarea de cargar los artefactos.
En la fase De implementación, se usa la
deploymentpalabra clave para definir un trabajo dedeploymentdestinado a un entorno. Mediante el uso de la plantilla, se crea automáticamente un entorno con el mismo nombre que la aplicación web si aún no existe. Como alternativa, puede crear previamente el entorno y proporcionarenvironmentNameDentro del trabajo de implementación, la primera tarea es UsePythonVersion, que especifica la versión de Python que se va a usar en el agente de compilación.
A continuación, usamos la tarea AzureWebApp para implementar el archivo .zip en el App Service que identificó por las variables y al principio del archivo de canalización. Pegue el código siguiente al final del archivo:
jobs: - deployment: DeploymentJob pool: vmImage: $(vmImageName) environment: $(environmentName) strategy: runOnce: deploy: steps: - task: UsePythonVersion@0 inputs: versionSpec: '$(pythonVersion)' displayName: 'Use Python version' - task: AzureWebApp@1 displayName: 'Deploy Azure Web App : {{ webAppName }}' inputs: azureSubscription: $(azureServiceConnectionId) appName: $(webAppName) package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip # The following parameter is specific to the Flask example code. You may # or may not need a startup command for your app. startUpCommand: 'gunicorn --bind=0.0.0.0 --workers=4 startup:app'El parámetro que se muestra aquí es específico del código de ejemplo
StartupCommandStartupCommandque define la aplicación en el startup.py archivo. De forma predeterminada, Azure App Service busca el objeto de aplicación de Flask en un archivo denominado app.py o application.py. Si el código no sigue este patrón, debe personalizar el comando de inicio. Es posible que las aplicaciones de Django no necesiten personalización. Para obtener más información, vea How to configure Python on Azure App Service - Customize startup command (Cómo configurar Python en Azure App Service: personalización del comando de inicio).Además, dado que el repositorio python-vscode-flask-tutorial contiene el mismo comando de inicio en un archivo denominado startup.txt, podría especificar ese archivo en el parámetro en lugar del comando mediante .
Ejecución de la canalización
Ya está listo para probarlo.
Seleccione Guardar en la esquina superior derecha del editor y, en la ventana emergente, agregue un mensaje de confirmación y seleccione Guardar.
Seleccione Ejecutar en el editor de canalizaciones y seleccione Ejecutar de nuevo en el cuadro de diálogo Ejecutar canalización. Azure Pipelines pone en cola otra ejecución de canalización, adquiere un agente de compilación disponible y hace que el agente de compilación ejecute la canalización.
La canalización tarda unos minutos en completarse, especialmente los pasos de implementación. Debería ver marcas de verificación verdes junto a cada uno de los pasos.
Si se produce un error, puede volver rápidamente al editor de YAML seleccionando los puntos verticales en la esquina superior derecha y seleccionando Editar canalización:

En la página de compilación, seleccione la tarea Aplicación web de Azure para mostrar su salida. Para visitar el sitio implementado, mantenga presionada la tecla Ctrl y seleccione la dirección URL después de App Service url de la aplicación.
Si usa el ejemplo de Flask, la aplicación debe aparecer de la siguiente manera:

Importante
Si se produce un error en la aplicación debido a una dependencia que falta, el archivorequirements.txt no se procesó durante la implementación. Este comportamiento se produce si ha creado la aplicación web directamente en el portal en lugar de usar el comando , como az webapp up se muestra en este artículo.
El az webapp up comando establece específicamente la acción de SCM_DO_BUILD_DURING_DEPLOYMENT compilación en true . Sin embargo, si aprovisionó app service a través del portal, esta acción no se establece automáticamente.
Los pasos siguientes establecen la acción:
- Abra el Azure Portal, seleccione el App Service y, a continuación, seleccione Configuración.
- En la pestaña Application Configuración (Configuración de la aplicación), seleccione New Application Setting (Nueva configuración de aplicación).
- En el menú emergente que aparece, establezca Nombre en , establezca Valor en y seleccione Aceptar.
- Seleccione Guardar en la parte superior de la página Configuración.
- Repetición de la ejecución de la canalización Las dependencias deben instalarse durante la implementación.
Ejecución de un script posterior a la implementación
Por ejemplo, un script posterior a la implementación puede definir variables de entorno esperadas por el código de la aplicación. Agregue el script como parte del código de la aplicación y ejec cándalo mediante el comando de inicio.
Para evitar codificar de forma rígida valores de variable específicos en el archivo YAML, puede definir variables en la interfaz web de la canalización y, a continuación, hacer referencia al nombre de la variable en el script. Para obtener más información, vea Variables: secretos.
Consideraciones sobre Django
Como se indicó anteriormente en este artículo, puede usar Azure Pipelines implementar aplicaciones de Django en Azure App Service en Linux, siempre que use una base de datos independiente. No se puede usar una base de datos sqlite, ya que App Service bloquea el archivo db.sqlite3, lo que impide tanto las lecturas como las escrituras. Este comportamiento no afecta a una base de datos externa.
Como se describe en Configuración de una aplicación de Python en App Service:proceso de inicio del contenedor, App Service busca automáticamente un archivo wsgi.py en el código de la aplicación, que normalmente contiene el objeto de aplicación. Si necesita personalizar el comando de inicio de alguna manera, use el parámetro en el paso del archivo de canalización de YAML, como se describe StartupCommandAzureWebApp@1 en la sección anterior.
Al usar Django, normalmente quiere migrar los modelos de datos mediante manage.py migrate después de implementar el código de la aplicación. Puede agregar con startUpCommand el script posterior a la implementación para este propósito:
startUpCommand: python3.6 manage.py migrate
Ejecución de pruebas en el agente de compilación
Como parte del proceso de compilación, puede que quiera ejecutar pruebas en el código de la aplicación. Las pruebas se ejecutan en el agente de compilación, por lo que es probable que primero tenga que instalar las dependencias en un entorno virtual en el equipo del agente de compilación. Después de ejecutar las pruebas, elimine el entorno virtual antes de crear el .zip para la implementación. Los siguientes elementos de script ilustran este proceso. Colómelos ArchiveFiles@2 antes de la tarea en el archivo ArchiveFiles@2 Para obtener más información, vea Ejecutar scripts multiplataforma.
# The | symbol is a continuation character, indicating a multi-line script.
# A single-line script can immediately follow "- script:".
- script: |
python3.6 -m venv .env
source .env/bin/activate
pip3.6 install setuptools
pip3.6 install -r requirements.txt
# The displayName shows in the pipeline UI when a build runs
displayName: 'Install dependencies on build agent'
- script: |
# Put commands to run tests here
displayName: 'Run tests'
- script: |
echo Deleting .env
deactivate
rm -rf .env
displayName: 'Remove .env before zip'
También puede usar una tarea como PublishTestResults@2 para que los resultados de las pruebas aparezcan en la pantalla de resultados de la canalización. Para más información, consulte Compilación de aplicaciones de Python: ejecución de pruebas.
Aprovisionamiento de App Service con comandos únicos
El comando az webapp up usado anteriormente en este artículo es un método práctico para aprovisionar el App Service e implementar inicialmente la aplicación en un solo paso. Si desea tener más control sobre el proceso de implementación, puede usar comandos únicos para realizar las mismas tareas. Por ejemplo, puede usar un nombre específico para el grupo de recursos o crear un App Service dentro de un plan App Service existente.
Los pasos siguientes realizan el equivalente del az webapp up comando :
Cree un grupo de recursos.
Un grupo de recursos es una colección de recursos de Azure relacionados. La creación de un grupo de recursos facilita la eliminación de todos esos recursos a la vez cuando ya no los necesita. En la Cloud Shell, ejecute el siguiente comando para crear un grupo de recursos en la suscripción de Azure. Establezca una ubicación para el grupo de recursos especificando el valor de
<your-region>. La salida JSON aparece en el Cloud Shell cuando el comando se completa correctamente.az group create -l <your-region> -n <your-resource-group>Cree un App Service plan.
Un App Service se ejecuta dentro de una máquina virtual definida por un App Service plan. Ejecute el siguiente comando para crear una App Service plan, sustituyendo sus propios valores por
<your-resource-group>y<your-appservice-plan>. Es--is-linuxnecesario para las implementaciones de Python. Si desea un plan de precios distinto del plan F1 Gratis predeterminado, use elskuargumento . especifica--sku B1el nivel de proceso de menor precio para la máquina virtual. Puede eliminar fácilmente el plan más adelante mediante la eliminación del grupo de recursos.az appservice plan create -g <your-resource-group> -n <your-appservice-plan> --is-linux --sku B1De nuevo, verá la salida JSON en el Cloud Shell cuando el comando se completa correctamente.
Cree una App Service en el plan.
Ejecute el siguiente comando para crear la App Service en el plan, reemplazando por un nombre único
<your-appservice>en Azure. Normalmente, se usa un nombre personal o de empresa junto con un identificador de aplicación, como<your-name>-flaskpipelines. Se produce un error en el comando si el nombre ya está en uso. Al asignar el App Service al mismo grupo de recursos que el plan, es fácil limpiar todos los recursos a la vez.az webapp create -g <your-resource-group> -p <your-appservice-plan> -n <your-appservice> --runtime "Python|3.6"Nota:
Si desea implementar el código al mismo tiempo que crea el servicio de aplicaciones, puede usar los
--deployment-source-url--deployment-source-branchargumentos y con elaz webapp createcomando . Para más información, consulte az webapp create.Sugerencia
Si ve el mensaje de error "El plan (nombre) no existe" y está seguro de que el nombre del plan es correcto, compruebe que el grupo de recursos especificado con el argumento también es correcto y que el plan que identifica forma parte de ese grupo de
-grecursos. Si se ha escrito incorrectamente el nombre del grupo de recursos, el comando no encuentra el plan en ese grupo de recursos inexistente y genera este error concreto.Si la aplicación requiere un comando de inicio personalizado, use el comando , como se describió anteriormente en Aprovisionamiento del destino
az webapp config setaz webapp config set. Por ejemplo, para personalizar el App Service con el grupo de recursos, el nombre de la aplicación y el comando de inicio, ejecute:az webapp config set -g <your-resource-group> -n <your-appservice> --startup-file <your-startup-command-or-file>La App Service en este momento solo contiene código de aplicación predeterminado. Ahora puede usar Azure Pipelines para implementar el código de aplicación específico.
Limpieza de recursos
Para evitar incurrir en cargos continuos por los recursos de Azure que creó en este tutorial, como un plan App Service B1, elimine el grupo de recursos que contiene el App Service y el plan App Service. Para eliminar el grupo de recursos de la Azure Portal, seleccione Grupos de recursos en el panel de navegación izquierdo. En la lista de grupos de recursos, seleccione ... a la derecha del grupo de recursos que desea eliminar, seleccione Eliminargrupo de recursos y siga las indicaciones.
También puede usar az group delete en el Cloud Shell para eliminar grupos de recursos.
Para eliminar la cuenta de almacenamiento que mantiene el sistema de archivos para Cloud Shell, lo que conlleva un pequeño cargo mensual, elimine el grupo de recursos que comienza por cloud-shell-storage-.