Abrir un container shell (SSH) y ejecutar comandos en Azure App Service

App Service proporciona acceso autenticado a contenedores de aplicaciones en ejecución para la resolución de problemas y tareas administrativas. Trata el acceso a contenedores como una operación privilegiada y concede acceso solo a usuarios que lo necesiten.

El servicio de aplicaciones proporciona acceso SSH basado en navegador a aplicaciones alojadas en contenedores personalizados de Windows. No se requiere ninguna configuración especial de imagen para la sesión del navegador.

El comando CLI de Azure az webapp exec solo es compatible con aplicaciones web de Linux. No use los ejemplos de la CLI de Linux en este artículo para planes de Aplicación de Windows Service.

Para contenedores Linux integrados y personalizados, el terminal de navegador más reciente y az webapp exec usan Kudu como proxy autenticado para conectarse al contenedor en ejecución. Estas opciones no requieren que instales un servidor SSH, incrustes una contraseña SSH, expongas un puerto SSH o inicies un daemon SSH en tu imagen personalizada. El WebSSH de Kudu heredado y el acceso az webapp ssh podrían seguir requiriendo un servidor SSH en una imagen personalizada.

Use el portal de Azure para una sesión de navegador, o bien el comando de vista previa az webapp exec para una sesión local de terminal o la ejecución en segundo plano de comandos. El terminal de navegador requiere /bin/bash en la imagen y actualmente no permite seleccionar otro shell. Si la imagen tiene un shell diferente, use az webapp exec --shell /bin/sh en su lugar. Las imágenes sin shell, incluidas las imágenes distroless, no pueden abrir una sesión interactiva.

Prerequisites

  • Para los ejemplos de CLI, instala CLI de Azure 2.90.0 o posterior e inicia sesión. Compruebe su versión con az version. También puedes usar Azure Cloud Shell si su CLI cumple este requisito.
  • Para una sesión interactiva de CLI, usa un terminal interactivo y una shell que exista en tu imagen. El valor por defecto es /bin/bash; para una imagen sin bash, especificar --shell /bin/sh si ese shell está disponible.

Abrir sesión SSH en el explorador

Tu aplicación y su contenedor deben estar funcionando antes de abrir una sesión del navegador.

En el portal de Azure, abre tu app de App Service. En Herramientas de Desarrollo, seleccione SSH y luego seleccione Ir. Inicia sesión con tu cuenta de Azure si te lo piden.

La sesión se abre en tu navegador, donde puedes ejecutar comandos dentro del contenedor de la app.

Conexión SSH

Abrir una sesión de SSH con la CLI de Azure

El comando de vista previa az webapp exec abre una shell interactiva en el contenedor principal de tu app. La sesión usa tu terminal local en Windows, macOS y Linux; no abre un navegador.

az webapp exec --resource-group <resource-group-name> --name <app-name>

Para una imagen que usa /bin/sh en lugar de bash:

az webapp exec --resource-group <resource-group-name> --name <app-name> --shell /bin/sh

Puedes ejecutar comandos e inspeccionar su salida en esta sesión. Por ejemplo, usa top si está instalado en la imagen. Para inspeccionar el contenedor SCM/Kudu en lugar del contenedor de la app:

az webapp exec --resource-group <resource-group-name> --name <app-name> --target kudu

La app y los contenedores de Kudu son entornos diferentes. Ejecuta comandos que dependan del entorno de ejecución, las dependencias o la conectividad de red de tu app en el contenedor de la app.

Seleccione una instancia o una ranura de despliegue

Por defecto, la CLI se conecta a una instancia de la app. Para encontrar los IDs de las instancias:

az webapp list-instances --resource-group <resource-group-name> --name <app-name> --output table

Para conectar con una instancia específica:

az webapp exec --resource-group <resource-group-name> --name <app-name> --instance <instance-id>

Añade --slot <slot-name> para acceder a un slot de implementación. Al seleccionar la instancia de una ranura, añade también --slot a az webapp list-instances.

