What is a container, and how does it differ from a virtual machine (VM)?
A container packages an application with its dependencies and shares the host machine's operating system kernel, making it much lighter and faster to start than a VM, which instead virtualizes an entire separate machine including its own full operating system — like renting a fully furnished room in an existing house (container) versus building an entirely separate house from scratch, complete with its own foundation and utilities (VM).
A Virtual Machine (VM) virtualizes hardware: a hypervisor (like AWS's Nitro Hypervisor) creates an isolated virtual machine that runs its own complete, independent operating system, including its own kernel, on top of the host's physical hardware. Each VM is heavyweight — it takes real memory and disk space just for its OS, and boots slowly (often tens of seconds to minutes) because it has to start an entire operating system from scratch.
A container, by contrast, virtualizes at the operating system level rather than the hardware level: it packages an application together with its code, runtime, libraries, and configuration into a single, portable unit, but shares the host machine's existing kernel rather than running its own separate one. Containers use OS-level isolation mechanisms (Linux namespaces for process/network/filesystem isolation, and cgroups for resource limiting) to give each container the appearance of running in its own isolated environment, without the overhead of a full separate OS. This makes containers dramatically lighter weight than VMs — they typically start in a fraction of a second to a few seconds, and many containers can run efficiently on a single host sharing that one kernel.
The practical implications: containers are the standard unit of deployment for modern microservices (via Docker images, orchestrated by ECS, EKS, or Kubernetes) because their fast startup and lower resource overhead fit well with elastic, horizontally-scaled architectures where you're frequently starting and stopping many instances of a service. VMs remain the right choice when you genuinely need full OS-level isolation (stronger security boundary between tenants) or need to run a different OS/kernel than the host provides — which is part of why AWS Fargate and Lambda both actually run on top of Firecracker microVMs under the hood: they combine container-like packaging and developer experience with VM-level isolation guarantees, getting benefits from both models simultaneously.
Mentioning that Lambda and Fargate run on Firecracker microVMs is a great way to tie this fundamental concept to real AWS architecture — it shows you understand that the 'container vs VM' distinction isn't purely academic, since AWS's own serverless platforms are built by deliberately combining ideas from both.