Поделиться через


Обзор JavaScript в приложениях контейнеров Azure

Приложения контейнеров Azure могут запускать любое контейнерное приложение JavaScript в облаке, предоставляя гибкие варианты развертывания приложений.

Конфигурация

Приложения контейнеров Azure позволяют упростить развертывание приложений JavaScript с помощью эффективной контейнеризации, включая настройку переменных среды, проектирование эффективных файлов Dockerfile и организацию процесса сборки приложения.

Переменные среды

Переменные среды важны для настройки приложения. .env Используйте файл для локального управления этими переменными и обеспечить безопасное управление ими в рабочей среде с помощью службы, такой как Azure Key Vault.

В следующем примере показано, как создать переменные для приложения.

# .env
NODE_ENV=production
PORT=3000
AZURE_COSMOS_DB_ENDPOINT=https://<YOUR_COSMOSDB_RESOURCE_NAME>.documents.azure.com:443/

Контейнеры

Хорошо настроенный Файл Dockerfile необходим для контейнеризации приложения:

  • Используйте базовый Файл Dockerfile: если несколько проектов совместно используют общую настройку, можно создать базовый Файл Dockerfile, включающий эти общие шаги. Файл Dockerfile каждого проекта может начинаться с FROM этого базового образа и добавлять конфигурации, специфичные для данного проекта.

  • Параметризация аргументов сборки: вы можете использовать аргументы сборки (ARG) в Dockerfile, чтобы сделать его более гибким. Таким образом, вы можете использовать различные значения этих аргументов при настройке для разработки, промежуточной или продуктивной среды.

  • Оптимизированный Node.js базовый образ: убедитесь, что вы используете соответствующий базовый образNode.js. Рассмотрите возможность использования небольших оптимизированных изображений, таких как варианты Alpine, чтобы сократить затраты.

  • Минимальные файлы — копировать только основные компоненты: сосредоточьтесь на копировании только необходимых файлов в контейнер. Создайте файл .dockerignore, чтобы гарантировать, что файлы разработки не копируются в такие места, как .env и node_modules. Этот файл помогает ускорить сборку в случаях, когда разработчики добавляют ненужные файлы.

  • Разделите сборку и среду выполнения с многоэтапными сборками: Используйте многоэтапные сборки для создания оптимизированного окончательного образа, разделив среду сборки от среды выполнения.

  • Предварительная сборка артефактов путем компиляции и бандеролирования: предварительная сборка артефактов вашего приложения (например, компиляция TypeScript или бандеролирование JavaScript) перед копированием их на стадию выполнения может свести к минимуму размер образа, ускорить развертывание контейнера и повысить производительность холодного запуска. Тщательное упорядочивание инструкций в Dockerfile также оптимизирует кэширование и время перестроения.

  • Docker Compose для сред разработки: Docker Compose позволяет определять и запускать многоконтейнерные приложения Docker. Этот подход с несколькими контейнерами полезен для настройки сред разработки. Контекст сборки и Dockerfile можно включить в файл Compose. Этот уровень инкапсуляции позволяет использовать различные файлы Dockerfile для разных служб при необходимости.

Базовый Dockerfile

Этот файл служит общей отправной точкой для изображений Node.js. Можно использовать его с директивой FROM в Dockerfiles, которые ссылаются на этот базовый образ. Используйте номер версии или коммит для поддержки новой и безопасной версии образа.

# Dockerfile.base

FROM node:22-alpine

# Set the working directory
WORKDIR /usr/src/app

# Define build arguments with default values
ARG PORT_DEFAULT=3000
ARG ENABLE_DEBUG_DEFAULT=false

# Set environment variables using the build arguments
ENV PORT=${PORT_DEFAULT}
ENV ENABLE_DEBUG=${ENABLE_DEBUG_DEFAULT}

# Copy package manifests and install dependencies
COPY package*.json ./
RUN npm install

# Expose the application and debugging ports
EXPOSE $PORT
EXPOSE 9229

# This image focuses on common steps; project-specific Dockerfiles can extend this.

При передаче значений с помощью флага --build-arg во время процесса сборки, переданные значения переопределяют жестко закодированные значения по умолчанию в Dockerfile.

Рассмотрим пример.

