Skip to main content
Docker packages your application and its dependencies into a portable, self-contained unit called a container. Containers share the host OS kernel but are isolated from each other through Linux namespaces and cgroups—lighter than virtual machines but just as reproducible. Whether you are running a single Spring Boot service or orchestrating a dozen microservices with Compose, Docker ensures that what works on your laptop works in production. This page walks you through everything from pulling your first image to building multi-stage Dockerfiles and pushing to a private registry.

Core Concepts

Images, containers, and registries

An image is a read-only, layered filesystem template—think of it as a class in object-oriented programming. A container is a running instance of an image—the object. You can start many containers from the same image, each with its own isolated process space, filesystem, and network. Images are built from layers stacked on top of a base image using the Union File System. Each Dockerfile instruction adds a new layer. Layers are cached and reused across builds and across images that share the same base, which keeps storage costs low.
A registry stores and distributes images. Docker Hub is the public default. You can also run a private registry inside your own infrastructure (covered in the final section).

Docker daemon and client

The Docker daemon (dockerd) runs as a background service and manages images, containers, networks, and volumes. The Docker client (docker) is the CLI you interact with—it sends API requests to the daemon over a local socket or TCP.

Essential Commands

Service management

Working with images

Managing containers

Common flags

Enable auto-restart for a container that already exists:

Writing Dockerfiles

A Dockerfile is a text file containing instructions that build an image layer by layer. Each instruction creates a new layer; layers are cached so unchanged steps are skipped on subsequent builds.

Core instructions

CMD vs ENTRYPOINT

  • CMD sets the default command. It can be overridden by arguments passed to docker run.
  • ENTRYPOINT sets the executable that always runs. Arguments from docker run are appended to it rather than replacing it.
A common pattern combines both: ENTRYPOINT sets the executable, CMD provides default arguments that you can override:

Multi-stage builds

Multi-stage builds let you compile code in one image and copy only the output into a smaller runtime image. This keeps your final image lean and free of build tools:
Build the image:

Deploying a Spring Boot app

Docker Compose

Running one container is simple. Running a whole microservice stack—app server, database, cache, reverse proxy—requires coordinating startup order, shared networks, and volume mounts. Docker Compose manages all of this from a single docker-compose.yml file.

Example: nginx + Spring Boot app

A minimal nginx reverse-proxy config (./nginx/conf.d/default.conf):

Core Compose commands

Named volumes

Volumes persist data beyond the lifecycle of a container. Declare them explicitly so Compose manages them:
Reference an externally created volume:

Networking

Bridge network (default)

Containers on the same default bridge network can reach each other by IP address. However, the IP address of a container can change between restarts, so hard-coding IPs in application config is fragile.

Custom bridge network

Custom networks assign DNS names equal to container names. Any container on the same custom network can reach another by its container name or alias:
With aliases, a container can be reached by multiple names:

Host network

A container with --network host shares the host’s network stack. There is no isolation—the container binds directly to host ports. This maximizes performance but prevents running multiple containers that use the same port.

Overlay network

Overlay networks span multiple Docker hosts (used with Docker Swarm or as a building block for Kubernetes). They let containers on different machines communicate as if they were on the same local network.

Network management commands

Private Registry

Docker Hub is public by default. For proprietary images, you can run a private registry using the official registry image.

Set up the registry

Tell the Docker daemon to trust your insecure (HTTP) registry by editing /etc/docker/daemon.json:
Restart the daemon:

Push an image to the private registry

Pull from the private registry

Authenticate with Docker Hub before pushing

If you are pushing to Docker Hub (not a private registry), you must tag images with your Docker Hub username and log in first:
The image name on Docker Hub must start with your username. Pushing without the correct prefix will fail with denied: requested access to the resource is denied.