Bir uygulamayı Heroku'dan Azure Container Apps'e geçirme

Bu makalede, heroku uygulamasını Azure Container Apps'e geçirme adımları gösterilmektedir. Heroku yapılandırmanızı dışarı aktarır, uygulamanızı dağıtır, veri hizmetlerini geçirir, CI/CD'yi ayarlar ve özel etki alanlarını yapılandırırsınız.

Heroku-Azure kavram eşlemesi, hizmet eşdeğerleri ve yaygın tuzaklara kavramsal genel bakış için bkz. Heroku'dan Azure Container Apps'e geçişe genel bakış.

Öğrenme hedefleri

Bu makalede şunları öğreneceksiniz:

  • Heroku uygulama yapılandırmasını dışarı aktarma ve Azure Container Apps'e dağıtma
  • PostgreSQL ve Redis verilerini Azure yönetilen hizmetlerine geçirme
  • GitHub Actions ile CI/CD işlem hattı yapılandırma
  • Yönetilen TLS sertifikaları ile özel alan adları kurulumu
  • Geçirilen uygulamanız için otomatik ölçeklendirme kurallarını yapılandırma

Önkoşullar

  • Etkin aboneliği olan Azure hesabı. Ücretsiz bir tane oluşturun.

  • Container Apps uzantısının yüklü olduğu Azure CLI (sürüm 2.53.0 veya üzeri).

    az extension add --name containerapp --upgrade
    az provider register --namespace Microsoft.App
    
  • Heroku CLI yüklü ve kimliği doğrulanmış (yapılandırmayı ve verileri dışarı aktarmak için kullanılır).

  • Docker (isteğe bağlı - yalnızca görüntüleri yerel olarak derlediyseniz gereklidir).

  • Uygulamanızın bir Git deposundaki kaynak kodu.

  • Bilgi: Heroku uygulama yönetimi, temel Azure CLI komutları ve kapsayıcı kavramları.

1 - Heroku yapılandırmanızı dışarı aktarma

Heroku uygulamanızın yapılandırma değişkenlerini dışarı aktararak başlayın. Azure'da ortam değişkenlerini ayarlarken başvuru olarak bu dosyayı kullanın.

heroku config -a <HEROKU_APP_NAME> --json > heroku-config.json

Uyarı

Heroku uygulama adınızla <HEROKU_APP_NAME> öğesini değiştirin. Bu makalede köşeli ayraçlardaki (< >) değerleri kendi değerlerinizle değiştirin.

2 - Azure kaynakları oluşturma

Bu yordam boyunca kullanılan kabuk değişkenlerini tanımlayın. Ardından bir kaynak grubu ve Container Apps ortamı oluşturun.

# Define variables used throughout this migration.
# Replace the placeholder values with your own.
RESOURCE_GROUP="<RESOURCE_GROUP>"
LOCATION="eastus"
ENVIRONMENT="<ENVIRONMENT_NAME>"
APP_NAME="<APP_NAME>"

Gerekli kaynak sağlayıcılarını kaydedin. Kaynak grubunu ve ortamı oluşturun.

# Register resource providers (required once per subscription)
az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights

# Create a resource group to hold all migration resources
az group create \
  --name $RESOURCE_GROUP \
  --location $LOCATION

# Create a Container Apps environment, which automatically
# provisions a Log Analytics workspace for logging
az containerapp env create \
  --name $ENVIRONMENT \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION

Uyarı

Ortam oluşturma otomatik olarak bir Log Analytics çalışma alanı sağlar. Bu adım bir ile iki dakika arasında sürebilir.

Doğrulama: Ortamın çalıştığını onaylayın.

az containerapp env show \
  --name $ENVIRONMENT \
  --resource-group $RESOURCE_GROUP \
  --query "properties.provisioningState" -o tsv

Çıktıda Succeeded görüntülenmelidir.

3 - Uygulamanızı dağıtma

Uygulamanızın kurulumuna göre aşağıdaki dağıtım seçeneklerinden birini seçin.

Seçenek A: Kaynaktan dağıtma (Dockerfile gerekmez)

Bu komut, Heroku git push deneyimine benzer şekilde dilinizi, derlemenizi ve dağıtmanızı otomatik olarak algılamak için Buluta Özel Derleme Paketleri'ni kullanır.