docker build \
  --build-arg PORT_DEFAULT=4000 \
  --build-arg ENABLE_DEBUG_DEFAULT=true \
  --tag <IMAGE>:<TAG> \
  --file Dockerfile.base .

В этом примере переменные PORT среды и ENABLE_DEBUG задаются явными значениями вместо значений по умолчанию.

Практики маркировки изображений контейнера, такие как использование latest, представляют собой установленный стандарт. Дополнительные сведения о рекомендациях по тегированию и версионированию образов контейнеров.

Настройка среды разработки с помощью Docker Compose

В следующем примере конфигурации используется специальный файл Docker для разработки (Dockerfile.dev) вместе с подключениями томов для живой перезагрузки и локальной синхронизации исходного кода.

version: "3.8"
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.base
      args:
        PORT_DEFAULT: ${PORT:-3000}
        ENABLE_DEBUG_DEFAULT: ${ENABLE_DEBUG:-false}
    ports:
      - "${PORT:-3000}:3000"
      - "9229:9229"  # Expose debug port if needed
    volumes:
      - .:/usr/src/app
      - /usr/src/app/node_modules
    environment:
      - NODE_ENV=development
      - PORT=${PORT:-3000}
      - ENABLE_DEBUG=${ENABLE_DEBUG:-false}

Чтобы запустить Docker Compose с пользовательскими значениями, можно экспортировать переменные среды в командной строке. Рассмотрим пример.

PORT=4000 ENABLE_DEBUG=true docker compose up

Рабочий файл Dockerfile

Этот многоэтапный Dockerfile создает приложение и генерирует оптимизированный образ среды выполнения. Убедитесь, что файл .dockerignore уже присутствует в исходном коде, чтобы команда COPY . . не копировала файлы, специфичные для среды разработки, которые не нужны в рабочей среде.

# Stage 1: Builder
FROM node:22 AS build

WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .

# Build your project (e.g., compile TypeScript or bundle JavaScript)
RUN npm run build

# Stage 2: Runtime
FROM my-base-image:latest AS runtime

WORKDIR /usr/src/app

# Copy only the compiled output and essential files from the build stage
COPY --from=build /usr/src/app/dist ./dist
COPY --from=build /usr/src/app/package*.json ./

# Install only production dependencies
RUN npm ci --omit=dev

# Copy the entrypoint script for remote debugging
COPY entrypoint.sh /usr/src/app/entrypoint.sh
RUN chmod +x /usr/src/app/entrypoint.sh

# Expose the application port (using the PORT environment variable) and the debug port (9229)
EXPOSE $PORT
EXPOSE 9229

# Use the entrypoint script to conditionally enable debugging
ENTRYPOINT ["sh", "/usr/src/app/entrypoint.sh"]

Скрипт точки входа позволяет подключаться к приложению-контейнеру для удаленной отладки.

Чтобы запустить контейнер из созданного рабочего образа с настраиваемыми переменными среды, выполните следующую команду:

docker run \
  --env PORT=4000 \
  --env ENABLE_DEBUG=true \
  --publish 4000:4000 \
  --publish 9229:9229 \
  <IMAGE>:<TAG>

Для рабочих сборок убедитесь, что вы используете правильный тег версии, который может не быть latest. Соглашения о маркировке изображений контейнера, такие как использование latest, являются соглашениями. Узнайте больше о рекомендациях по тегированию и версионированию образов контейнеров.

Развертывание

Чтобы поддерживать непрерывную интеграцию и непрерывное развертывание (CI/CD), настройте конвейер CI/CD с помощью GitHub Actions, Azure DevOps или другого средства CI/CD для автоматизации процесса развертывания.

# .github/workflows/deploy.yml
name: Deploy to Azure

on:
push:
    branches:
    - main

jobs:
build-and-deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4

    - name: Set up Node.js
      uses: actions/setup-node@v4
      with:
          node-version: '22'

    - name: Install dependencies
      run: npm ci

    - name: Build the app
      run: npm run build

    - name: Log in to Azure
      uses: azure/login@v2
      with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}

    - name: Deploy to Azure Container Apps
      run: |
          az containerapp up \
          --name my-container-app \
          --resource-group my-resource-group \
          --image my-image:my_tag \
          --environment my-environment \
          --cpu 1 --memory 2Gi \
          --env-vars NODE_ENV=production PORT=3000

