Docker is a tool that lets you package an application together with its entire environment and run it identically on any machine. For a backend developer this means the end of the eternal "works on my machine" problem.
The problem: "works on my machine"
Picture this: you wrote a Spring Boot application and tested it locally — everything works. You hand it to a colleague — it crashes. You deploy it to a server — trouble again. The cause is almost always the same: the environment is different.
You have Java 21, your colleague has 17. The server runs a different version of a library. An environment variable is named slightly differently. These discrepancies pile up and turn into unpredictable errors that are hard to reproduce.
This problem used to be solved with virtual machines: spin up a separate OS, configure it by hand, ship a disk image several gigabytes in size. It worked, but it was heavy and slow.
Docker offered a lighter approach — containers.
What a container is
A container is an isolated process on the host machine. It sees only what it is allowed to: its own file system, its own environment variables, its own network interfaces.
A short formula: container = isolated process + its own file system.
Isolation is achieved through Linux kernel features:
- namespaces — separate the namespaces for processes, network, users, and file system.
- cgroups (control groups) — limit how much CPU and memory a container can use.
This is what fundamentally sets a container apart from a virtual machine.
Container vs virtual machine
| Virtual machine | Container | |
|---|---|---|
| OS kernel | Its own (guest) | Shared with the host |
| Startup | Minutes | Seconds / fractions of a second |
| Size | Gigabytes | Tens–hundreds of megabytes |
| Isolation | Full (hardware level) | At the process level |
A virtual machine emulates an entire computer: it has its own kernel, its own drivers, its own OS. This gives maximum isolation but demands significant resources.
A container uses the host kernel and adds isolation on top of it. It doesn't know about neighboring containers and doesn't see the host's files — but the processes inside it start with almost no overhead.
For most backend tasks, containers are perfectly sufficient.
Image and container: class and object
Before you can run a container, you need an image. An image is an immutable snapshot of a file system: all the application files, dependencies, configuration, and the right version of Java.
The relationship is simple:
- An image is a template (like a class in Java). It is immutable and stored on disk or in a registry.
- A container is a running instance of an image (like an object). You can have several from a single image.
A single image myapp:1.0 can be run as one container on a developer's laptop, another on a test server, and a third in production. Each one gets an identical environment.
Where this helps a backend developer
The same environment everywhere. Dev, staging, and production run on the same image. "Works on my machine" stops being an argument.
Fast start and stop. A container with a JVM starts in a few seconds. This is convenient both for development and for horizontal scaling under load.
Dependency isolation. Two applications require different versions of the same library — each runs in its own container without conflicts.
Reproducible builds. An image is built from an instruction (Dockerfile) and reproduces identically on any machine. This is the foundation of reliable CI/CD.
A first look at the basic commands
Below are overview examples of what Docker looks like in practice. The details of each command are covered in the next article.
# Run a container from the eclipse-temurin:21-jre image
docker run eclipse-temurin:21-jre java -version
# View running containers
docker ps
# Stop a container by its ID or name
docker stop <container_id>
# Remove a stopped container
docker rm <container_id>
docker run pulls the image from a registry (if it isn't available locally), creates a container, and runs the specified command. docker ps shows what is running right now.
The default registry is Docker Hub (hub.docker.com). It stores official images: eclipse-temurin, postgres, nginx, and hundreds of others.
In short
- A container is an isolated process with its own file system; isolation is built on the Linux kernel's
namespacesandcgroups. - A container uses the host kernel — it is lighter and faster than a virtual machine, but it isolates only at the process level.
- An image is an immutable template; a container is a running instance of an image (one image, many containers).
- Docker solves the "works on my machine" problem: dev, staging, and production run from a single image.
- An image is described by a
Dockerfileand is reproducible on any machine. - Basic operations:
docker run,docker ps,docker stop,docker rm.
What to read next
- Images and the Dockerfile — how image layers are structured and how to write your first
Dockerfile. - Containers: running and managing them —
docker runflags, environment variables, ports, and the container lifecycle. - Spring Boot in a container — we'll package a real Spring Boot application into an image step by step.