El modo shell interactivo solo soporta una instancia a la vez.

Ejecutar comandos sin una sesión interactiva

Usa --mode execute para enviar un comando al contenedor principal de la app sin abrir una sesión de terminal. El comando se ejecuta en segundo plano. Este modo es útil para diagnósticos en segundo plano u otros trabajos que no requieren salida inmediata.

Importante

El modo de ejecución es fire-and-forget. Un resultado con estado accepted solo confirma que la solicitud fue aceptada, no que el comando se ejecutó, completó o tuvo éxito. La CLI no devuelve la salida estándar del comando remoto, ni el error estándar ni el código de salida. Un envío fallido produce un error de CLI, pero una invocación exitosa de CLI no es prueba de una ejecución remota exitosa. Utiliza una shell interactiva cuando necesites observar el resultado de inmediato.

Ejecuta un programa directamente

Use --command para especificar un programa y sus argumentos. Pon entre comillas todo el comando:

az webapp exec --resource-group <resource-group-name> --name <app-name> --mode execute --command "python3 /home/site/wwwroot/scripts/diagnostics.py" --working-directory /home/site/wwwroot --instance <instance-id>

Sustituye la ruta del script por un script desplegado en tu app. El ejecutable y sus dependencias deben existir en el contenedor.

--command no interpreta operadores de shell como >, |, o &&. Use --shell-command en su lugar cuando necesite un shell. Estas dos opciones son mutuamente excluyentes.

Capturar la salida y comprobar la finalización

En el siguiente ejemplo se utilizan comillas del cliente Bash, como en Cloud Shell. Envía un comando diagnóstico de solo lectura a una instancia y registra por separado su salida y su estado de salida. Sustituye <run-id> por un nuevo identificador para cada invocación y <instance-id> por un ID de az webapp list-instances.

az webapp exec --resource-group <resource-group-name> --name <app-name> \
  --mode execute --instance <instance-id> --shell /bin/sh \
  --shell-command 'uname -a > /home/LogFiles/diagnostics-<run-id>.log 2>&1; result=$?; printf "%s\n" "$result" > /home/LogFiles/diagnostics-<run-id>.exit'

Asegúrate de que existan /bin/sh y el comando de diagnóstico, y de que /home/LogFiles exista y tenga permisos de escritura. La persistencia de /home en contenedores personalizados depende de la configuración de almacenamiento de la app. Las comillas simples evitan que el shell del cliente expanda $? y $result antes de que la solicitud llegue al contenedor.

Tras la entrega, abre un shell interactivo de la aplicación en la misma instancia e inspecciona los archivos:

cat /home/LogFiles/diagnostics-<run-id>.log
cat /home/LogFiles/diagnostics-<run-id>.exit

Un estado de salida registrado de 0 indica que el comando de diagnóstico tuvo éxito. Un estado distinto de cero indica fallo; inspecciona el registro. Si el archivo de estado no existe, no se ha establecido la finalización: el comando puede seguir en ejecución, puede que no haya comenzado o que se haya interrumpido. No infieras éxito a partir de la aceptación ni de la presencia de un registro parcial. Usa un identificador de ejecución nuevo para que un archivo de estado antiguo no pueda confundirse con el resultado actual.

La CLI no proporciona una API para sondear la finalización. Redirigir la salida a un archivo no la pone automáticamente a disposición en la transmisión de registros de App Service.

Para migraciones de bases de datos u otras operaciones que cambian el estado compartido, selecciona una instancia, comprueba la finalización por separado y no vuelvas a ejecutar la operación solo porque el envío no ha devuelto salida. Mantén el flujo de trabajo interactivo cuando necesites verificar el éxito antes de continuar.

Ejecutar comandos independientes en múltiples instancias

El modo de ejecución también acepta una lista separada por comas de IDs de instancia o --instance all. Las solicitudes para múltiples instancias se envían en paralelo. Por ejemplo, ejecuta un script de diagnóstico desplegado por instancia en cada instancia:

