Zum Hauptinhalt springen
IT BIBLEAnmelden

Blog / Homelab

Late to Docker, and Why I Now Build Almost Everything With It

A short history of Docker, what it was like arriving years after everyone else, and the habits that make containers worth using for home labs and day-to-day builds.

WizardTux
· 6 min read · Homelab
Late to Docker, and Why I Now Build Almost Everything With It

Photo by Mohammad Rahmani on Unsplash

I showed up to Docker years after most of the industry did. Now I build a lot with it, and I wish I had started sooner. This post covers where Docker came from, what changed once I started using it, and a few starting points if you are also arriving late.

A brief history

Docker did not invent containers. It made them easy to use. The ideas underneath had been developing for decades.

  • chroot (1979): Unix introduced a way to change the apparent root directory for a process. It is the ancestor of filesystem isolation.
  • FreeBSD jails (2000): A much fuller form of isolation for processes, files and networking.
  • Solaris Zones (2004): Similar goals on Solaris.
  • Linux cgroups and namespaces (mid-2000s): Control groups limit and account for resources. Namespaces isolate what a process can see, such as process IDs, network interfaces and mount points. Together they are the kernel features modern Linux containers depend on.
  • LXC (2008): A userspace toolset that combined those kernel features into usable containers.

Docker was publicly introduced in March 2013 by Solomon Hykes at PyCon. It came out of dotCloud, a platform-as-a-service company that later renamed itself Docker, Inc. Early versions used LXC under the hood. Docker later moved to its own library for this layer.

What Docker added was the workflow: a simple image format, a Dockerfile to describe how to build one, a registry (Docker Hub) to share images, and a CLI that made all of it feel approachable. Once you could docker pull something and run it in seconds, the idea spread quickly.

A few later milestones matter for context:

  • Fig, a tool for defining multi-container apps, was acquired by Docker and became Docker Compose.
  • Google open sourced Kubernetes in 2014, and orchestration became its own large topic.
  • The Open Container Initiative formed in 2015 to standardize image and runtime formats, so containers are no longer tied to one vendor's tooling.
  • Components such as containerd and runc came out of Docker's internals and are used widely, including by Kubernetes.

Why being late was not a disaster

Arriving after the dust settles has real advantages. The tooling is mature, the documentation is extensive, and the rough edges that early adopters hit have mostly been sanded down. Compose is built into the CLI as docker compose. Official images exist for most common software. Most error messages you will hit have been asked about and answered online.

The cost of being late is mostly psychological. It is easy to feel that you missed the explanation everyone else got, and that makes the first step feel bigger than it is. I was always worried that packages wouldn't stay up-to-date, but once I realized its not really much different than using apt.

The mental model that made it click

If you are new, three terms cover most of what you need:

  • Image: A read-only template containing a filesystem and metadata about how to run it.
  • Container: A running instance of an image, isolated from the host and from other containers.
  • Volume: Storage that lives outside the container's writable layer so data survives when the container is removed.

A container is not a virtual machine. It shares the host kernel, which is why it starts quickly and uses fewer resources. It is also why isolation is weaker than with a full VM, and why you should still think about what you run and with which privileges.

A first Dockerfile

A Dockerfile is a recipe for building an image. Here is a small example for a Python app:

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]

Copying requirements.txt and installing dependencies before copying the rest of the code is deliberate. Docker caches each layer, so dependencies are only reinstalled when that file changes. That one habit saves a lot of build time.

Build and run it:

docker build -t myapp .
docker run --rm -p 8000:8000 myapp

Compose for everything with more than one part

Most real projects need more than one process. Compose lets you describe the whole stack in a single file:

services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      DATABASE_URL: postgres://app:changeme@db:5432/app
    depends_on:
      - db
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: changeme
      POSTGRES_DB: app
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

Then manage it with a few commands:

docker compose up -d
docker compose logs -f web
docker compose down

The passwords above are placeholders. In anything you keep, use secrets or an environment file that stays out of version control.

Habits worth building early

These are the practices that pay off most for people building a lot with containers:

  1. Pin image tags. latest changes under you. Use a specific version so rebuilds are predictable.
  2. Use small base images where practical. Slim or minimal variants reduce size and attack surface, though they can make debugging harder.
  3. Keep data in volumes. Treat containers as disposable and state as something you manage deliberately.
  4. Add a .dockerignore file. It keeps build contexts small and keeps files like .git and local secrets out of images.
  5. Keep Compose files in version control. Your whole environment becomes reproducible and reviewable.
  6. Run as a non-root user inside the container when the application allows it.

What building with Docker has changed

Most of the services that you see here, are either running in docker or kubernetes. It's basically the easiest and fastest way to spin up environments.

The general benefit is hard to overstate. A setup that lives in a Dockerfile and a Compose file can be rebuilt on another machine, shared with a teammate, or thrown away and recreated after a mistake. That removes a lot of the fear from experimenting.

Next step

If you have been putting Docker off, pick one small thing you already run on a server or laptop and containerize it. Write the Dockerfile or Compose file, bring it up, tear it down, and bring it up again. Doing that loop a few times teaches more than reading about it. Being late costs very little, because the tools are in good shape and the path is well marked.

homelabdockercontainersdocker composedevops
Teilen

Have a question about this guide?

Create a free account to ask the community and join the discussion. Members who run the real thing answer every day.

Sign in to comment.