При использовании Реестра Docker войдите в реестр, а затем отправьте образы Docker в реестр контейнеров, например Реестр контейнеров Azure (ACR) или Docker Hub.

# Tag the image
docker tag \
  <IMAGE>:<TAG> \
  <AZURE_REGISTRY>.azurecr.io/<IMAGE>:<TAG>

# Push the image
docker push <AZURE_REGISTRY>.azurecr.io/<IMAGE>:<TAG>

Холодные запуски

Оптимизируйте рабочую сборку, включив только необходимый код и зависимости. Чтобы убедиться, что полезная нагрузка оптимально сокращена, используйте один из следующих подходов:

  • Многоэтапные сборки или пакеты Docker: используйте средства сборки и объединяющие инструменты, такие как Webpack или Rollup, чтобы помочь вам создать наименьший объем данных для контейнера. При компиляции и упаковке только того, что необходимо в производственной среде, вы помогаете свести к минимуму размер контейнера и улучшить время холодного запуска.

  • Тщательно управляйте зависимостями:node_modules Держите папку минимальной, включая только пакеты, необходимые для работы в производственной среде. Не перечисляйте зависимости разработки или тестирования в dependencies разделе вашего приложения package.json. Удалите все неиспользуемые зависимости и убедитесь, что package.json и файл блокировки остаются согласованными.

Безопасность

Вопросы безопасности для разработчиков JavaScript, использующих приложения контейнеров Azure, включают защиту переменных среды (например, с помощью Azure Key Vault), обеспечение httpS с правильным управлением сертификатами, обслуживание up-toзависимостей даты с регулярными аудитами, а также внедрение надежного ведения журнала и мониторинга для быстрого обнаружения и реагирования на угрозы.

Безопасные переменные среды

Убедитесь, что конфиденциальные сведения, такие как строки подключения к базе данных и ключи API, хранятся безопасно. Используйте Azure Key Vault для безопасного управления секретами и переменными среды.

Перед выполнением этой команды обязательно замените заполнители, окруженные <>, на ваши значения.

az keyvault secret set \
  --vault-name <KEY_VAULT_APP> \
  --name "<SECRET_NAME>" \
  --value "<CONNECTION_STRING>"

HTTPS и сертификаты

Убедитесь, что приложение обслуживается по протоколу HTTPS. Приложения контейнеров Azure могут управлять сертификатами для вас. Настройте личный домен и сертификат на портале Azure.

Управление зависимостями

Регулярно обновляйте зависимости, чтобы избежать уязвимостей системы безопасности. Используйте такие средства, как npm audit, чтобы проверить наличие уязвимостей.

npm audit

Обработка ошибок

Реализуйте надежную обработку ошибок в приложении Node.js. Используйте ПО промежуточного слоя в Express или Fastify, чтобы корректно обрабатывать ошибки.

// src/middleware/errorHandler.ts
import { Request, Response, NextFunction } from 'express';

export function errorHandler(err: any, req: Request, res: Response, next: NextFunction) {
  console.error(err.stack);
  res.status(500).send('Something broke!');
}

Грациозное завершение работы

Правильное завершение работы приложения имеет решающее значение, чтобы убедиться, что запросы, находящиеся в обработке, завершены, а ресурсы освобождаются правильно. Это помогает предотвратить потерю данных и поддерживать гладкое взаимодействие с пользователем во время развертываний или событий масштабирования. В следующем примере демонстрируется один подход с помощью Node.js и Express для обработки сигналов завершения работы корректно.

import express from 'express';
import healthRouter from './health.js';

const app = express();

app.use(healthRouter);

const server = app.listen(process.env.PORT || 3000);

// Graceful shutdown
process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down...');
  server.close(() => {
    console.log('Server closed');
    process.exit(0);
  });

  // Force close after 30s
  setTimeout(() => {
    console.error('Could not close connections in time, forcing shutdown');
    process.exit(1);
  }, 30000);
});

Лесозаготовка

В приложениях контейнеров Azure автоматически фиксируются и регистрируются вызовы console.log и console.error. Приложения контейнеров Azure фиксируют стандартные выходные () и стандартные потоки ошибок (stdoutstderr) из приложения и делают их доступными в Azure Monitor и Log Analytics.

