Deployment Implementations: Containers, Scripts & Databases
Implement application deployments using containers, binaries, and scripts. Handle database deployment tasks and use Azure App Configuration Feature Manager for feature flags.
From Strategy to Implementation
Think of recipes vs actual cooking.
The previous module was the recipe book β βuse blue-green deployment, apply canary strategy.β This module is the actual cooking β βhere is how you build the Docker image, push it to the registry, and deploy the container. Here is how you run the database migration without breaking the live app.β
Knowing the strategy is half the battle. Implementing it correctly β with the right pipeline tasks, deployment methods, and database safety patterns β is where exam questions get specific.
Container Deployment Pipeline
The standard container deployment pipeline follows a build-push-deploy pattern:
Build and Push to ACR
# Azure Pipelines
- task: Docker@2
inputs:
containerRegistry: 'myACRConnection'
repository: 'claims-api'
command: 'buildAndPush'
Dockerfile: '**/Dockerfile'
tags: |
$(Build.BuildId)
latest
Best practices:
- Tag images with the build ID (immutable) AND
latest(convenience) - Use multi-stage Dockerfiles β build stage with SDK, runtime stage with minimal image
- Scan images before pushing β use Microsoft Defender for Containers or Trivy
- Never store secrets in Docker images β use environment variables or Azure Key Vault references at runtime
Deploy to Azure Container Instances (ACI)
For simple container workloads without orchestration:
- task: AzureCLI@2
inputs:
azureSubscription: 'MyAzureConnection'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
az container create \
--resource-group myRG \
--name claims-api \
--image myacr.azurecr.io/claims-api:$(Build.BuildId) \
--registry-login-server myacr.azurecr.io \
--registry-username $(acrUser) \
--registry-password $(acrPassword)
Deploy to AKS
For production orchestrated workloads, use the KubernetesManifest task:
- task: KubernetesManifest@1
inputs:
action: 'deploy'
connectionType: 'azureResourceManager'
azureSubscriptionConnection: 'MyAzureConnection'
azureResourceGroup: 'myRG'
kubernetesCluster: 'myAKS'
manifests: '$(Pipeline.Workspace)/manifests/deployment.yaml'
containers: 'myacr.azurecr.io/claims-api:$(Build.BuildId)'
Binary and Script Deployments
Not every deployment uses containers. Azure App Service supports multiple deployment methods:
| Method | How It Works | Best For | Pipeline Task |
|---|---|---|---|
| ZIP Deploy | Upload ZIP package via Kudu API | Most App Service deployments | AzureWebApp@1 with package input |
| Web Deploy (MSDeploy) | IIS-level deployment with transforms | Legacy .NET Framework apps | AzureRmWebAppDeployment@4 |
| Run From Package | App runs directly from ZIP (read-only wwwroot) | Fastest cold start, immutable deploys | WEBSITE_RUN_FROM_PACKAGE = 1 |
| Azure CLI | Script-based deployment via az webapp deploy | Custom deployment logic | AzureCLI@2 |
| FTP | File-level upload to wwwroot | Avoid β slow, no atomic deploy | Not recommended for CI/CD |
| GitHub Actions Deploy | azure/webapps-deploy action | GitHub-hosted workflows | azure/webapps-deploy@v3 |
Scenario: Kai deploys containers with image scanning
π Kaiβs pipeline at Launchpad Labs:
- Build β multi-stage Dockerfile (SDK for build, Alpine for runtime)
- Scan β Trivy scans the image for CVEs. Pipeline fails on HIGH/CRITICAL findings
- Push β Docker@2 pushes to their ACR with build ID tag
- Deploy to staging β KubernetesManifest@1 updates the staging namespace
- Integration tests β run against staging endpoints
- Deploy to production β KubernetesManifest@1 with canary strategy (20% traffic)
- Monitor and promote β if Datadog shows no error spike after 15 minutes, promote to 100%
Riku adds a Dockerfile linting step using hadolint early in the pipeline to catch anti-patterns (running as root, missing HEALTHCHECK, not pinning base image versions).
Database Deployment Tasks
Database deployments are the most dangerous part of any release. A bad migration can corrupt data, cause downtime, or be impossible to roll back. The exam tests your knowledge of safe database deployment patterns.
Migration Approaches
| Approach | Tool | How It Works | Rollback |
|---|---|---|---|
| Code-first migrations | EF Core, Django, Rails | Generate migration files from model changes | Run migrate down or apply reverse migration |
| State-based (dacpac) | SQL Server Data Tools (SSDT) | Compare desired schema to current, generate diff script | Limited β requires manual rollback scripts |
| Versioned scripts | Flyway, Liquibase, DbUp | Numbered SQL scripts run in order | Write corresponding rollback scripts |
| Idempotent scripts | Custom SQL | Scripts check before modifying (IF NOT EXISTS) | Each script is self-contained and re-runnable |
The SqlAzureDacpacDeployment Task
For Azure SQL deployments in Azure Pipelines:
- task: SqlAzureDacpacDeployment@1
inputs:
azureSubscription: 'MyAzureConnection'
AuthenticationType: 'servicePrincipal'
ServerName: 'meridian-sql.database.windows.net'
DatabaseName: 'ClaimsDB'
deployType: 'DacpacTask'
DeploymentAction: 'Publish'
DacpacFile: '$(Pipeline.Workspace)/database/Claims.dacpac'
Safe Database Deployment Patterns
Always apply the expand-contract pattern for breaking changes:
- Never rename a column directly β add new column, migrate data, update code, drop old column
- Never remove a column that existing code reads β deploy code changes first, then contract
- Add indexes as non-blocking (ONLINE = ON for SQL Server)
- Use transactions for DML but be careful with DDL β some DDL auto-commits
Feature Flags with Azure App Configuration
Implementing feature flags with Azure App Configuration Feature Manager:
Setup
- Create an Azure App Configuration resource
- Add feature flags in the Feature Manager blade
- Add the
Microsoft.FeatureManagementNuGet package to your app - Connect your app to App Configuration using the connection string or managed identity
Configuration Filters
// In Program.cs
builder.Configuration.AddAzureAppConfiguration(options =>
options.Connect(connectionString)
.UseFeatureFlags());
builder.Services.AddFeatureManagement();
Percentage Filter (Gradual Rollout)
In the Azure portal or via CLI, configure a feature flag with a percentage filter:
- NewCheckout β enabled for 10% of users
- Increase to 25%, 50%, 100% as confidence grows
- The SDK handles consistent user bucketing (same user always sees the same version)
Targeting Filter (User and Group Targeting)
Target specific users or groups:
- Enable for
kai@launchpadlabs.com(individual) - Enable for
beta-testersgroup (group) - Default percentage for everyone else: 0%
Exam tip: Feature flags in pipelines
The exam may ask how to integrate feature flags into a deployment pipeline:
- Pre-deployment: Pipeline creates/updates the feature flag in App Configuration (OFF by default)
- Post-deployment: Pipeline enables the flag for a test group via the App Configuration REST API
- Validation: Run tests against the feature-flagged path
- Promotion: Increase percentage filter via pipeline task
- Rollback: Set the flag to OFF via a single API call β no redeployment needed
Key distinction: Feature flags separate DEPLOYMENT from RELEASE. The code is deployed (available) but not released (visible to users) until the flag is enabled.
Kai needs to deploy a new microservice to AKS. The pipeline should build the Docker image, scan it for vulnerabilities, push it to ACR, and deploy to the cluster. Which sequence of Azure Pipelines tasks is correct?
Nadia needs to rename a column in the production SQL database from 'CustName' to 'CustomerFullName'. The Claims API reads this column. What is the safest approach?
Which Azure App Service deployment method provides the fastest cold start and ensures the deployment is immutable (files cannot be modified at runtime)?
π¬ Video coming soon
Container, Script and Database Deployments
Next up: Infrastructure as Code: ARM vs Bicep vs Terraform