Day 47 of 50 Days of Python: Introduction to Infrastructure as Code with Python (Terraform / Bicep)
Part of Week 7: Python in Production
We’ve packaged our code, now it needs somewhere for it to live. Infrastructure as Code (IaC) turns cloud resources (networks, databases, containers) into files you commit to Git and review like any other Python module. Treating infrastructure declaratively means your FastAPI service spins up the same way on every environment and can be recreated from scratch in minutes.
What Is IaC & Why Python Developers Care
Reproducibility – A teammate can clone the repo and spawn an identical stack for your Python API.
Auditability – Git history shows who changed what subnet or secret and why.
Rollback – Just revert a commit to undo a bad infra change, no manual console clicking.
Automation – CI/CD can
terraform apply
after tests pass, giving you push‑button deployments.Cost Awareness – Plans show diffs (resources + price) before cloud bills surprise you.
Key Concepts
Declarative Desired State – Describe what you want, not how; the engine figures out steps.
Idempotency – Re‑applying the same file makes zero changes when state already matches code.
Mutable vs Immutable Resources – Some infra updates in‑place (security‑group rule), others replace resources entirely (RDS engine version).
State File – Snapshot mapping of “real world ↔ code” to track drift; store remotely & encrypt.
Modules/Re‑usability – Parameterised building blocks (VPC, S3 bucket) for DRY infra.
Providers – Plugins that know the API of a cloud (AWS, Azure) or SaaS (Datadog).
Plan → Apply Cycle – Preview diff first, then execute; prevents foot‑guns.
Drift Detection – Identify manual console edits and reconcile.
Hands On: Deploy a Python Container in Two Ways
Terraform (AWS)
# main.tf (simplified)
provider "aws" { region = var.aws_region }
module "ecr_repo" {
source = "terraform-aws-modules/ecr/aws"
name = "calihouse-api"
}
module "app" {
source = "terraform-aws-modules/ecs-fargate/aws"
name = "calihouse-api"
container_name = "api"
container_image = "${module.ecr_repo.repository_url}:latest"
cpu = 256
memory = 512
healthcheck = true
assign_public_ip = true
}
Then run in the console:
terraform init # download AWS provider
terraform plan # preview resources & cost
terraform apply # 3 min later your API has a public URL
Bicep (Azure)
// main.bicep – deploy Container App
param location string = resourceGroup().location
param image string = 'ghcr.io/you/calihouse-api:latest'
resource app 'Microsoft.App/containerApps@2024-01-01-preview' = {
name: 'calihouse-api'
location: location
properties: {
environmentId: resourceId('Microsoft.App/managedEnvironments', 'demo-env')
configuration: {
ingress: {
external: true
targetPort: 8000
}
}
template: {
containers: [
{
name: 'api'
image: image
}
]
scale: {
minReplicas: 1
maxReplicas: 3
}
}
}
}
az deployment group create \
--resource-group demo-rg \
--template-file main.bicep \
--parameters image=ghcr.io/you/calihouse-api:v0.1.0
Both files land in infra/ directory, reviewed via pull request, and executed by CI only after tests pass.
Tips & Tricks
Remote State Back‑ends – Use S3 + DynamoDB (Terraform) or Azure Storage (Bicep) to keep state central and lock‑protected.
Secrets Injection – Pull DB creds from AWS Secrets Manager/Azure Key Vault rather than hard‑coding.
Cross‑account deployments – Terraform workspaces or Azure DevOps service connections.
Policy Guardrails – Enforce cost or security rules with OPA (Terraform Cloud) or Azure Policies.
TL;DR
IaC treats cloud resources like code: versioned, reviewable, reproducible.
Terraform (multi‑cloud) and Bicep (Azure‑native) both express declarative desired state.
Commit infra alongside Python code; CI runs
plan
/apply
after unit & integration tests.Your FastAPI container now spins up in AWS Fargate or Azure Container Apps with two tiny files.
Next Up: Day 48 - Python Security Best Practices.
Day 48 (two days till the end of this series…..) will cover how best to organise your secrets, variables and protect your code and assets. Which is an important piece of the puzzle for any developer.
Join me tomorrow and as always… Happy coding!