Configurar um aplicativo Node.js para o Serviço de Aplicativo do Azure

Os aplicativos Node.js devem ser implantados com todas as dependências de NPM necessárias. O mecanismo de implantação do Serviço de Aplicativo executa npm install --production de maneira automática quando você implanta um npm install --production ou um pacote Zipcom a automação de build habilitada. No entanto, se você implantar os arquivos usando FTP/S, será necessário carregar os pacotes necessários manualmente.

Este guia fornece conceitos e instruções essenciais para desenvolvedores Node.js que implantam no Serviço de Aplicativo. Se você nunca usou o Serviço de Aplicativo do Azure, siga o Início rápido do Node.js e o Tutorial de Node.js com MongoDB primeiro.

Exibir a versão do Node.js

Para mostrar a versão atual do Node.js, execute o seguinte comando no Cloud Shell:

az webapp config appsettings list --name <app-name> --resource-group <resource-group-name> --query "[?name=='WEBSITE_NODE_DEFAULT_VERSION'].value"

Para mostrar todas as versões compatíveis do Node.js, acesse https://<sitename>.scm.azurewebsites.net/api/diagnostics/runtime ou execute o seguinte comando no https://<sitename>.scm.azurewebsites.net/api/diagnostics/runtime:

az webapp list-runtimes --os windows | grep NODE

Para mostrar a versão atual do Node.js, execute o seguinte comando no Cloud Shell:

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

Para mostrar todas as versões compatíveis do Node.js, execute o seguinte comando no Cloud Shell:

az webapp list-runtimes --os linux | grep NODE

Definir a versão do Node.js

Para definir o aplicativo para uma versão do Node.js com suporte, execute o seguinte comando no Cloud Shell para definir WEBSITE_NODE_DEFAULT_VERSION como uma versão com suporte:

az webapp config appsettings set --name <app-name> --resource-group <resource-group-name> --settings WEBSITE_NODE_DEFAULT_VERSION="~16"

Observação

Este exemplo usa a "sintaxe de til" recomendada para direcionar a versão mais recente disponível do runtime do Node.js 16 no Serviço de Aplicativo.

Como o runtime é regularmente corrigido e atualizado pela plataforma, não é recomendável direcioná-lo a um patch/versão secundária específica, pois não há garantia de que eles estejam disponíveis devido a possíveis riscos de segurança.

Observação

Você deve definir a versão do Node.js no projeto package.json. O mecanismo de implantação é executado em um processo separado que contém todas as versões do Node.js com suporte.

Para definir o aplicativo para uma versão do Node.js com suporte, execute o seguinte comando no Cloud Shell:

az webapp config set --resource-group <resource-group-name> --name <app-name> --linux-fx-version "NODE|14-lts"

Essa configuração especifica a versão do Node.js a ser usada, no runtime e durante a restauração automatizada de pacote no Kudu.

Observação

Você deve definir a versão do Node.js no projeto package.json. O mecanismo de implantação é executado em um contêiner separado que contém todas as versões do Node.js com suporte.

Obter o número da porta

O aplicativo Node.js precisa escutar a porta certa para receber solicitações de entrada.

No Serviço de Aplicativo do Windows, os aplicativos Node.js são hospedados com IISNode e o aplicativo Node.js deve escutar a porta especificada na variável process.env.PORT. O exemplo a seguir mostra como fazer isso em um aplicativo Express simples:

O Serviço de Aplicativo define a variável de ambiente PORT no contêiner Node.js e encaminha as solicitações de entrada para o contêiner nesse número de porta. Para receber as solicitações, o aplicativo deve escutar essa porta usando process.env.PORT. O exemplo a seguir mostra como fazer isso em um aplicativo Express simples:

const express = require('express')
const app = express()
const port = process.env.PORT || 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

Personalizar a automação de build

Se você implantar seu aplicativo usando o Git ou pacotes zip com a automação de compilação habilitada, as etapas de automação de compilação do Serviço de Aplicativo terão a seguinte sequência:

  1. Executar script personalizado se especificado por PRE_BUILD_SCRIPT_PATH.
  2. Execute npm install sem nenhum sinalizador, o que inclui os scripts preinstall e postinstall do npm e também devDependencies das instalações.
  3. Execute npm run build se um script de compilação for especificado no npm run build.
  4. Execute npm run build:azure se um script build:azure for especificado no npm run build:azure.
  5. Executar script personalizado se especificado por POST_BUILD_SCRIPT_PATH.

Observação

Conforme descrito nos documentos do npm, os scripts chamados prebuild e postbuild executados antes e depois de build, respectivamente, se especificados. preinstall e postinstall executados antes e depois install, respectivamente.

