What is Docker?
Docker is a platform for packaging and running applications in isolated environments called containers. Instead of installing an application's runtime, libraries and dependencies manually on every server, you package what the application needs into a reproducible image.
This solves a classic problem: “It works on my machine.” With Docker, the same image can move from a developer laptop to CI/CD, staging and production with much less environmental drift.
1. Docker Image — the Blueprint
A Docker image is an immutable template used to create containers. It contains the application code, runtime, system libraries and dependencies required to run the application.
Images are normally built from a Dockerfile. They are made of read-only layers, which makes them efficient to store, transfer and reuse.
$ docker images
Think of an image like a class or blueprint. The blueprint itself is not the running application; it is used to create one or more running instances.
2. Container — a Running Instance
A container is a running instance created from an image. Docker adds a thin writable layer on top of the image's read-only layers.
Changes made inside the container — such as creating temporary files — normally live in this writable layer. If the container is removed, those changes disappear unless the data is stored somewhere persistent.
$ docker ps
Image
Read-only, reusable template containing your app and its dependencies.
Container
Running instance of an image with its own writable layer and isolated processes.
3. Volumes — Persistent Data
Containers are designed to be disposable. That is excellent for application deployments, but databases and user uploads need data to survive container replacement.
Docker volumes provide persistent storage managed outside the container's writable layer. If you delete and recreate a container while keeping its volume, the data remains available.
$ docker run -d -v app-data:/var/lib/myapp my-app:1.0
4. Ports — Connecting Traffic
Applications inside containers can listen on ports, but that does not automatically make them reachable through the host. Docker port publishing maps a host port to a container port.
Here, 8080 is the host port and 80 is the container port. A request to the host on port 8080 is forwarded to port 80 inside the container.
Host Port
The port exposed on the Docker host, load balancer or development machine.
Container Port
The port where the application is listening inside the container.
5. Docker Engine and the Host OS
The Docker Engine is the runtime responsible for building images, creating containers, managing networks and handling container lifecycle operations.
On Linux, containers share the host's kernel while maintaining process, filesystem and network isolation. This is one reason containers can be lightweight compared with traditional virtual machines.
6. Containers vs Virtual Machines
Containers and virtual machines both provide isolation, but they operate at different levels.
| Feature | Container | Virtual Machine |
|---|---|---|
| Isolation level | OS/process level | Hardware/OS virtualization |
| Guest OS | Shares host kernel on Linux | Each VM has its own guest OS |
| Startup | Usually very fast | Usually slower |
| Resource usage | Generally lower overhead | Generally higher overhead |
| Typical use | Microservices, APIs, CI/CD | Full OS workloads, strong VM isolation |
Containers are not automatically “better” than VMs. They solve a different problem and are often used together. For example, cloud providers may run container workloads on virtual machines underneath.
7. The Docker Workflow
A common Docker development and deployment workflow looks like this:
01 — Write
Create your application and a Dockerfile describing its runtime environment.
02 — Build
Build a versioned image with docker build.
03 — Run
Create a container with ports, environment variables, volumes and networks.
04 — Deploy
Push the image to a registry and run it on your target infrastructure.
$ docker run -d --name my-api -p 8080:8080 my-api:1.0
$ docker logs my-api
$ docker stop my-api
8. Dockerfile Example
A Dockerfile defines how an image is assembled. For example, a simple Node.js API might look like this:
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]
During a build, Docker creates image layers from these instructions. Dependencies can be cached between builds, which helps make repeated builds faster.
9. Docker Networking
Containers frequently need to communicate with other services such as APIs, databases, Redis or message queues. Docker provides virtual networks so containers can communicate without exposing every service directly to the host.
For example, with Docker Compose, an API can connect to a database using the database service name rather than hard-coding an IP address.
api:
build: .
db:
image: mysql:8.4
# API can connect to: db:3306
10. Docker Compose
When an application has multiple services, running individual Docker commands becomes difficult. Docker Compose lets you define services, networks, volumes, environment variables and dependencies in a YAML file.
frontend:
build: ./frontend
ports:
- "3000:3000"
api:
build: ./api
redis:
image: redis:7-alpine
11. Why Docker is Important in DevOps
Docker fits naturally into modern CI/CD pipelines. A team can build an image once, scan and test it, push it to a container registry, and deploy the same immutable artifact across environments.
Consistency
Reduce differences between development, testing and production environments.
Portability
Package applications in a standardized format that can run across many environments.
Scalability
Run multiple container instances behind a load balancer or orchestrator.
CI/CD
Build, test, scan, publish and deploy versioned container images automatically.
12. Common Docker Commands
| Command | Purpose |
|---|---|
docker build | Build an image from a Dockerfile |
docker images | List local images |
docker run | Create and start a container |
docker ps | List running containers |
docker logs | View container logs |
docker exec | Run a command inside a running container |
docker stop | Stop a container |
docker rm | Remove a container |
docker push | Push an image to a registry |
13. A Real-World Mental Model
Imagine you are deploying a web application with a frontend, backend API, Redis and a database.
The frontend image contains the frontend application and runtime. The API image contains the backend and its dependencies. Each image can be started as one or more containers. Redis and the database can run as separate services. Docker networks allow the services to communicate, while persistent storage protects important database data.
In a production environment, those images can be pushed to a registry such as a private container registry and deployed using an orchestration platform or container service.
Remember These 4 Things
- Image = template / blueprint
- Container = running instance of an image
- Volume = persistent data outside the container lifecycle
- Port mapping = traffic from host to container
Conclusion
Docker becomes much easier once you stop thinking of it as “another server technology” and instead see it as a standardized way to package and run applications.
The key relationship is simple: an image is the blueprint, a container is the running instance, volumes protect persistent data, networks connect services, and ports expose applications to traffic.
Once these concepts are clear, you are ready to move into more advanced topics such as Docker Compose, multi-stage builds, image optimization, container security, CI/CD, Kubernetes and cloud container services.