Basics Story

Chapter #12 – Deployment

packaging, containers, cloud, CI/CD, monitoring, security

12.0  Prologue

Deployment is the process of making software available to users. Writing correct code is necessary but not sufficient — software must also be packaged, configured, delivered to a runtime environment, observed in production, and updated without downtime. Modern deployment is automated, repeatable, and designed to fail fast with minimal user impact.

12.1  Building and Packaging

Software must be packaged into a distributable form before deployment:
  • Native executable + installer: Windows (.msi, .exe), macOS (.pkg, .dmg), Linux (.deb, .rpm, AppImage). Self-contained; targets one OS and architecture.
  • Language runtime package: Python wheel (.whl), Java JAR, npm package. Requires the appropriate runtime on the target machine.
  • Container image (Docker): a portable, layered bundle that includes the application, its runtime, and all system libraries. Runs identically on any host with a container runtime.
  • Serverless bundle: a zip file or container image deployed to a FaaS (Function as a Service) platform; the cloud provider manages the runtime environment.
Reproducibility: the same source code + same environment should always produce the same build artifact. Lock files, pinned dependency versions, and hermetic build systems (Bazel, Nix) all serve this goal.

12.2  Virtual Machines and Containers

  Virtual Machine (VM) Container (Docker / Podman)
Isolation Full OS virtualisation; separate kernel Shared host kernel; isolated namespace + cgroup
Startup time 30 s – 2 min <1 s (or milliseconds for pre-pulled images)
Overhead Several GB per VM Tens to hundreds of MB
Security boundary Stronger (separate kernel) Weaker (shared kernel; container escape is possible)
Best for Strong isolation, running different OSes Microservices, CI jobs, fast horizontal scaling
A minimal Dockerfile for a Python web service: FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "server.py"] Container orchestration (Kubernetes): manages containers across a cluster. Handles scheduling (which node?), scaling (how many replicas?), rolling updates, health checks, and service discovery. The dominant orchestration platform in cloud-native deployments.

12.3  Cloud Computing

Cloud providers (AWS, Azure, GCP, and others) rent compute, storage, and network infrastructure on demand. Three primary service models:
  • IaaS (Infrastructure as a Service): rent VMs and storage; you manage the OS, runtime, and application. Examples: EC2 (AWS), Azure VMs.
  • PaaS (Platform as a Service): rent a managed runtime; you deploy the application only. Examples: Heroku, Google App Engine, Azure App Service. The provider handles patching, scaling, and availability zones.
  • Serverless / FaaS (Function as a Service): rent individual function invocations; you provide the function and it runs in response to events. Examples: AWS Lambda, Azure Functions, Google Cloud Run. Scales to zero; you pay only for invocations.
Commonly used managed services:
  • Databases: RDS / Aurora (AWS), Cloud SQL (GCP), Azure SQL
  • Object storage: S3 (AWS), GCS, Azure Blob Storage
  • Queues: SQS (AWS), Pub/Sub (GCP), Azure Service Bus
  • Caches: ElastiCache / Redis (AWS), Azure Cache
  • CDN: CloudFront (AWS), Cloudflare, Azure CDN

12.4  Continuous Integration / Continuous Delivery (CI/CD)

CI/CD pipelines automate the path from a developer’s commit to running software in production, making deployments frequent, fast, and low-risk. Typical pipeline stages:
  1. Developer pushes a commit to version control.
  2. CI server (GitHub Actions, GitLab CI, Jenkins, CircleCI) detects the push.
  3. Build: compile, transpile, or package the application.
  4. Test: run unit tests, integration tests, static analysis (linting, type checking), security scanners.
  5. Publish: push the built artifact or container image to a registry.
  6. Deploy: update the staging or production environment.
  7. Verify: smoke tests, health checks; roll back automatically on failure.
Advanced deployment patterns:
  • Blue/green: run the old version (blue) alongside the new (green); switch traffic in one step; instant rollback by switching back.
  • Canary release: gradually shift traffic from old to new (1% → 10% → 100%), monitoring error rates at each step.
  • Feature flags: enable new features for a subset of users without redeployment. Decouples deploy from release.
A minimal GitHub Actions workflow: on: [push] jobs: build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: cargo build --release - run: cargo test

12.5  Monitoring and Observability

You cannot fix what you cannot see. The three pillars of observability are:
  • Logs: structured records of events (2026-04-29 INFO request completed in 42ms). Collected by the application, shipped to an aggregator (Elasticsearch/Kibana, Grafana Loki, Datadog Logs).
  • Metrics: numeric time-series measurements (CPU %, request rate, error rate, latency p99). Collected by Prometheus; visualised in Grafana. Commercial alternatives: Datadog, New Relic, CloudWatch.
  • Traces: records of a single request’s path through multiple services, with timing for each hop. Essential for diagnosing latency in microservice architectures. Tools: Jaeger, Zipkin, Honeycomb, AWS X-Ray.
Alerts: rules that fire when a metric crosses a threshold (error rate > 1%, p99 latency > 500 ms), notifying an on-call engineer via PagerDuty, Opsgenie, or Slack. SLO (Service Level Objective): a measurable target for reliability (e.g., 99.9% of requests succeed in <200 ms, measured over a 30-day window). SLOs drive prioritisation: when you are within the SLO, you can take risks; when you are burning your error budget, reliability work takes precedence.

12.6  Security Basics

Security is not a feature to add at the end — it is a property to maintain throughout the software lifecycle. Key principles:
  • Principle of least privilege: processes, users, and services should have the minimum permissions needed for their function. A web server should not run as root.
  • Keep dependencies updated: most real-world vulnerabilities are known CVEs in third-party libraries. Use dependabot, cargo audit, or pip-audit to detect them.
  • HTTPS everywhere: TLS encrypts data in transit. Never transmit credentials or sensitive data over plain HTTP.
  • Input validation: never trust data from outside the system. SQL injection, cross-site scripting (XSS), and command injection all exploit unvalidated user input.
  • Secrets management: do not hardcode API keys, passwords, or certificates in source code. Use environment variables, a secrets manager (HashiCorp Vault, AWS Secrets Manager), or a CI secret store.
  • Authentication vs. authorisation: authentication confirms who you are (login with password / OAuth / certificate); authorisation determines what you may do (RBAC, ACLs).
  • Defence in depth: assume one layer will be breached; design so that a breach in one layer does not immediately compromise everything.

12.7  Epilogue

Deployment closes the loop between writing software and delivering value. The tools and practices described in this chapter — containers, cloud services, CI/CD pipelines, observability, and security hygiene — form the operational foundation of modern software engineering. Mastering them, alongside the hardware, OS, networking, language, and algorithm knowledge in the preceding chapters, gives you a complete picture of how software is built and run.

12.8  References

Docker Getting Started
Kubernetes Basics Tutorial
The Twelve-Factor App
GitHub Actions Documentation
OWASP Top 10 Security Risks