PRE_BUILD_COMMAND e POST_BUILD_COMMAND são variáveis de ambiente vazias por padrão. Para executar comandos pré-build, defina PRE_BUILD_COMMAND. Para executar comandos pós-build, defina POST_BUILD_COMMAND.

O exemplo a seguir especifica as duas variáveis para uma série de comandos, separados por vírgulas.

az webapp config appsettings set --name <app-name> --resource-group <resource-group-name> --settings PRE_BUILD_COMMAND="echo foo, scripts/prebuild.sh"
az webapp config appsettings set --name <app-name> --resource-group <resource-group-name> --settings POST_BUILD_COMMAND="echo foo, scripts/postbuild.sh"

Para obter variáveis de ambiente adicionais para personalizar a automação de build, confira Configuração do Oryx.

Para obter mais informações sobre como o Serviço de Aplicativo executa e compila aplicativos Node.js no Linux, veja a Documentação do Oryx: Como os aplicativos Node.js são detectados e compilados.

Configurar o servidor Node.js

Os contêineres Node.js vêm com PM2, um gerente de processo de produção. Você pode configurar o aplicativo para iniciar com o PM2, com o NPM ou com um comando personalizado.

Ferramenta Finalidade
Executar com o PM2 Recomendado – Uso em produção ou em preparo. O PM2 fornece uma plataforma de gerenciamento de aplicativo de serviço completo.
Executar a inicialização do npm Uso somente de desenvolvimento.
Executar o comando personalizado Desenvolvimento ou preparo.

Executar com o PM2

O contêiner inicia automaticamente o aplicativo com o PM2 quando um dos arquivos Node.js comuns for encontrado no projeto:

  • bin/www
  • server.js
  • app.js
  • index.js
  • hostingstart.js
  • Um dos seguintes arquivos PM2: process.json e ecosystem.config.js

Você também pode configurar um arquivo de inicialização personalizado com as seguintes extensões:

  • Um arquivo .js
  • Um arquivo PM2 com a extensão .json, .config.js, .yaml ou .yml

Observação

No Node 14 LTS e em versões posteriores, o contêiner não inicia automaticamente seu aplicativo com PM2. Para iniciar seu aplicativo com PM2, defina o comando de inicialização como pm2 start <.js-file-or-PM2-file> --no-daemon. Você deve usar o argumento --no-daemon, porque PM2 precisa ser executado em primeiro plano para que o contêiner funcione corretamente.

Para adicionar um arquivo de inicialização personalizado, execute o seguinte comando no Cloud Shell:

az webapp config set --resource-group <resource-group-name> --name <app-name> --startup-file "<filename-with-extension>"

Executar o comando personalizado

O Serviço de Aplicativo pode iniciar o aplicativo usando um comando personalizado, como um executável como run.sh. Por exemplo, para executar npm run start:prod, execute o seguinte comando no Cloud Shell:

az webapp config set --resource-group <resource-group-name> --name <app-name> --startup-file "npm run start:prod"

Executar a inicialização do npm

Para iniciar o aplicativo usando npm start, apenas verifique se um script start está no arquivo npm start. Por exemplo:

{
  ...
  "scripts": {
    "start": "gulp",
    ...
  },
  ...
}

Para usar um package.json personalizado no projeto, execute o seguinte comando no Cloud Shell:

az webapp config set --resource-group <resource-group-name> --name <app-name> --startup-file "<filename>.json"

Depurar remotamente

Observação

No momento, a depuração remota está em Versão Prévia Visualização.

Você poderá depurar o aplicativo Node.js remotamente no Visual Studio Code se for configurado para ser executado com o PM2, exceto quando for executado usando um .config.js,.yml ou .yaml.

Na maioria dos casos, nenhuma configuração adicional é necessária para o aplicativo. Se o aplicativo for executado com um arquivo process.json (padrão ou personalizado), ele deverá ter uma propriedade script na raiz JSON. Por exemplo:

{
  "name"        : "worker",
  "script"      : "./index.js",
  ...
}

Para configurar o Visual Studio Code para a depuração remota, instale a extensão do Serviço de Aplicativo. Siga as instruções na página de extensão e entre no Azure do Visual Studio Code.

No Azure Explorer, localize o aplicativo que você deseja depurar, clique nele com o botão direito do mouse e selecione Iniciar Depuração Remota. Clique em Sim para habilitá-la para o aplicativo. O Serviço de Aplicativo inicia um proxy de túnel para você e anexa o depurador. Em seguida, você pode fazer solicitações para o aplicativo e ver o depurador pausando em pontos de interrupção.