az containerapp up \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --environment $ENVIRONMENT \
  --source . \
  --ingress external \
  --target-port 3000

Uyarı

Container Apps Cloud Build özelliği --source bayrağını kullanır ve bu, tüm bölgelerde veya tüm dil yığınlarında kullanılabilir olmayabilir. Başarısız olursa, bunun yerine B Seçeneğini kullanın.

Uygulamanızın Dockerfile'ı yoksa bir Dockerfile oluşturun. Aşağıdaki örnekte üretim bağımlılıklarını yükleyen, uygulama kodunu kopyalayan ve sunucuyu başlatan en düşük Node.js Dockerfile gösterilmektedir.

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Azure Container Registry (ACR) aracılığıyla görüntüyü derleyin ve Container Apps'e dağıtın. Bu dizi bir kayıt defteri oluşturur, görüntüyü bulutta oluşturur, kayıt defterini Container Apps'e kaydeder ve kapsayıcı uygulamasını yeni görüntüyü kullanacak şekilde güncelleştirir.

# Create an Azure Container Registry
az acr create \
  --name <REGISTRY_NAME> \
  --resource-group $RESOURCE_GROUP \
  --sku Basic \
  --admin-enabled true

# Build the image in ACR (no local Docker required)
az acr build \
  --registry <REGISTRY_NAME> \
  --image $APP_NAME:v1 .

# Retrieve the ACR password for registry authentication
ACR_PASSWORD=$(az acr credential show \
  --name <REGISTRY_NAME> \
  --query "passwords[0].value" -o tsv)

# Register ACR with the container app
az containerapp registry set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --server <REGISTRY_NAME>.azurecr.io \
  --username <REGISTRY_NAME> \
  --password $ACR_PASSWORD

# Deploy the image to the container app
az containerapp update \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --image <REGISTRY_NAME>.azurecr.io/$APP_NAME:v1

Tavsiye

az acr build Docker görüntüsünü bulutta oluşturur. Docker'ın yerel olarak yüklenmesi gerekmez. Bu yaklaşım en güvenilir dağıtım yoludur.

Doğrulama: Kapsayıcı uygulamasının çalıştığını onaylayın.

az containerapp show \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --query "properties.runningStatus" -o tsv

4 - Ortam değişkenlerini ayarlama

Container Apps, bağlantı dizeleri ve API anahtarları gibi hassas değerler için gizli diziler kullanır. Ortam değişkenlerinde bunları kullanmadan önce gizli bilgileri ayarlamanız gerekir.

Önemli

Ortam değişkenleri olarak kullanmadan önce gizli anahtarları ayarlayın. Sıra önemlidir; henüz var olmayan bir gizliye atıfta bulunmak hataya neden olur.

Aşağıdaki komutlar Container Apps'te gizli diziler oluşturur ve ardından bu gizli dizilere başvuran ortam değişkenlerini ayarlar. Gizli bilgileri tek başına güncellemek uygulamayı yeniden başlatmaz; az containerapp update komut yeni değerleri alan yeni bir revizyon oluşturur.

# Set secrets (connection strings, API keys)
az containerapp secret set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --secrets "redis-url=<AZURE_REDIS_CONNECTION_STRING>" \
            "api-key=<YOUR_API_KEY>"

# Set environment variables that reference the secrets
az containerapp update \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --set-env-vars "REDIS_URL=secretref:redis-url" \
                 "API_KEY=secretref:api-key"

Tavsiye

Çevre değişkenlerinin toplu geçişine yönelik olarak heroku-config.json'i az containerapp update komutlarına dönüştürmek için bir betik kullanın.

5 - Dağıtımı doğrulama

Uygulama URL'sini alın, ardından uygulamanızı bir tarayıcıda veya kullanarak curltest edin. Başlangıç hatalarını izlemek için günlük akışını kullanın.

# Get the app URL
az containerapp show \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --query "properties.configuration.ingress.fqdn" -o tsv

# Stream live console logs to check for errors
az containerapp logs show \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --type console \
  --follow

6 - Veri hizmetlerini geçirme

PostgreSQL'i geçirme