az webapp exec --resource-group <resource-group-name> --name <app-name> --mode execute --command "python3 /home/site/wwwroot/scripts/diagnostics.py" --instance all

El script debe capturar sus propios resultados. Utiliza rutas de salida distintas por instancia y por ejecución si el almacenamiento es compartido. No la utilices all para migraciones de bases de datos compartidas u otras operaciones que solo deban ejecutarse una vez. Si algunos envíos fallan, la CLI informa de un error aunque otras instancias podrían haber aceptado el comando.

Agregue --slot <slot-name> para ejecutar en una ranura de implementación.

Limitations

  • El modo de ejecución se aplica solo al contenedor principal de la aplicación. Solo puedes usar --target kudu en modo shell interactivo.
  • Usa --working-directory o --cwd solo en modo de ejecución, y proporciona una ruta absoluta.
  • Proporciona una ruta absoluta para --shell. En modo ejecutar, solo puedes usarlo con --shell-command.
  • Esta vista previa no ofrece transferencia de archivos, reenvío de puertos ni opción para seleccionar contenedores laterales arbitrarios. Use métodos de implementación compatibles para cargar archivos.
  • La ejecución en segundo plano no es un planificador de trabajos duradero. Un reinicio o reemplazo del contenedor puede interrumpir el trabajo. No asuma los reintentos automáticos ni la ejecución exactamente una vez.

Control del acceso SSH

Desactiva el acceso SSH en las apps que no lo necesiten configurando la propiedad de configuración de la app sshEnabled en false. Los siguientes ejemplos utilizan entrecomillado JSON de Bash:

az webapp config set --resource-group <resource-group-name> --name <app-name> \
  --generic-configurations '{"sshEnabled": false}'

Para habilitar el acceso a SSH de nuevo:

az webapp config set --resource-group <resource-group-name> --name <app-name> \
  --generic-configurations '{"sshEnabled": true}'

Para inspeccionar la configuración:

az webapp config show --resource-group <resource-group-name> --name <app-name> --query sshEnabled

Añade --slot <slot-name> para configurar o inspeccionar una ranura de despliegue.

Para la gobernanza entre aplicaciones y ranuras, usa las directivas integradas las aplicaciones de App Service deben deshabilitar SSH y las ranuras de aplicaciones de App Service deben deshabilitar SSH. Consulta la referencia de política de App Service para enlaces de asignación.

Ambas políticas tienen como valor predeterminado Audit y también admiten Deny y Disabled. Evalúan un valor sshEnabled ausente o no falso como no conforme. La auditoría informa de incumplimiento; no desactiva SSH. Denegar evita cambios de recursos no conformes; no reconfigura automáticamente las aplicaciones existentes. Puedes asignar políticas en el ámbito de suscripción o de grupo de administración, incluido el grupo de administración raíz del tenant para la gobernanza en todo el tenant.

La configuración y el cumplimiento de políticas SSH no sustituyen la protección del acceso a SCM/Kudu. Utiliza los permisos RBAC apropiados y las restricciones de acceso a la red.

Solucionar problemas de acceso a contenedores

  • Confirma que la aplicación ha arrancado correctamente. Revisa los registros de diagnóstico para detectar fallos de arranque.
  • Para acceder a la CLI, comprueba la versión de la CLI, la aplicación seleccionada, la ranura y la instancia, y si existe el ejecutable o el shell solicitado.
  • Comprueba la autorización y la conectividad de red al endpoint SCM. No necesitas activar la autenticación básica de publicación; la CLI soporta la autenticación Microsoft Entra cuando la autenticación básica SCM está desactivada. Consulta Desactivar la autenticación básica.
  • Los cambios que haces dentro del contenedor no sustituyen actualizar y volver a desplegar la app o la imagen. Los reinicios del contenedor pueden eliminar archivos fuera del almacenamiento persistente.