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

Os aplicativos Node.js precisam 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 automaticamente quando você implanta um Repositório do Git ou quando implanta um Pacote zip com a automação de compilação 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 é corrigido e atualizado regularmente pela plataforma, não recomendamos que você especifique uma determinada versão secundária/patch, já que não há garantia de que estejam disponíveis devido aos 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 Git ou usando pacotes zip com a automação de compilação habilitada, o Serviço de Aplicativo do Azure criará etapas de automação por meio da seguinte sequência:

  1. Se for especificado por PRE_BUILD_SCRIPT_PATH, execute um script personalizado.
  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 e se especificado, os scripts chamados prebuild e postbuild serão executados antes e depois do build, respectivamente. 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 usa as duas variáveis para especificar 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 informações sobre variáveis de ambiente adicionais e personalizar a automação de compilação, 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 seu aplicativo para iniciar com o PM2, com o npm start 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 com o npm start Uso somente de desenvolvimento.
Executar com um 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 do 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 com um 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 com o npm start

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

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. Selecione Sim para habilitar a depuração remota para o seu 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 do Git ou da implantação por Zip com a automação de compilação habilitada. 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 seu 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 do seu aplicativo precisar verificar se as solicitações do usuário estão criptografadas, 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.

Regravações de URL

Ao implantar aplicativos Node.js no Serviço de Aplicativo do Azure para Linux, talvez você precise rescrever a URL diretamente dentro do seu aplicativo. Isso é particularmente útil para garantir que padrões de URL específicos sejam redirecionados para os pontos de extremidade corretos sem depender das configurações do servidor Web. Há várias maneiras de realizar regravações de URL no Node.js. Um exemplo é por meio do pacote express-urlrewrite.

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 Application Insights, vá para o aplicativo web no portal, selecione Application Insights em Configurações e, a seguir, selecione Ativar o Application Insights. Em seguida, selecione um recurso do Application Insights existente ou crie um novo. Por fim, selecione Aplicar na parte inferior. Para instrumentar seu aplicativo web usando o PowerShell, confira essas 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 seu package.json, diferentes pacotes podem ser instalados para o modo de produção (dependencies x devDependencies).
    • Determinadas estruturas da web talvez implantem arquivos estáticos de maneira diferente no modo de produção.
    • Determinadas estruturas da web podem usar scripts de inicialização personalizados ao serem executadas no modo de produção.
  • Execute o aplicativo no modo de desenvolvimento do Serviço de Aplicativo. Por exemplo, em MEAN.js, você pode configurar seu 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

Após implantar seu código Node.js em um aplicativo nativo do Windows no Serviço de Aplicativo, você verá a mensagem You do not have permission to view this directory or page no navegador quando navegar para a URL do seu aplicativo. Isso provavelmente ocorre porque você não tem um arquivo web.config. (Confira 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ê usar a Implantação por ZIP (por meio do Visual Studio Code, por exemplo), certifique-se de habilitar a automação de compilação. Ela não vem 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