Depois de concluir a depuração, pare o depurador selecionando Desconectar. Quando solicitado, você deve clicar em Sim para desabilitar a depuração remota. Para desabilitá-la mais tarde, clique com o botão direito do mouse no aplicativo novamente no Azure Explorer e selecione Desabilitar Depuração Remota.

Acessar variáveis de ambiente

No Serviço de Aplicativo, você pode definir configurações de aplicativo fora do código do aplicativo. Em seguida, você pode acessá-las usando o modelo Node.js padrão. Por exemplo, para acessar uma configuração de aplicativo chamada NODE_ENV, use o seguinte código:

process.env.NODE_ENV

Executar Grunt/Bower/Gulp

Por padrão, a automação de compilação do Serviço de Aplicativo executa npm install --production quando reconhece que um aplicativo Node.js foi implantado por meio da implantação do Git ou do Zip npm install --production. Se o aplicativo exigir qualquer uma das ferramentas de automação populares, como Grunt, Bower ou Gulp, você precisará fornecer um script de implantação personalizado para executá-lo.

Para habilitar o repositório de modo a executar essas ferramentas, você precisa adicioná-las às dependências no package.json. Por exemplo:

"dependencies": {
  "bower": "^1.7.9",
  "grunt": "^1.0.1",
  "gulp": "^3.9.1",
  ...
}

Em uma janela de terminal local, altere o diretório para a raiz do repositório e execute os seguintes comandos:

npm install kuduscript -g
kuduscript --node --scriptType bash --suppressPrompt

A raiz do repositório agora tem dois arquivos adicionais: .deployment e deploy.sh.

Abra o deploy.sh e localize a seção Deployment, que é semelhante a esta:

##################################################################################################################################
# Deployment
# ----------

Esta seção termina com a execução de npm install --production. Adicione a seção de código de que você precisa para executar a ferramenta necessária no final da seção Deployment:

Veja um exemplo no MEAN.js de amostra, em que o script de implantação também executa um comando npm install personalizado.

Bower

Esse snippet de código executa bower install.

if [ -e "$DEPLOYMENT_TARGET/bower.json" ]; then
  cd "$DEPLOYMENT_TARGET"
  eval ./node_modules/.bin/bower install
  exitWithMessageOnError "bower failed"
  cd - > /dev/null
fi

Gulp

Esse snippet de código executa gulp imagemin.

if [ -e "$DEPLOYMENT_TARGET/gulpfile.js" ]; then
  cd "$DEPLOYMENT_TARGET"
  eval ./node_modules/.bin/gulp imagemin
  exitWithMessageOnError "gulp failed"
  cd - > /dev/null
fi

Grunt

Esse snippet de código executa grunt.

if [ -e "$DEPLOYMENT_TARGET/Gruntfile.js" ]; then
  cd "$DEPLOYMENT_TARGET"
  eval ./node_modules/.bin/grunt
  exitWithMessageOnError "Grunt failed"
  cd - > /dev/null
fi

Detectar sessão HTTPS

No Serviço de Aplicativo, a terminação TLS/SSL ocorre nos balanceadores de carga de rede, de modo que todas as solicitações HTTPS chegam ao seu aplicativo como solicitações HTTP não criptografadas. Se a lógica de aplicativo precisar verificar se as solicitações do usuário estão criptografadas ou não, inspecione o cabeçalho X-Forwarded-Proto.

Estrutura Web populares permitem que você acesse informações do X-Forwarded-* no seu padrão de aplicativo básico. No Express, você pode usar proxies de confiança. Por exemplo:

app.set('trust proxy', 1)
...
if (req.secure) {
  // Do something when HTTPS is used
}

Acessar logs de diagnóstico

Para acessar os logs de console gerados dentro do código do aplicativo no Serviço de Aplicativo, ative o log de diagnóstico executando o seguinte comando no Cloud Shell:

az webapp log config --resource-group <resource-group-name> --name <app-name> --docker-container-logging filesystem --level Verbose

Os valores possíveis para --level são Error, Warning, Info e Verbose. Cada nível seguinte inclui o anterior. Por exemplo: Error inclui apenas mensagens de erro e Verbose inclui todas as mensagens.

Depois que o log de diagnósticos estiver ativado, execute o seguinte comando para ver o fluxo de logs:

az webapp log tail --resource-group <resource-group-name> --name <app-name>

Se você não vir os logs do console imediatamente, verifique novamente após 30 segundos.

Observação

Você também pode inspecionar os arquivos de log do navegador em https://<app-name>.scm.azurewebsites.net/api/logs/docker.

