Terraform: Deploying Docker Compose on Azure App Service
This guide demonstrates how to use Terraform to provision an Azure Linux App Service that runs multiple Docker containers using a Docker Compose file. It includes best practices, step-by-step instructions, and common pitfalls for real-life DevOps workflows.
Best Practices
- Store your Docker Compose file (
docker-compose.yml) in version control and keep secrets out of the file (use environment variables or Azure Key Vault). - Pin image versions (avoid
latest) for reproducibility. - Use Terraform variables for resource names, locations, and sensitive data.
- Enable monitoring and logging for your App Service.
- Use CI/CD pipelines (GitHub Actions, Azure Pipelines) to automate deployments.
Step-by-Step: Deploy Multi-Container App with Terraform
- Write your Docker Compose file:
version: '3.3' services: db: image: mysql:5.7 volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: somewordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: depends_on: - db image: wordpress:6.4.3 ports: - "8000:80" restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress volumes: db_data: - Terraform configuration:
provider "azurerm" { features {} } resource "azurerm_resource_group" "main" { name = "${var.prefix}-resources" location = var.location } resource "azurerm_app_service_plan" "main" { name = "${var.prefix}-asp" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name kind = "Linux" reserved = true sku { tier = "Standard" size = "S1" } } resource "azurerm_app_service" "main" { name = "${var.prefix}-appservice" location = azurerm_resource_group.main.location resource_group_name = azurerm_resource_group.main.name app_service_plan_id = azurerm_app_service_plan.main.id site_config { app_command_line = "" linux_fx_version = "COMPOSE|${filebase64("docker-compose.yml")}" # Use filebase64 to encode the compose file } app_settings = { "WEBSITES_ENABLE_APP_SERVICE_STORAGE" = "false" } } - Deploy with Terraform:
terraform init terraform apply -var="prefix=myapp" -var="location=westeurope" - Access your app:
- Find the app’s URL in the Azure Portal or via Terraform output.
Real-Life Example: CI/CD Integration
- Use GitHub Actions to deploy on every push:
```yaml
- name: Terraform Apply run: terraform apply -auto-approve -var=”prefix=myapp” -var=”location=westeurope” ```
Common Pitfalls
- Using
latestimage tags (can cause unexpected updates) - Not encoding the Docker Compose file with
filebase64 - Not setting
WEBSITES_ENABLE_APP_SERVICE_STORAGE(can cause issues with persistent storage) - Forgetting to open required ports in the Compose file
- Not monitoring app health and logs