Docker Containers
Learn the complete lifecycle of Docker containers - create, run, inspect, manage, and clean them up. The hands-on foundation for everything else in Docker.
What Is a Docker Container?
A container is a running instance of a Docker image. If an image is a blueprint, a container is the building constructed from it. You can run dozens of containers from the same image - each fully isolated, each with its own process space, filesystem, and network interface.
Containers vs. Virtual Machines
Both technologies provide isolation, but they do it very differently:
| Container | Virtual Machine | |
|---|---|---|
| Startup time | Milliseconds | Minutes |
| Disk usage | MBs | GBs |
| OS | Shared host kernel | Full guest OS |
| Isolation | Process-level | Hardware-level |
| Portability | Very high | Moderate |
Containers are lightweight because they share the host OS kernel - there's no guest OS to boot. Each container gets its own isolated view of the filesystem, network, and processes.
The Container Lifecycle
A container moves through well-defined states:
Docker Container Lifecycle
Both stop and kill lead to stopped — but stop sends SIGTERM first
Understanding this lifecycle is essential for managing containers in development and production.
Quick Start
The most common way to create and start a container in one command:
# Run nginx, map port 8080 on host to 80 in container
docker run -d -p 8080:80 --name my-nginx nginx
# Visit http://localhost:8080 to see it running
Flag breakdown:
-d- detached mode (run in background)-p 8080:80- publish port:hostPort:containerPort--name my-nginx- give it a memorable name
What's Covered in This Section
This section is split into focused subsections, each covering a key area of container management:
| Subsection | What You'll Learn |
|---|---|
| Running Containers | docker run flags, detached vs interactive, port mapping |
| Lifecycle | start, stop, restart, pause, kill - and when to use each |
| Exec & Interact | Shell into containers, run commands, debug live containers |
| Logs & Monitoring | Stream logs, filter output, inspect resource usage |
| Networking Basics | Container networking, DNS, port publishing, container communication |
| Volumes & Storage | Persist data, bind mounts vs named volumes |
| Env Vars & Config | Pass configuration into containers safely |
| Cleanup & Pruning | Remove stopped containers, reclaim disk space |
Each subsection has interactive exercises so you can practice the commands as you learn them.
Containers Are Ephemeral by Design
One of the most important mental shifts in Docker: containers are disposable. Any data written inside a container's filesystem is lost when the container is removed. This is intentional - it keeps containers stateless and replaceable.
For data that must survive container restarts and removals, use volumes (covered in the Volumes & Storage subsection).
# This data is LOST when the container is removed
docker run alpine sh -c "echo 'hello' > /data/file.txt"
# This data PERSISTS via a named volume
docker run -v mydata:/data alpine sh -c "echo 'hello' > /data/file.txt"
Your First Container
Try it now - run an interactive Alpine container:
Run Your First Container
ConceptRun an Alpine Linux container interactively, print 'Hello from Docker!', then exit.
Key Concepts to Keep in Mind
Each container is isolated - changes inside one container don't affect others or the host (unless you use volumes or bind mounts).
Containers are fast - starting a container typically takes under a second. Don't be afraid to stop and recreate them.
Names are optional but helpful - without --name, Docker assigns a random name like festive_einstein. Named containers are much easier to manage.
One process per container - the Docker philosophy is one concern per container. A web app container shouldn't also run a database. Use Docker Compose (covered later) to wire multiple containers together.
Let's dig into each topic, starting with the most important command you'll use daily: docker run.