Sign in to create and edit playbooks. Sign In Register

Add Container & Deploy Make Targets

DCD-3 Order: #3 Elaboration Has Dependencies

Updated 4 months ago

Guidance

Add Container & Deploy Make Targets

Objective

Extend the application Makefile (from BSP-06) with container, deployment, and operations targets. Uncomment and configure the ##@ Deployment section in the Makefile template. After this activity, every deployment operation is a single make command.


Process

1. Add Dockerfile

Create a multi-stage Dockerfile in the app monorepo:

# Dockerfile
# Stage 1: Build
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .

# Stage 2: Runtime
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --from=builder /app .
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "{project}.wsgi:application"]

2. Uncomment & Configure Makefile Deployment Section

In the Makefile (from BSP/artifacts/makefile_template.mk), uncomment and configure the ##@ Deployment section:

# Add/update these variables at the top
PROJECT := {project}
AWS_REGION := {region}
AWS_ACCOUNT := {account-id}
ECR_REPO := $(AWS_ACCOUNT).dkr.ecr.$(AWS_REGION).amazonaws.com/$(PROJECT)
HELM_CHART := deploy/helm/$(PROJECT)
ENV ?= local
NAMESPACE ?= $(ENV)
DOMAIN := {domain}
IMAGE_TAG := $(shell git rev-parse --short HEAD)

##@ Containers

containers: ## Build and push Docker image to ECR
    @echo "Building container $(ECR_REPO):$(IMAGE_TAG)..."
    docker build -t $(ECR_REPO):$(IMAGE_TAG) -t $(ECR_REPO):latest .
    @echo "Pushing to ECR..."
    aws ecr get-login-password --region $(AWS_REGION) | docker login --username AWS --password-stdin $(AWS_ACCOUNT).dkr.ecr.$(AWS_REGION).amazonaws.com
    docker push $(ECR_REPO):$(IMAGE_TAG)
    docker push $(ECR_REPO):latest
    @echo "✅ Pushed $(ECR_REPO):$(IMAGE_TAG)"

containers-local: ## Build Docker image for local K8s (no push)
    docker build -t $(PROJECT):local .
    @echo "✅ Built $(PROJECT):local"

##@ Deployment

deploy: ## Deploy to environment (ENV=local|blue|green)
    @echo "Deploying to $(ENV) (namespace: $(NAMESPACE))..."
    helm upgrade --install $(PROJECT) $(HELM_CHART) \
        -f $(HELM_CHART)/values.yaml \
        -f $(HELM_CHART)/values-$(ENV).yaml \
        --set image.tag=$(IMAGE_TAG) \
        --namespace $(NAMESPACE) \
        --create-namespace \
        --wait --timeout 300s
    @echo "✅ Deployed to $(ENV)"

deploy-local: ## Deploy to local K8s
    $(MAKE) containers-local
    $(MAKE) deploy ENV=local

deploy-blue: ## Deploy to blue namespace
    $(MAKE) deploy ENV=blue

deploy-green: ## Deploy to green namespace
    $(MAKE) deploy ENV=green

##@ Traffic & Operations

smoke-test: ## Run smoke tests (ENV=blue|green|prod)
    @echo "Running smoke tests on $(ENV)..."
    $(PYTEST) tests/smoke/ -v --base-url=https://$(ENV).$(DOMAIN) 2>&1 | tee smoke-tests.log
    @echo "✅ Smoke tests passed on $(ENV)"

switch: ## Switch prod ↔ idle DNS traffic
    @echo "Switching traffic: prod ↔ idle..."
    cd ../$(PROJECT)-infra && $(MAKE) traffic-switch
    @echo "✅ Traffic switched. Verify at https://prod.$(DOMAIN)"

rollback: ## Rollback to previous deployment
    @echo "Rolling back traffic..."
    cd ../$(PROJECT)-infra && $(MAKE) traffic-rollback
    @echo "✅ Rolled back"

verify: ## Full verification: test + integration + smoke
    $(MAKE) test
    $(MAKE) test-integration
    $(MAKE) smoke-test ENV=$(ENV)
    @echo "✅ Full verification passed for $(ENV)"

pipeline-status: ## Show current deployment status
    @echo "=== Blue Namespace ==="
    kubectl get pods -n blue 2>/dev/null || echo "  (not deployed)"
    @echo "=== Green Namespace ==="
    kubectl get pods -n green 2>/dev/null || echo "  (not deployed)"
    @echo "=== DNS ==="
    dig +short prod.$(DOMAIN) 2>/dev/null || echo "  (not configured)"
    dig +short idle.$(DOMAIN) 2>/dev/null || echo "  (not configured)"

3. Verify All New Targets

make help                  # Should show new sections: Containers, Deployment, Traffic
make containers-local      # Should build Docker image
make deploy-local          # Should deploy to local K8s
make pipeline-status       # Should show pod status

4. Test Local End-to-End

# Build and deploy locally
make deploy-local

# Verify pods running
kubectl get pods -n local

# Port forward and test
kubectl port-forward -n local svc/{project} 8080:80
curl http://localhost:8080/health

5. Commit

git add Makefile Dockerfile
git commit -m "feat(deploy): add container and deployment make targets"

Deliverables

  • Dockerfile created (multi-stage)
  • Makefile extended with containers, deploy, switch, rollback, verify, pipeline-status
  • make help shows new sections
  • Local deploy verified (make deploy-local)
  • All new make targets functional

Inputs

Read these before starting this activity. They are produced earlier in the playbook and are authoritative — raise a drift event instead of deviating.

  • Helm Chart Template (Template, Required) — produced by Create Helm Chart & Values (#82).
  • Makefile Template (Code, Required) — produced by Create Makefile (#93).
Details
Order:
#3
Phase:
Predecessor:
DCD-2 Create Helm Chart & Values
Created:
Apr 12, 2026
Last Updated:
May 21, 2026
Workflow
Design & Deploy CICD

Design and deploy CI/CD pipeline using GitHub Actions in the application monorepo. Create Helm chart with per-environment values, add container …

View Workflow
Assigned Agent

No agent assigned

Required Skills
Rules

No rules linked.

Input Artifacts 2
Output Artifacts

No output artifacts