A container is a self-contained, executable software package with all components needed to run an application — including the application code, system libraries, runtime, configurations, and supplemental tools. Containers function as an abstraction layer atop the host OS and lower-level infrastructure. They also enable teams to easily replicate their applications in distinct development, testing, and production environments. This is the more Docker-centric definition, as the industry widely credits Docker with setting the modern standard for containers.
That said, we can think of containers in a few other ways — as a delivery mechanism for deploying software in a reusable and repeatable way, as a self-contained application with all dependencies baked in, or even as a lightweight process that you can spin up quickly using a standard API.
Surprisingly, the concept of containerization has existed since 1979, tracing its "chroots" to foundational Unix V7 filesystem changes. Since then, numerous OSes, tools, and vendors — such as FreeBSD, Linux VServer, Solaris, and Warden — steadily introduced their own implementations of container-based virtualization. Numerous solutions have also emerged to support enterprise use cases.
There's now a bit more competition in the containerization space. While Docker remains a juggernaut, alternatives such as Rancher Desktop and Podman have gained some traction (especially within the open-source community).
How do containers work?
Containers solve the "it works on my machine" problem, since they can run in almost any computing environment and any cloud. Portability aside, containers are designed to be lightweight (consuming minimal disk space and fewer system resources). They help enable DevOps practices such as rolling deployments, self-healing infrastructure, and auto-scaling.
Containers are built from an installable template called a container image. Typically, each image is based on an operating system layer (such as various flavors of Linux, or Windows) that determines which libraries and other components are packaged within. Docker images specifically include the option to build from scratch, which is as slim as possible and enables you to create custom base images that aren't otherwise available. These empty containers omit any standard files or components by default.
We recommend building any custom container images using official images from Docker Hub or other reputable repositories. These sources are verified and directly maintained by software vendors, and undergo regular security checks to help prevent known vulnerabilities.
Containers provide isolation while allowing containerized applications to run as distinct processes in the user space. While each container contains OS-specific components, they don't actually include a full version of the OS. Instead, one or more containers will share the underlying OS kernel at runtime. This helps dramatically reduce their size and complexity.
Horizontal scalability is a major advantage to using containers. The process of creating more container instances and scaling up resource availability is relatively seamless, supported by popular orchestration platforms such as Kubernetes. This setup is highly beneficial for microservices-based architectures, where small, loosely-coupled services (and APIs) comprise the overall application experience. These services are often deployed within containers to maintain portability and scalability.
Containers versus virtual machines (VMs)
Containers stand apart from VMs architecturally, both functionally and in terms of performance. While containers provide abstraction and share the host OS kernel, each VM comes packaged with a full OS (making them much larger in size) and typically contain a single application. Containers can contain multiple processes or applications. This is generally frowned upon unless you're running just one primary process within the container, but it does offer some additional flexibility for fringe use cases.
Meanwhile, VMs are abstractions of hardware. With the help of an intermediate software hypervisor, VMs function as servers that divvy up host system resources for their own use — and request additional resources from the host machine to meet surges in demand. Containers are also considered more ephemeral in that they can spin up and down as needed, whereas the typical VM lifecycle is longer running.
However, containers and VMs do share some similarities. For example, you can nest "child" containers within parent containers and VMs within other VMs. Both package crucial binaries and libraries together to support applications. You can also operate containers and VMs side by side to support different workloads, making these technologies more complimentary than they might appear on paper.
Containers versus WebAssembly (Wasm)
WebAssembly burst onto the virtualization scene as a perceived alternative to containerization. Like containers, Wasm employs modules to decode, validate, and execute portable bytecode using your underlying infrastructure at runtime. Wasm APIs help the host environment and runtime environment communicate effectively, ensuring such modules can run on their respective machines.
Both containers and Wasm deliver robust support for numerous programming languages. They're both relatively lean and can run in multiple environments, such as web browsers. It's also possible to use containers and Wasm modules together to ensure seamless development, efficient deployment, process isolation, and improved application performance.
However, Wasm operates more as a sandboxed environment. The technology has also gained popularity in the server realm thanks to specialized WebAssembly System Interface (WASI) APIs — providing filesystem access and more.
You’ve mastered one topic, but why stop there?
Our blog delivers the expert insights, industry analysis, and helpful tips you need to build resilient, high-performance services.
Does HAProxy support containers?
Yes! HAProxy and HAProxy One are designed to support any application deployed in any environment. Additionally, you can deploy HAProxy itself within various Docker containers (installable via Docker Hub) for improved scalability.
To learn more about container support in HAProxy, check out our How to Run HAProxy with Docker blog post.