Docker
Docker is a platform for building, shipping, and running applications in containers. It standardises the packaging of an application and all its dependencies — runtime, libraries, environment variables, configuration — into a single portable unit that runs identically on any machine with the Docker Engine installed.
Core concepts
flowchart LR
df[Dockerfile] -->|docker build| img[Image]
img -->|docker run| c1[Container A]
img -->|docker run| c2[Container B]
img -->|docker push| reg[(Registry\nDocker Hub)]
reg -->|docker pull| img2[Image on\nanother host] Dockerfile : A text file containing step-by-step instructions for building an image. Each instruction creates a new read-only layer.
Image : An immutable snapshot built from a Dockerfile. Images are the artifact that gets versioned, pushed to a registry, and shipped.
Container : A running instance of an image. Containers are isolated processes on the host OS — they share the kernel but have their own filesystem, network, and process namespace.
Registry : A server that stores and distributes images. Docker Hub is the default public registry. Private registries (AWS ECR, GitHub Container Registry, GitLab Registry) are used for proprietary images.
Dockerfile
A Dockerfile defines the environment the application runs in. Each instruction adds a layer to the image:
# Base image — choose the smallest that fits
FROM eclipse-temurin:21-jre-alpine
# Working directory inside the container
WORKDIR /app
# Copy the built artifact from the host
COPY target/app.jar app.jar
# Expose the port the application listens on (documentation only)
EXPOSE 8080
# Command to run when the container starts
ENTRYPOINT ["java", "-jar", "app.jar"]
Multi-stage builds
Multi-stage builds separate the build environment from the runtime environment, producing a smaller final image:
# Stage 1: build
FROM maven:3.9-eclipse-temurin-21 AS builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline # cache dependencies separately
COPY src ./src
RUN mvn package -DskipTests
# Stage 2: run — only the JRE, no Maven, no source
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /build/target/app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
The final image contains only the JRE and the compiled JAR — Maven and the source tree are discarded.
Essential commands
Managing containers
| Command | Description |
|---|---|
docker run <image> | Create and start a container from an image |
docker run -d <image> | Run in detached (background) mode |
docker run -p 8080:8080 <image> | Map host port 8080 → container port 8080 |
docker run --name myapp <image> | Assign a name to the container |
docker ps | List running containers |
docker ps -a | List all containers (including stopped) |
docker stop <container> | Gracefully stop a running container |
docker rm <container> | Remove a stopped container |
docker exec -it <container> sh | Open an interactive shell in a running container |
docker logs <container> | Stream container logs |
docker logs -f <container> | Follow logs in real time |
docker inspect <container> | Full JSON metadata for a container |
Managing images
| Command | Description |
|---|---|
docker build -t myapp:1.0 . | Build an image from the Dockerfile in the current directory |
docker images | List local images |
docker pull <image> | Download an image from the registry |
docker push <image> | Push an image to the registry |
docker rmi <image> | Remove a local image |
docker tag <image> <new-tag> | Tag an image with a new name |
Housekeeping
| Command | Description |
|---|---|
docker system prune | Remove stopped containers, dangling images, unused networks |
docker volume ls | List volumes |
docker network ls | List networks |
Networking
Each container gets its own network namespace. Docker provides several network drivers:
| Driver | Description |
|---|---|
bridge (default) | Containers on the same bridge network can communicate by container name |
host | Container shares the host's network stack (no isolation) |
none | No network access |
When using Docker Compose, all services share a default bridge network automatically and can reach each other by their service name as the hostname.
Volumes
Containers are ephemeral — data written inside a container is lost when the container is removed. Volumes persist data beyond the container lifecycle:
# Named volume (managed by Docker)
docker run -v mydata:/var/lib/postgresql/data postgres
# Bind mount (maps a host directory)
docker run -v /host/path:/container/path myapp
Named volumes are preferred in production because Docker manages their location. Bind mounts are useful during development to reflect local file changes without rebuilding the image.
-
Docker Hub — public image registry ↩