Moved homelab-mastery repo content into homelab-mastery/ subdirectory. Covers architecture, concepts, certifications, interview-prep, and learning-path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
126 lines
5.2 KiB
Markdown
126 lines
5.2 KiB
Markdown
# Docker — What It Actually Is
|
|
|
|
## The Wrong Mental Model
|
|
|
|
Most people think containers are "mini virtual machines." They're not. Understanding the real model is what makes Docker make sense.
|
|
|
|
## What a Container Actually Is
|
|
|
|
A container is a **process** (or group of processes) running on the host Linux kernel, with two things applied:
|
|
|
|
1. **Namespaces** — isolation. The process gets its own view of the filesystem, network, processes, users. It can't see other containers' processes.
|
|
2. **cgroups (control groups)** — resource limits. The process is limited to a certain amount of CPU, RAM, etc.
|
|
|
|
That's it. There's no second kernel. No hypervisor. No hardware emulation. The nginx running in your `homepage` container is a regular Linux process on your laptop — it just *thinks* it's alone.
|
|
|
|
This is why containers start in milliseconds (no boot) and use almost no overhead.
|
|
|
|
## Images vs Containers
|
|
|
|
| Concept | Analogy | What it is |
|
|
|---------|---------|-----------|
|
|
| **Image** | A recipe | A read-only template — filesystem layers, default command, environment |
|
|
| **Container** | A meal cooked from that recipe | A running instance of an image — has its own writable layer on top |
|
|
|
|
You can run 10 containers from the same image. They all share the read-only image layers and each gets their own writable layer on top. If a container is deleted, its writable layer is gone. The image remains.
|
|
|
|
When you run `docker compose up -d`, Docker:
|
|
1. Pulls the image if not already local
|
|
2. Creates a container (adds writable layer)
|
|
3. Attaches it to the specified networks
|
|
4. Mounts the volumes
|
|
5. Starts the process defined in the image's CMD or your compose override
|
|
|
|
## Docker Networks — Why the `kitestacks` Network Exists
|
|
|
|
Docker creates several default networks. Containers on the **same network** can reach each other by **container name** (Docker has its own DNS built in).
|
|
|
|
In this homelab:
|
|
```
|
|
docker network create kitestacks
|
|
```
|
|
|
|
Every container joins this network. So when cloudflared routes traffic for `www.kitestacks.com`, it resolves `homepage` via Docker DNS to the container's IP on the `kitestacks` network. Without this shared network, cloudflared can't find the other containers.
|
|
|
|
```
|
|
cloudflared container → DNS lookup "homepage" → 172.x.x.x (homepage container)
|
|
```
|
|
|
|
**`network_mode: host`** is different — the container shares the HOST's network namespace entirely. No isolation. Used for the metrics API so it can read actual host network stats.
|
|
|
|
## Volumes — Keeping Data When Containers Are Deleted
|
|
|
|
Containers are ephemeral — their writable layer is deleted when the container is removed. To persist data:
|
|
|
|
**Bind mount:** Links a host directory to a container path.
|
|
```yaml
|
|
volumes:
|
|
- ./data:/forgejo-data
|
|
```
|
|
`./data` on your laptop → `/forgejo-data` inside container. Data lives on your laptop. You can browse it with `ls`.
|
|
|
|
**Named volume:** Docker manages the storage location.
|
|
```yaml
|
|
volumes:
|
|
- prometheus-data:/prometheus
|
|
```
|
|
Docker stores it in `/var/lib/docker/volumes/prometheus-data/`. You don't specify where.
|
|
|
|
**In this homelab:** Databases, config files, and user data use bind mounts (`./data`, `./config`, etc.) so you know exactly where everything is. Named volumes are used where location doesn't matter (Prometheus metrics, Portainer settings).
|
|
|
|
## Docker Compose — What It's Doing
|
|
|
|
`docker compose up -d` reads `docker-compose.yml` and for each service:
|
|
1. Ensures the image exists (pull if needed)
|
|
2. Creates the network if it doesn't exist
|
|
3. Creates the container with all specified config (env vars, volumes, ports, networks)
|
|
4. Starts the container
|
|
|
|
`-d` means detached — run in background.
|
|
|
|
`restart: unless-stopped` means Docker will restart the container if it crashes or if the host reboots — unless you explicitly stop it with `docker compose stop`.
|
|
|
|
## Port Mappings
|
|
|
|
```yaml
|
|
ports:
|
|
- "3006:3000"
|
|
```
|
|
|
|
`HOST_PORT:CONTAINER_PORT`
|
|
|
|
Port 3000 inside the container is mapped to port 3006 on the host. From the host, `http://localhost:3006` reaches the service. From within the `kitestacks` Docker network, other containers use `http://forgejo:3000` (the container port, via Docker DNS).
|
|
|
|
Cloudflare Tunnel doesn't use host ports — it goes through the Docker network directly using the container name and container port.
|
|
|
|
## Commands to Know Cold
|
|
|
|
```bash
|
|
# See all running containers
|
|
docker ps
|
|
|
|
# See logs for a container
|
|
docker logs forgejo
|
|
docker logs -f forgejo # follow (live tail)
|
|
|
|
# Execute a command inside a running container
|
|
docker exec -it forgejo bash # open a shell
|
|
docker exec forgejo forgejo admin user list # run a specific command
|
|
|
|
# Inspect a container's config
|
|
docker inspect authentik
|
|
|
|
# See all networks
|
|
docker network ls
|
|
docker network inspect kitestacks
|
|
|
|
# See disk usage
|
|
docker system df
|
|
|
|
# Remove unused images/containers/networks
|
|
docker system prune
|
|
```
|
|
|
|
## What to Say About Docker
|
|
|
|
> *"I containerized every service using Docker and Docker Compose. Each service is isolated in its own container with its own dependencies, connected through a shared Docker bridge network named 'kitestacks' so they can communicate by container name. Data is persisted via bind-mounted host directories. The entire stack is defined in version-controlled YAML files, making it reproducible on any Linux host."*
|