Para interromper o streaming de log a qualquer momento, digite Ctrl+C.

Você pode acessar os logs do console gerados de dentro do contêiner.

Primeiro, ative o log do contêiner executando o seguinte comando:

az webapp log config --name <app-name> --resource-group <resource-group-name> --docker-container-logging filesystem

Substitua <app-name> e <resource-group-name> pelos nomes apropriados para seu aplicativo Web.

Depois que o log do contêiner estiver ativado, execute o seguinte comando para ver o fluxo de log:

az webapp log tail --name <app-name> --resource-group <resource-group-name>

Se você não vir os logs do console imediatamente, verifique novamente após 30 segundos.

Para interromper o streaming de log a qualquer momento, digite Ctrl+C.

Você também pode inspecionar os arquivos de log em um navegador em https://<app-name>.scm.azurewebsites.net/api/logs/docker.

Monitorar com Application Insights

O Application Insights permite monitorar o desempenho, as exceções e o uso do aplicativo sem fazer nenhuma alteração de código. Para anexar o agente do App Insights, acesse o aplicativo Web no portal, selecione Application Insights em Configurações e, em seguida, selecione Ativar o Application Insights. Em seguida, selecione um recurso do App Insights existente ou crie um novo. Por fim, selecione Aplicar na parte inferior. Para instrumentar o aplicativo Web usando o PowerShell, veja estas instruções

Esse agente monitorará o aplicativo Node.js no lado do servidor. Para monitorar o JavaScript do lado do cliente, adicione o SDK do JavaScript ao projeto.

Para obter mais informações, veja as notas sobre a versão da extensão do Application Insights.

Solução de problemas

Quando um aplicativo Node.js que esteja funcionando se comportar de maneira diferente no Serviço de Aplicativo ou tiver erros, tente o seguinte:

  • Acessar o fluxo de log.
  • Teste o aplicativo localmente no modo de produção. O Serviço de Aplicativo executa seus aplicativos do Node.js no modo de produção, portanto, verifique se seu projeto funciona como esperado localmente no modo de produção. Por exemplo:
    • Dependendo do package.json, diferentes pacotes podem ser instalados para o modo de produção (dependencies em comparação a devDependencies).
    • Determinadas estruturas da Web podem implantar arquivos estáticos de maneira diferente no modo de produção.
    • Determinadas estruturas da Web podem usar scripts de inicialização personalizados ao serem executados no modo de produção.
  • Execute o aplicativo no modo de desenvolvimento do Serviço de Aplicativo. Por exemplo, em MEAN.js, você pode definir o aplicativo para o modo de desenvolvimento no runtime definindo a configuração NODE_ENV do aplicativo.

Você não tem permissão para visualizar este diretório ou página

Depois de implantar o código Node.js em um aplicativo nativo do Windows no Serviço de Aplicativo do Azure, você verá a mensagem You do not have permission to view this directory or page. no navegador ao navegar até a URL do aplicativo. Isso acontece provavelmente porque você não tem um arquivo web.config (consulte o modelo e um exemplo).

Se você implantar os arquivos usando o Git ou usando a implantação de ZIP com a automação de compilação habilitada, o mecanismo de implantação gerará um web.config na raiz de Web do aplicativo (%HOME%\site\wwwroot) automaticamente se uma das seguintes condições for verdadeira:

  • A raiz do projeto tem um package.json que define um script start que contém o caminho de um arquivo JavaScript.
  • A raiz do projeto tem um server.js ou um app.js.

O web.config gerado é adaptado para o script de início detectado. Em outros métodos de implantação, adicione esse web.config manualmente. Verifique se o arquivo está formatado corretamente.

Se você usa a implantação de ZIP (por meio de Visual Studio Code, por exemplo), certifique-se de habilitar a automação de compilação porque ela não está habilitada por padrão. az webapp up usa a implantação ZIP com a automação de compilação habilitada.

robots933456 em logs

Você poderá ver a seguinte mensagem nos logs de contêiner:

2019-04-08T14:07:56.641002476Z "-" - - [08/Apr/2019:14:07:56 +0000] "GET /robots933456.txt HTTP/1.1" 404 415 "-" "-"

Você pode ignorar essa mensagem com segurança. /robots933456.txt é um caminho de URL fictício que o Serviço de Aplicativo usa para verificar se o contêiner é capaz de atender a solicitações. Uma resposta 404 indica apenas que o caminho não existe, mas informa ao Serviço de Aplicativo que o contêiner está íntegro e pronto para responder a solicitações.

Próximas etapas

Ou, veja recursos adicionais:

Referência de variáveis de ambiente e configurações de aplicativo