Aşağıdaki dizi, Heroku Postgres'ten bir yedekleme dışarı aktarır, PostgreSQL için Azure Veritabanı Esnek Sunucusu oluşturur, verileri geri yükler ve kapsayıcı uygulamanızdaki bağlantı dizesini güncelleştirir.

# Export a backup from Heroku Postgres
heroku pg:backups:capture -a <HEROKU_APP_NAME>
heroku pg:backups:download -a <HEROKU_APP_NAME>

PostgreSQL için Azure Veritabanı Esnek Sunucusunu ve veritabanını oluşturun.

# Create the PostgreSQL Flexible Server instance
az postgres flexible-server create \
  --resource-group $RESOURCE_GROUP \
  --name <PG_SERVER_NAME> \
  --location $LOCATION \
  --admin-user <ADMIN_USER> \
  --admin-password '<STRONG_PASSWORD>' \
  --sku-name Standard_B1ms \
  --tier Burstable

# Create the application database
az postgres flexible-server db create \
  --resource-group $RESOURCE_GROUP \
  --server-name <PG_SERVER_NAME> \
  --database-name <DATABASE_NAME>

Heroku yedeklemesini yeni Azure veritabanına geri yükleyin ve bağlantı dizesini güncelleştirin.

# Restore the Heroku backup to Azure PostgreSQL
pg_restore \
  --host=<PG_SERVER_NAME>.postgres.database.azure.com \
  --port=5432 \
  --username=<ADMIN_USER> \
  --dbname=<DATABASE_NAME> \
  --no-owner --no-acl \
  latest.dump

# Update the Container App with the new connection string
az containerapp secret set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --secrets "database-url=postgresql://<ADMIN_USER>:<PASSWORD>@<PG_SERVER_NAME>.postgres.database.azure.com:5432/<DATABASE_NAME>?sslmode=require"

Doğrulama: Azure veritabanına bağlanın ve tablolarınızın ve satır sayılarınızın Heroku kaynağıyla eşleşip eşleşmedığını onaylayın.

Redis'i Geçirme

Redis için Azure Cache örneği oluşturun ve kapsayıcı uygulamanıza bağlayın. Aşağıdaki komutlar önbelleği hazırlar, erişim anahtarını alır ve bağlantı dizesini gizli dizi olarak ayarlar.

# Create Azure Cache for Redis (provisioning takes 10–20 minutes)
az redis create \
  --resource-group $RESOURCE_GROUP \
  --name <REDIS_NAME> \
  --location $LOCATION \
  --sku Basic \
  --vm-size c0

# Retrieve the primary access key
az redis list-keys \
  --resource-group $RESOURCE_GROUP \
  --name <REDIS_NAME> \
  --query "primaryKey" -o tsv

# Store the connection string as a Container App secret
az containerapp secret set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --secrets "redis-url=rediss://:<ACCESS_KEY>@<REDIS_NAME>.redis.cache.windows.net:6380"

# Set the environment variable referencing the secret
az containerapp update \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --set-env-vars "REDIS_URL=secretref:redis-url"

Uyarı

Redis için Azure Cache sağlama 10-20 dakika sürebilir. Redis genellikle önbellek olarak kullanılır, bu nedenle birincil veri deposu olarak kullanmadığınız sürece geçirilecek veri yoktur. Uygulamanızı yeni örneğe yöneltin.

Doğrulama: Güncelleştirmeden sonra uygulamanızın sistem durumu uç noktasını veya günlüklerini denetleyerek Redis bağlantısını onaylayın.

Diğer eklentiler

Diğer Heroku eklentileri için, geçişe genel bakış bölümünde Hizmet eşdeğerleri tablosuna bakın.

Her eklenti için: Azure eşdeğer hizmetini sağlayın, Container App ortam değişkenlerinizdeki bağlantı ayrıntılarını güncelleştirin, tümleştirmeyi doğrulayın ve ardından Heroku eklentisini kaldırın.

7 - CI/CD'yi ayarlama

GitHub İşlemleri

Docker görüntünüzü oluşturup, ACR'ye gönderip, ardından Container Apps'e dağıtan ve her main dalına yapılan gönderimde çalışan bir GitHub Actions iş akışı oluşturun. Aşağıdaki dosyayı deponuza .github/workflows/deploy.yml olarak kaydedin.