Настройка ведения журнала в приложениях контейнеров Azure

Чтобы убедиться, что журналы правильно записаны и доступны, необходимо настроить параметры диагностики для приложения контейнера Azure. Настройка — это двухэтапный процесс.

  1. Включение параметров диагностики. Используйте Azure CLI для включения параметров диагностики для приложения контейнера Azure.

    Перед выполнением этой команды обязательно замените заполнители, окруженные <>, на ваши значения.

    az monitor diagnostic-settings create \
    --resource /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.Web/containerApps/<CONTAINER_APP_NAME> \
    --name "containerapp-logs" \
    --workspace <LOG_ANALYTICS_WORKSPACE_ID> \
    --logs '[{"category": "ContainerAppConsoleLogs","enabled": true}]'
    
  2. Получите доступ к журналам на портале, перейдя в рабочую область Log Analytics и выполнив запрос журналов.

Использование библиотек ведения журнала

Хотя console.log и console.error автоматически собираются, использование журнальной библиотеки, такой как Winston, обеспечивает большую гибкость и контроль над логированием. Эта гибкость позволяет отформатировать журналы, задать уровни журналов и выходные журналы для нескольких назначений, таких как файлы или внешние службы ведения журнала.

В следующем примере показано, как настроить Winston для хранения журналов высокой точности.

// src/logger.ts
import { createLogger, transports, format } from 'winston';

const logger = createLogger({
  level: 'info',
  format: format.combine(
    format.timestamp(),
    format.json()
  ),
  transports: [
    new transports.Console(),
    new transports.File({ filename: 'app.log' })
  ]
});

export default logger;

Чтобы использовать средство ведения журнала, используйте следующий синтаксис в приложении:

import logger from './logger';

logger.info('This is an info message');
logger.error('This is an error message');

Удаленная отладка

Чтобы включить удаленную отладку, можно использовать встроенный инспектор узла. Вместо жесткого кодирования параметров отладки в вашем Dockerfile CMD вы можете динамически включить удаленную отладку, используя скрипт оболочки в качестве точки входа вашего контейнера.

Следующий сценарий проверяет переменную среды (например, ENABLE_DEBUGпри запуске контейнера). Если для переменной задано значение true, скрипт запускает Node.js в режиме отладки (с помощью --inspect или --inspect-brk). В противном случае контейнер запускает приложение обычно.

Вы можете реализовать удаленную отладку, выполнив следующие действия.

  1. Создайте скрипт точки входа в файле с именем entrypoint.sh в корне проекта со следующим содержимым:

    #!/bin/sh
    # If ENABLE_DEBUG is set to "true", start Node with debugging enabled
    if [ "$ENABLE_DEBUG" = "true" ]; then
      echo "Debug mode enabled: starting Node with inspector"
      exec node --inspect=0.0.0.0:9229 dist/index.js
    else
      echo "Starting Node without debug mode"
      exec node dist/index.js
    fi
    
  2. Измените Dockerfile, чтобы скопировать entrypoint.sh скрипт в контейнер и задать его в качестве точки входа. Кроме того, при необходимости предоставляют порт отладки:

    # Copy the entrypoint script to the container
    COPY entrypoint.sh /usr/src/app/entrypoint.sh
    
    # Ensure the script is executable
    RUN chmod +x /usr/src/app/entrypoint.sh
    
    # Expose the debugging port (if using debug mode)
    EXPOSE 9229
    
    # Set the shell script as the container’s entrypoint
    ENTRYPOINT ["sh", "/usr/src/app/entrypoint.sh"]
    
  3. Активируйте режим отладки, установив для переменной ENABLE_DEBUG среды значение true. Например, с помощью Azure CLI:

    az containerapp update \
      --name <CONTAINER_APP> \
      --env-vars ENABLE_DEBUG=true
    

Перед выполнением этой команды обязательно замените шаблоны, окруженные <>, на ваши значения.

Этот подход предлагает гибкое решение, позволяющее перезапустить контейнер в режиме отладки, обновив переменную среды при запуске. Это позволяет избежать необходимости создавать новую редакцию с разными CMD параметрами при каждом отладке приложения.

