Chapter 7
Containers, Orchestration and Serverless Computing
Bachelors Program in Full Stack Development
Cloud Integration & Deployment (Heroku/AWS)
•
Bachelor
Containers, Orchestration and Serverless Computing
Introduction
Modern cloud applications are assembled from services that must be packaged, deployed, scaled, secured, observed, and updated reliably. Containers and serverless computing address these concerns in different ways. A container packages an application with its runtime dependencies while sharing the host operating system kernel. Orchestration platforms schedule and manage many containers. Serverless platforms execute application code in response to events while the provider manages servers and much of the operational infrastructure.
For full-stack developers, these technologies are not interchangeable deployment buttons. They represent different operating models. Heroku provides a highly simplified platform-as-a-service experience for deploying containers or build-based applications. Amazon Elastic Container Service (ECS) provides AWS-native container orchestration with configurable infrastructure choices, while Amazon Elastic Kubernetes Service (EKS) provides managed Kubernetes control planes and a broader, more complex ecosystem. AWS Lambda, API Gateway, and event services support event-driven applications with fine-grained scaling, but introduce constraints involving execution duration, statelessness, cold starts, observability, and vendor dependence.
This chapter develops a design framework for selecting and securely using these approaches.
Learning Objectives
By the end of this chapter, you should be able to:
Explain container images, registries, runtimes, and orchestration.
Build a secure, reproducible Docker image using practical best practices.
Compare container deployment on Heroku, ECS, and EKS.
Design an event-driven application using Lambda, API Gateway, and AWS event services.
Evaluate cold starts, state management, portability, scaling, and operational complexity.
Apply governance, security, reliability, and cost considerations to deployment decisions.
1. The Deployment Abstraction Spectrum
Deployment technologies can be viewed as a spectrum of operational responsibility.
A container is an isolated process environment, not a complete virtual machine. Namespaces isolate processes, networking, and filesystems; control groups (cgroups) constrain resource use. Because containers share the host kernel, they usually start faster and use fewer resources than virtual machines, but they provide a different isolation boundary. A compromised container may threaten the host if the runtime or configuration is vulnerable.
A container image is an immutable artifact containing application files, dependencies, metadata, and a startup instruction. Images are composed of layers. Reusing unchanged layers improves build and distribution efficiency, but an image layer should not be treated as a secure deletion mechanism: sensitive data copied into an earlier layer may remain recoverable even if deleted in a later layer.
Important terms include:
Image: A packaged filesystem and metadata used to create containers.
Container: A running process created from an image.
Registry: A repository for storing and distributing images, such as Amazon ECR or Docker Hub.
Runtime: Software that creates and runs containers, such as containerd or Docker Engine.
Immutable deployment: Replacing an artifact with a new version rather than modifying a running instance.
Orchestrator: A system that schedules workloads and manages their desired state.
Function: A deployable unit of code invoked by an event or request.
2. Building Secure Docker Images
A Dockerfile is a declarative build recipe. A minimal example for a Node.js service is:
FROM node:20-bookworm-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build && npm prune --omit=dev
FROM node:20-bookworm-slim
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/package*.json ./
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]
This multi-stage build separates compilation from execution. The final image excludes source files and build tools that are unnecessary at runtime. The non-root user reduces the impact of an application-level compromise. CMD uses an exec-form array so that the application receives operating-system signals directly and can shut down gracefully.
A secure image-development process should include the following practices:
Select a maintained base image. Use a trusted source, pin an appropriate version, and monitor security advisories. Absolute digest pinning improves reproducibility, although it creates an update-maintenance obligation.
Use a small runtime image. Smaller images reduce transfer time and attack surface, but extreme minimalism can make debugging and certificate management harder.
Use a .dockerignore file. Exclude .git, local dependencies, credentials, logs, test output, and environment files.
Never bake secrets into images. Supply secrets through a secret manager or platform configuration at deployment time.
Run as a non-root user. Combine this with read-only filesystems and dropped Linux capabilities where supported.
Scan dependencies and images. Scanning detects known vulnerabilities; it does not prove that the application is secure.
Generate a software bill of materials (SBOM). An SBOM records components and supports vulnerability response.
Sign and verify images. Provenance and signature policies help ensure that only authorized artifacts are deployed.
Use deterministic builds where practical. Lock dependency versions and produce build metadata.
Define health behavior. A health check should test meaningful service readiness rather than merely whether a process exists.
A .dockerignore file might contain:
.git
.env
node_modules
coverage
*.log
Configuration belongs outside the image. For example, a database URL should be injected through a platform secret or environment configuration, with access controlled by an identity policy. Environment variables are convenient but may be exposed through logs, process inspection, crash reports, or administrative interfaces; highly sensitive credentials should use a managed secret facility.
Resource and Reliability Considerations
Containers should declare realistic CPU and memory requests and limits. A limit protects the host from an individual workload, but an excessively low limit can cause termination or performance degradation. Applications should handle termination signals, close connections, and stop accepting new work before exit. Stateless HTTP containers should externalize sessions, files, and durable data to managed stores such as object storage or databases.
A useful capacity approximation is:
N = ⌈λT / C⌉
where λ is the arrival rate in requests per second, T is average service time in seconds, C is the sustainable concurrency per container, and N is the approximate number of containers required. This is a planning approximation based on average behavior; it excludes safety margins, burstiness, queueing effects, startup time, and failure capacity. For example, if λ = 120 requests per second, T = 0.25 seconds, and each container safely handles C = 10 concurrent requests, then N = ⌈120 × 0.25 ÷ 10⌉ = 3. Production capacity would normally add headroom and account for latency objectives.
3. Orchestration and Desired State
Manual container execution becomes unsuitable when an application contains multiple replicas, networks, rolling releases, secrets, health checks, and failure recovery requirements. An orchestrator maintains a desired state. If the desired state is three healthy replicas and one fails, the scheduler attempts to create a replacement.
Core orchestration functions include:
scheduling workloads onto available compute;
service discovery and load balancing;
health checking and replacement;
rolling or blue-green deployment;
autoscaling;
secret and configuration distribution;
access control and audit logging;
storage and network integration.
Kubernetes expresses desired state through resources such as Deployments, Pods, Services, ConfigMaps, and Secrets. ECS expresses workloads through task definitions, tasks, services, clusters, and capacity providers. Kubernetes offers a broad, portable API and ecosystem, but the control plane, networking, policy, upgrades, and observability require substantial expertise. ECS is more AWS-integrated and often simpler for teams already committed to AWS.
Heroku Containers, ECS, and EKS
Dimension
Heroku Container Runtime
Amazon ECS
Amazon EKS
Primary abstraction
Application and release
AWS service and task
Kubernetes cluster and resources
Operational effort
Low
Moderate
High
Portability
Moderate; platform conventions matter
Lower outside AWS
Higher API portability, though integrations vary
Infrastructure control
Limited
Flexible, especially with Fargate or EC2
Extensive
Ecosystem
Simple deployment workflow
AWS-native services
Kubernetes ecosystem
Best fit
Small teams and rapid delivery
AWS services with controlled complexity
Large platforms or Kubernetes expertise
Heroku’s container deployment commonly uses a Procfile, registry-based image release, configuration variables, attached services, and platform-managed routing. It is attractive when developer productivity and low operational burden are priorities. Its constraints include less control over networking, scheduling, node placement, and specialized infrastructure.
ECS can run tasks on AWS Fargate, where AWS manages the underlying servers, or on EC2 capacity managed by the customer. Fargate reduces host administration; EC2 may offer more control or different cost characteristics. ECS integrates naturally with IAM, CloudWatch, Elastic Load Balancing, and ECR.
EKS is appropriate when Kubernetes APIs, operators, service meshes, or a multi-environment Kubernetes strategy justify the complexity. Managed control planes do not eliminate responsibility for worker capacity, cluster configuration, add-ons, policies, application security, and operational observability.
The correct comparison is not “which platform is most powerful?” but “which platform supplies the required control with acceptable complexity?” Excess capability can become technical debt.
4. Serverless Computing and Event-Driven Design
AWS Lambda executes functions in response to invocations. Events may originate from API Gateway, S3, EventBridge, SQS, Kinesis, or scheduled rules. Lambda functions should generally be small, stateless, independently deployable units. They may write state to DynamoDB, Amazon S3, RDS, or another managed service.
API Gateway provides HTTP or REST interfaces, authentication integration, throttling, routing, monitoring, and request transformation options. EventBridge supports event buses and rules for loosely coupled event routing. SQS provides durable queues and helps absorb bursts. The choice between synchronous APIs and asynchronous events should follow the interaction requirement: a user-facing request normally needs a bounded response, whereas background processing can be queued and retried.
A typical architecture is:
Serverless event-driven architecture
Figure: Serverless event-driven architecture
Figure: A serverless API combines synchronous requests with asynchronous event processing and externalized durable state.
Cold Starts and Latency
A cold start occurs when the platform must create or initialize an execution environment. Initialization may include runtime startup, dependency loading, network attachment, and application initialization. A warm invocation reuses an existing environment, although reuse is not guaranteed.
Average latency can be conceptualized as:
L̄ = pcLc + (1 − pc)Lw
where L̄ is expected latency, pc is the probability of a cold invocation, Lc is cold-invocation latency, and Lw is warm-invocation latency. This weighted-average model assumes two categories and stable representative latencies; real systems have distributions, retries, queueing, and percentiles. If pc = 0.10, Lc = 900 ms, and Lw = 120 ms, then L̄ = 0.10 × 900 + 0.90 × 120 = 198 ms. Average latency alone is insufficient for user experience because the 95th or 99th percentile may be much higher.
Cold-start mitigation includes reducing package size, moving expensive initialization outside the handler, selecting an appropriate runtime, reusing database connections, and using provisioned concurrency when its cost and operational implications are justified. Provisioned concurrency reduces initialization surprises but does not eliminate all latency or design problems.
State, Retries, and Idempotency
Lambda execution environments are temporary. Local memory and /tmp storage may persist across invocations in the same environment, but they must not be treated as durable state. Durable state belongs in an appropriate managed data store.
Event services commonly retry failed deliveries. Therefore, consumers should be idempotent: processing the same event more than once should not create an incorrect result. A practical pattern is to assign each event a unique identifier and record processed identifiers transactionally with the business update where possible. Dead-letter queues and failure destinations support investigation of messages that repeatedly fail.
At-least-once delivery means duplicates are possible. Exactly-once business outcomes require application-level design, such as idempotency keys, conditional writes, or transactional state transitions. A timeout does not prove that the operation failed; the remote service may have completed it before the caller lost the response.
5. Security and Governance
Security must be designed across the software supply chain and runtime:
Use least-privilege IAM roles for tasks and functions.
Separate build, deployment, and runtime identities.
Restrict registry access and scan artifacts before release.
Encrypt data in transit and at rest where appropriate.
Place private resources in controlled network segments, while recognizing that network isolation is not a substitute for identity authorization.
Validate API input and enforce authentication, authorization, quotas, and rate limits.
Log security-relevant events without exposing credentials or personal data.
Apply retention, deletion, and residency requirements to logs and stored events.
Maintain an incident-response process and an auditable deployment trail.
Event payloads can contain personal or commercially sensitive information. Data minimization, access controls, encryption, retention schedules, and privacy obligations should be considered before routing events through shared buses or third-party integrations. Automated scaling can amplify an abuse event, so throttling and budget alarms are governance controls as well as performance controls.
6. Operational Complexity and Decision Framework
A deployment choice should evaluate at least six dimensions:
Control: Is custom networking, scheduling, runtime choice, or storage required?
Scale pattern: Is load steady, bursty, periodic, or unpredictable?
Latency: Are occasional cold starts acceptable?
State: Can the workload remain stateless, or does it require long-lived processes and local state?
Portability: Is migration across providers a strategic requirement?
Team capability: Can the team operate Kubernetes, networking, IAM, observability, and incident response?
A simple decision heuristic is useful. Choose Heroku when the application is conventional, the team values rapid delivery, and platform control requirements are limited. Choose ECS when AWS integration and container control are needed without adopting the full Kubernetes ecosystem. Choose EKS when Kubernetes capabilities or organizational standardization justify its operational investment. Choose Lambda when event-driven execution, variable demand, and short-lived stateless work dominate. Use containers for long-running processes, custom runtimes, predictable performance, specialized networking, or workloads that do not fit function limits.
Portability is multidimensional. OCI-compatible images improve artifact portability, but IAM policies, load balancers, databases, event formats, deployment pipelines, and observability systems may remain provider-specific. Kubernetes portability can also be overstated because managed services differ in networking, storage, identity, and load-balancing behavior.
7. Illustrative Case: Online Document Processing
Background
A university application accepts documents through a web interface. Users expect immediate confirmation, while virus scanning, text extraction, and indexing may take several minutes.
Problem
A single containerized web process performed upload, scanning, extraction, and indexing synchronously. During submission peaks, requests timed out, and a failed extraction forced users to upload again. Operations staff also had difficulty scaling background work independently from the web interface.
Analysis
The workload contains two different interaction types. Upload confirmation is synchronous and latency-sensitive. Document processing is asynchronous, retryable, and potentially CPU-intensive. Documents and status records require durable storage. Duplicate events are possible because queue delivery is at least once.
Approach
The team retained a containerized web API on ECS and placed documents in object storage. The API created a document record with a unique idempotency key and emitted an event to a queue. A Lambda consumer performed lightweight validation and dispatched larger extraction jobs to a container worker service. A database stored status transitions such as RECEIVED, SCANNING, EXTRACTING, INDEXED, and FAILED. A dead-letter queue captured repeatedly failing messages. API Gateway and the web application exposed status to users without waiting for extraction.
IAM roles were separated for the API, Lambda function, and worker. Images were built with multi-stage Dockerfiles, scanned, signed, and deployed through an approval pipeline. Logs used document identifiers rather than document contents.
Outcome
Web requests became independent of extraction duration. Background workers could scale separately, failures could be retried, and operators gained visibility into queue depth and processing age. The design introduced additional services and therefore required stronger observability, event tracing, cost monitoring, and data-retention governance.
Learning Points
The case demonstrates that architectural decomposition should follow interaction and scaling boundaries. Serverless functions are valuable for event adapters and short tasks, while containers remain appropriate for long-running or resource-specialized processing. Idempotency and durable state are essential, not optional refinements.
8. Contemporary Developments and Best Practices
Current practice increasingly combines models rather than selecting one platform exclusively. Teams may use containers for core services, Lambda for event handlers, managed databases for state, and queues for resilience. Platform engineering teams provide reusable deployment templates, policy-as-code, observability defaults, and secure golden images.
AI-assisted coding and automated remediation can accelerate Dockerfile creation, dependency updates, and incident analysis, but generated configurations must be reviewed. An AI tool may introduce excessive permissions, insecure defaults, obsolete images, or leaked data. Human accountability remains necessary for security, compliance, and architectural decisions.
A mature delivery pipeline should include source review, automated tests, image construction, SBOM generation, vulnerability scanning, signature verification, deployment policy checks, progressive release, health validation, monitoring, and rollback. Operational metrics should include availability, latency percentiles, error rate, queue age, cold-start frequency, resource utilization, deployment frequency, and recovery time. Cost should be analyzed with workload shape rather than headline per-request prices alone.
Challenges and Limitations
Containers do not automatically provide security, portability, or efficient scaling. Image vulnerabilities, excessive privileges, insecure registries, and weak runtime policies remain common risks. Orchestrators solve scheduling problems but add configuration and failure modes. Kubernetes can become a platform whose operation consumes more effort than the application itself.
Serverless reduces infrastructure administration but does not remove architecture. Developers still manage IAM, retries, observability, quotas, data consistency, deployment versions, and provider limits. Cold starts, execution-duration limits, concurrency controls, and vendor-specific events can affect design. Distributed systems also make debugging and transaction coordination more difficult.
The appropriate objective is not minimum infrastructure ownership at any cost. It is a reliable, secure, economically justified system whose complexity matches its requirements and the team’s capabilities.
Chapter Summary
Containers package applications into reproducible artifacts and provide a useful boundary between application software and infrastructure. Secure images use maintained bases, multi-stage builds, non-root execution, externalized secrets, vulnerability scanning, SBOMs, and controlled provenance. Orchestration maintains desired state, schedules replicas, performs health management, and supports deployment strategies.
Heroku emphasizes simplicity and developer productivity. ECS offers AWS-native container management with moderate operational complexity. EKS supplies Kubernetes capabilities and extensive control at a higher operational cost. Serverless systems using Lambda, API Gateway, queues, and event buses support elastic, event-driven architectures, but require careful handling of cold starts, retries, idempotency, IAM, observability, and durable state.
Deployment decisions should consider control, demand patterns, latency, state, portability, security, cost, and team capability. Hybrid architectures are often effective when synchronous APIs, asynchronous processing, long-running workers, and managed services have different requirements.
Key Terms
Container: An isolated process running from an image.
Container image: An immutable package containing application files, dependencies, and metadata.
Dockerfile: A declarative recipe for building a container image.
Registry: A repository that stores and distributes images.
Multi-stage build: A build using separate stages to exclude unnecessary tools from the runtime image.
Orchestration: Automated scheduling, scaling, networking, and lifecycle management of workloads.
Desired state: The declared condition that an orchestrator attempts to maintain.
ECS: AWS managed container orchestration service.
EKS: AWS managed Kubernetes service.
Heroku Container Runtime: Heroku’s deployment model for running container images.
Serverless computing: A model in which the provider manages server infrastructure and charges or allocates capacity around executions or requests.
AWS Lambda: AWS function-as-a-service platform.
API Gateway: A managed service for exposing and controlling APIs.
Event-driven architecture: Architecture in which events trigger decoupled processing.
Cold start: Initialization delay when a new function execution environment is created.
Idempotency: Property that repeated processing produces the same intended business result.
Dead-letter queue: A destination for messages that cannot be processed successfully.
SBOM: Software bill of materials listing software components and dependencies.
Least privilege: Granting only the permissions required for a task.
Immutable deployment: Releasing a new artifact rather than modifying a running artifact in place.
Review Questions
Short Answer Questions
Why is a container different from a virtual machine?
What is the purpose of a multi-stage Docker build?
Name two differences between ECS and EKS.
What is a cold start in AWS Lambda?
Why must event consumers be idempotent?
Long Answer Questions
Explain how a secure Docker image should be built, scanned, released, and operated.
Compare Heroku, ECS, and EKS in terms of control, portability, and operational complexity.
Describe how API Gateway, Lambda, SQS, and a database can form a resilient serverless application.
Analyze the advantages and limitations of externalizing state in cloud-native systems.
Explain why Kubernetes may be technically suitable but organizationally unsuitable for a small team.
Analytical / Application Questions
A service has unpredictable traffic, short stateless requests, and occasional latency-sensitive users. Would you choose containers, Lambda, or a hybrid design? Justify your decision using scaling, cold-start, and operational considerations.
Design an idempotent document-processing workflow that remains correct when a queue delivers the same event twice. Identify the state store, idempotency key, retry policy, and failure-handling mechanism.
A team wants to move a Dockerized application from Heroku to AWS. Identify which artifacts are likely to be portable and which platform integrations must be redesigned or reconfigured.
Multiple Choice Questions with Answers
Question 1
Which Docker practice most directly reduces the impact of a process compromise?
A. Running the application as a non-root user
B. Exposing more container ports
C. Copying secrets into the image
D. Disabling image scanning
Correct Answer: A. Running the application as a non-root user
Question 2
What is the primary purpose of an orchestrator such as ECS or Kubernetes?
A. Editing application source code
B. Maintaining desired workload state and managing deployment and scaling
C. Replacing all application databases
D. Encrypting every user document automatically
Correct Answer: B. Maintaining desired workload state and managing deployment and scaling
Question 3
Which platform generally provides the greatest Kubernetes ecosystem compatibility?
A. Heroku Container Runtime
B. Amazon ECS
C. Amazon EKS
D. A Dockerfile alone
Correct Answer: C. Amazon EKS
Question 4
Where should a database password normally be supplied to a containerized application?
A. In a committed .env file
B. In an image layer
C. Through runtime configuration or a managed secret facility
D. In the Dockerfile comment section
Correct Answer: C. Through runtime configuration or a managed secret facility
Question 5
What is a cold start in AWS Lambda?
A. A failed database transaction
B. The initialization of a new function execution environment
C. A queue message that has been deleted
D. A container image scan
Correct Answer: B. The initialization of a new function execution environment
Question 6
Why is idempotency important for event consumers?
A. Event systems may deliver a message more than once
B. It guarantees zero network latency
C. It eliminates the need for durable storage
D. It prevents all authorization errors
Correct Answer: A. Event systems may deliver a message more than once
Question 7
If arrival rate is 120 requests per second, service time is 0.25 seconds, and each container safely handles 10 concurrent requests, what approximate minimum number of containers is given by N = ⌈λT ÷ C⌉?
A. 1
B. 2
C. 3
D. 30
Correct Answer: C. 3
Question 8
Which service is most appropriate for buffering asynchronous work and supporting retry-oriented processing?
A. Amazon SQS
B. Amazon Route 53 only
C. Docker Hub only
D. A Dockerfile
Correct Answer: A. Amazon SQS
Question 9
Which statement best describes portability?
A. An OCI image guarantees that every cloud integration is portable
B. Portability includes artifacts, but IAM, networking, events, and managed services may remain provider-specific
C. Portability is impossible for all containers
D. Kubernetes removes every operational difference between clouds
Correct Answer: B. Portability includes artifacts, but IAM, networking, events, and managed services may remain provider-specific
Question 10
What is a major reason to choose ECS over EKS?
A. ECS always supports more Kubernetes APIs
B. ECS can provide AWS-native container management with less Kubernetes operational complexity
C. ECS cannot run containers
D. ECS eliminates the need for IAM
Correct Answer: B. ECS can provide AWS-native container management with less Kubernetes operational complexity
Cloud Integration & Deployment (Heroku/AWS)
Chapter 7
of 14