Bu iş akışı aşağıdaki adımları uygular:

  1. Kaynak kodunuzu inceler.
  2. GitHub'da gizli bilgi olarak depolanan bir hizmet temsilcisini kullanarak Azure'da oturum açar.
  3. Git işleme SHA'sı ile etiketlenmiş bir Docker görüntüsünü oluşturup Azure Container Registry'ye (ACR) gönderir.
  4. Kapsayıcı uygulamasını yeni görüntüyü kullanacak şekilde güncelleştirir ve bu da yeni bir düzeltmeyi tetikler.
name: Deploy to Azure Container Apps

on:
  push:
    branches: [main]

# Environment variables shared across all jobs.
# Update these values to match your Azure resource names.
env:
  AZURE_CONTAINER_REGISTRY: <REGISTRY_NAME>.azurecr.io
  IMAGE_NAME: <APP_NAME>
  RESOURCE_GROUP: <RESOURCE_GROUP>
  CONTAINER_APP_NAME: <APP_NAME>

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      # Check out the repository source code
      - uses: actions/checkout@v4

      # Authenticate to Azure using the service principal credentials
      - uses: azure/login@v2
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}

      # Build the Docker image and push it to ACR
      - name: Build and push image
        run: |
          az acr login --name <REGISTRY_NAME>
          docker build -t ${{ env.AZURE_CONTAINER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} .
          docker push ${{ env.AZURE_CONTAINER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

      # Deploy the new image to the container app
      - name: Deploy to Container Apps
        run: |
          az containerapp update \
            --name ${{ env.CONTAINER_APP_NAME }} \
            --resource-group ${{ env.RESOURCE_GROUP }} \
            --image ${{ env.AZURE_CONTAINER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

Hizmet sorumlusunu oluşturun: Erişim kapsamı kaynak grubunuzla Contributor belirlenmiş bir hizmet sorumlusu oluşturmak için aşağıdaki komutu çalıştırın. JSON çıkışını AZURE_CREDENTIALS GitHub depo ayarlarınızda gizli anahtar olarak depolayın.

az ad sp create-for-rbac \
  --name "github-deploy" \
  --role contributor \
  --scopes /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/$RESOURCE_GROUP \
  --json-auth

Azure DevOps

Azure DevOps işlem hattınızda Azure Container Apps Dağıtma görevini kullanın. İş akışı benzerdir: görüntüyü derleyin, ACR'ye gönderin ve kapsayıcı uygulamasını güncelleştirin.

8 - Özel etki alanlarını ve TLS'yi yapılandırma

Aşağıdaki komutlar kapsayıcı uygulamanıza özel bir etki alanı ekler, DNS doğrulama kayıtlarını alır ve ücretsiz bir yönetilen TLS sertifikası bağlar. 2. ve 4. adımlar arasında etki alanı sağlayıcınıza DNS kayıtları eklemeniz gerekir.

# Add your custom domain to the container app
az containerapp hostname add \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --hostname <YOUR_DOMAIN>

# List hostnames to get the required DNS verification records
az containerapp hostname list \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  -o table

DNS sağlayıcınıza aşağıdaki kayıtları ekleyin:

  • TXT kaydı: Etki alanı doğrulaması için (önceki komut çıkışında gösterilen değer).
  • CNAME kaydı: <YOUR_DOMAIN> adresini <APP_NAME>.<REGION>.azurecontainerapps.io adresine yönlendirin.

DNS yayma işleminin ardından yönetilen sertifikayı bağlayın.

# Bind a free managed TLS certificate (auto-renews)
az containerapp hostname bind \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --hostname <YOUR_DOMAIN> \
  --environment $ENVIRONMENT \
  --validation-method CNAME

Doğrulama: Sertifikanın bağlı olduğunu onaylayın.

az containerapp hostname list \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  -o table

Yönetilen sertifikalar, Heroku'nun Otomatik Sertifika Yönetimi ile eşdeğer olan ücretsiz ve otomatik olarak yenilenir.

9 - Ölçeklendirmeyi yapılandırma

Heroku'nun el ile dyno ölçeklendirmesini değiştirmek için otomatik ölçeklendirme kuralları ayarlayın. Aşağıdaki komut, eşzamanlı istek yüküne göre 0 ile 10 çoğaltma arasında ölçeklendirilen HTTP tabanlı otomatik ölçeklendirmeyi yapılandırırken, tek bir örnek 50 eşzamanlı isteği aştığında yeni bir çoğaltma eklenir.

az containerapp update \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --min-replicas 0 \
  --max-replicas 10 \
  --scale-rule-name http-rule \
  --scale-rule-type http \
  --scale-rule-http-concurrency 50

İşçi süreçleri için, kuyruk tabanlı ölçeklendirme ile ayrı bir kapsayıcı uygulaması dağıtın. Aşağıdaki komut, Bir Azure Depolama kuyruğundaki iletilerin sayısına göre 0 ile 5 çoğaltma arasında ölçeklendirilen bir çalışan kapsayıcı uygulaması oluşturur.

az containerapp create \
  --name <APP_NAME>-worker \
  --resource-group $RESOURCE_GROUP \
  --environment $ENVIRONMENT \
  --image <REGISTRY_NAME>.azurecr.io/<APP_NAME>-worker:latest \
  --min-replicas 0 \
  --max-replicas 5 \
  --scale-rule-name queue-rule \
  --scale-rule-type azure-queue \
  --scale-rule-metadata "queueName=jobs" "queueLength=10" \
  --scale-rule-auth "connection=queue-connection-string"

Tavsiye

Hemen yanıt vermesi gereken üretim uygulamaları için ayarını yapın --min-replicas 1. Geliştirme ve hazırlama ortamlarında, ölçeği sıfıra indirmenin avantajlarından yararlanmak ve boşta kalma maliyetlerini ortadan kaldırmak için --min-replicas 0 kullanın.

Sorun giderme

Sorun Nedeni Çözüm
Uygulama dağıtımdan sonra HTTP isteklerine yanıt vermiyor Container Apps, uygulamanızın PORT ortam değişkeni tarafından belirtilen (varsayılan 80) bağlantı noktasını dinlemesini bekler. Uygulamanız farklı bir bağlantı noktasında dinliyor olabilir. Kapsayıcı uygulamanızı oluştururken veya güncelleştirirken --target-port noktasını, uygulamanızın dinlediği bağlantı noktası olarak ayarlayın.
az containerapp up --source oluşturucu hatalarıyla başarısız oluyor Bulut Derlemesi tüm bölgelerde veya tüm dil yığınlarında kullanılamaz. Dockerfile tabanlı yaklaşımı kullanın: az acr build imajını oluşturun ve dağıtın. Bkz . B Seçeneği: Dockerfile ile dağıtma.
Gizli bilgilere başvuran ortam değişkenleri boştur. Çevre değişkenlerinde referans göstermeden önce gizli bilgiler mevcut olmalıdır. önce komutunu çalıştırın az containerapp secret set , ardından az containerapp update env değişkenlerini ayarlayın. Bkz. 4. Adım.
Azure hizmeti sağlama işlemi beklenenden uzun sürüyor Azure yönetilen hizmetlerinin sağlama süreleri Heroku eklentilerinden daha uzun olur. Redis için Azure Cache: 10-20 dakika. PostgreSQL Esnek Sunucusu: 5-10 dakika. Uygulamanızı dağıtırken hizmetleri paralel olarak sağlayın.
Çalışma zamanında yazılan dosyalar yeniden başlatıldıktan sonra kaybolur Container Apps, Heroku'ya benzer kısa ömürlü bir dosya sistemi kullanır. Kalıcı depolama için bir Azure Dosyalar paylaşımı bağlayın.

Kaynakları temizle

Bu geçiş kılavuzu için özel olarak kaynaklar oluşturduysanız, ilişkili tüm kaynakları kaldırmak ve ücretlendirmeyi durdurmak için kaynak grubunu silin.

az group delete --name $RESOURCE_GROUP --yes --no-wait

Dikkat

Bu komut kaynak grubunu ve veritabanları, kapsayıcı kayıt defterleri ve kapsayıcı uygulamaları dahil olmak üzere içindeki tüm kaynakları siler. Bu eylem geri alınamaz.