Рекомендации по обслуживанию и производительности

Для поддержания и оптимизации производительности приложения с течением времени убедитесь, что вы эффективно управляете изменениями переменных среды, отслеживаете ресурсы, храните зависимости up-to-date, настраиваете масштабирование правильно и настраиваете оповещения мониторинга.

Изменения переменной среды

Так как для каждого изменения переменных среды требуется новая версия развертывания, внесите все изменения в секреты приложения разом. По завершении изменений свяжите секреты с переменными среды ревизии. Этот подход сводит к минимуму количество исправлений и помогает поддерживать чистый журнал развертывания.

Распределение ресурсов

Отслеживайте и настраивайте выделение ЦП и памяти для контейнеров на основе шаблонов производительности и использования приложения. Чрезмерное предоставление ресурсов может привести к ненужным затратам, в то время как недостаточное предоставление ресурсов может вызвать проблемы с производительностью.

Обновления зависимостей

Регулярно обновляйте зависимости, чтобы воспользоваться улучшениями производительности и исправлениями безопасности. Используйте такие средства, как npm-check-updates, чтобы автоматизировать этот процесс.

npm install -g npm-check-updates
ncu -u
npm install

Масштабирование

Настройте автомасштабирование на основе нагрузки приложения. Приложения контейнеров Azure поддерживают горизонтальное масштабирование, которое автоматически настраивает количество экземпляров контейнеров на основе использования ЦП или памяти.

В следующем примере показано, как задать правило масштабирования на основе ЦП. Перед выполнением этой команды обязательно замените заполнители, окруженные тегами <>, на ваши значения.

az containerapp revision set-scale \
  --name <CONTAINER_APP> \
  --resource-group <RESOURCE_GROUP> \
  --min-replicas 1 \
  --max-replicas 10 \
  --cpu 80

Оповещения мониторинга

Настройте мониторинг и оповещения для отслеживания производительности и работоспособности приложения. Используйте Azure Monitor для создания оповещений для определенных метрик, таких как использование ЦП, использование памяти и время отклика.

Перед выполнением этой команды обязательно замените заполнители, окруженные <>, на ваши значения.

az monitor metrics alert create \
  --name "HighCPUUsage" \
  --resource-group <RESOURCE_GROUP> \
  --scopes /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.ContainerInstance/containerGroups/<CONTAINER_GROUP> \
  --condition "avg Percentage CPU > 80" \
  --description "Alert when CPU usage is above 80%"

Управление ресурсами

Используйте расширение "Приложения контейнеров Azure " для Visual Studio Code для быстрого создания, редактирования и развертывания контейнерных приложений непосредственно из Visual Studio Code.

Устранение неполадок

При возникновении проблем во время выполнения в приложениях контейнеров Azure можно использовать ведение журнала, удаленную отладку и оповещения проверки работоспособности для поиска и устранения проблемы.

Лесозаготовка

Включите и настройте ведение журнала для записи журналов приложений. Используйте Azure Monitor и Log Analytics для сбора и анализа журналов. Перед запуском этих команд убедитесь, что заменили заполнители, окруженные тегами <>, на ваши значения.

  1. Создайте новую рабочую область.

    az monitor log-analytics workspace create \
        --resource-group <RESOURCE_GROUP> \
        --workspace-name <WORKSPACE_NAME>
    
  2. Затем создайте новый параметр рабочей области.

    az monitor diagnostic-settings create \
        --resource <CONTAINER_APP> \
        --workspace <WORKSPACE_NAME> \
        --logs '[{"category": "ContainerAppConsoleLogs","enabled": true}]'
    

Отладка

Средства удаленной отладки используются для подключения к работающему контейнеру. Убедитесь, что Dockerfile предоставляет необходимые порты для отладки.

# Expose the debugging port
EXPOSE 9229

Медицинские проверки

Настройте проверки работоспособности для мониторинга работоспособности приложения. Эта функция гарантирует, что приложения контейнеров Azure могут перезапустить контейнер, если он не отвечает.

# Azure Container Apps YAML configuration
properties:
configuration:
    livenessProbe:
    httpGet:
        path: /health
        port: 3000
    initialDelaySeconds: 30
    periodSeconds: 10