| | |

LFCA 75 🐧 What Docker Is

Docker is a platform for packaging, distributing, and running applications in isolated environments called containers. It was released in 2013 and is built on Linux kernel features — namespaces and control groups — that existed long before Docker existed. What Docker did was make those features accessible through a consistent toolchain and a standard packaging format. The result is an application that runs the same way on a developer’s laptop, a test server, and a production cluster.

The LFCA exam places Docker under DevOps Fundamentals, which carries 12–16% of the total weight. The competencies include “Containers” and “DevOps Basics”. Docker is the reference implementation of containerization, and understanding it is the prerequisite for every container orchestration tool that follows.

Key point: A container is not a small virtual machine. A VM virtualizes hardware and includes a full guest operating system with its own kernel. A container virtualizes the operating system and shares the host kernel. It contains only the application and its user-space dependencies. This is why containers start in milliseconds, consume megabytes, and achieve far higher density than VMs.


Why Docker exists

Before Docker, deploying an application meant manually installing its dependencies on a server. The application worked on the developer’s machine and failed in production because the two environments were subtly different. Docker solves that problem by packaging the application and its dependencies into a single artifact that runs identically everywhere.

The environment drift problem. A Node.js application depends on a specific version of Node, a set of npm packages, and certain system libraries. On the developer’s laptop, those are installed manually. On the production server, they are installed differently, or not at all. Docker packages the exact version of Node and the exact dependencies into the image. The production server runs the same image that the developer ran locally.

The density problem. A virtual machine includes a full operating system. Running ten VMs means running ten operating system instances, each consuming gigabytes of disk and hundreds of megabytes of RAM just for the OS itself. A container shares the host kernel and contains only the application layer. A single host can run dozens or hundreds of containers where it might run a handful of VMs. This density directly reduces infrastructure cost.

The speed problem. A VM takes minutes to boot because it must load a full operating system. A container starts in milliseconds because there is no OS to boot — just a process to launch. This speed enables rapid scaling, fast CI/CD pipelines, and development workflows where containers are created and destroyed constantly.

The distribution problem. A Docker image can be pushed to a registry and pulled by anyone with access. The image is the unit of distribution, and it includes everything needed to run the application. There is no install script, no dependency resolution, no “make sure you have X installed first.” The image is self-contained.

The trade-off. Containers share the host kernel, so they provide weaker isolation than VMs. A kernel vulnerability could allow a container to affect the host or other containers. Containers also cannot run a different operating system than the host — a Linux host runs Linux containers, a Windows host runs Windows containers. For workloads that need strong isolation or a different kernel, VMs remain the right choice.


a. Images and Containers

A Docker image is a read-only template that contains the application code, its dependencies, and the instructions for running it. A container is a running instance of an image. The relationship is the same as a class and an object, or a recipe and a baked cookie.

An image is built from a Dockerfile. The Dockerfile is a text file with instructions that describe the build process. Each instruction creates a layer. Layers are cached, so rebuilding an image after changing only the application code reuses the layers that did not change.

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

The FROM instruction selects the base image — node:20-alpine is a minimal Linux image with Node.js 20 installed. The WORKDIR sets the working directory inside the container. COPY copies files from the build context into the image. RUN executes a command during the build. CMD specifies the command that runs when the container starts.

The image is built with docker build:

docker build -t my-app:1.0 .

The -t flag assigns a name and tag. The . specifies the build context — the directory containing the Dockerfile and the application files. The result is an image stored locally, ready to run.

A container is created and started with docker run:

docker run -d -p 3000:3000 --name my-app my-app:1.0

The -d flag runs the container in the background. The -p flag maps port 3000 on the host to port 3000 in the container. The --name flag assigns a name. The container is a running process, isolated from the host and from other containers.


b. The Docker Architecture

Docker uses a client-server architecture. The Docker client is the command-line tool that the user interacts with. The Docker daemon is the background service that does the work. The two communicate through a REST API.

The Docker client (docker) sends commands to the daemon. When you run docker run, the client sends the request to the daemon, which creates the container.

The Docker daemon (dockerd) listens for API requests and manages Docker objects: images, containers, networks, and volumes. It pulls images from registries, builds new images, and starts and stops containers.

A Docker registry stores images. Docker Hub is the default public registry, and Docker looks for images there by default. Private registries can be run for internal images. When you run docker pull, the daemon fetches the image from the registry. When you run docker push, it uploads the image to the registry.

Docker Desktop is an application for Mac, Windows, and Linux that bundles the daemon, client, Docker Compose, and Kubernetes into a single installable package. It is the standard way to run Docker on a development machine.

Docker Compose is a tool for defining and running multi-container applications. A docker-compose.yaml file describes the services, networks, and volumes, and docker compose up starts everything.


c. Core Docker Objects and Commands

Docker manages several types of objects. Images and containers are the primary ones. Volumes provide persistent storage that survives container restarts. Networks allow containers to communicate with each other and with the host.

A volume is the mechanism for persisting data. Containers are ephemeral by default — when a container is removed, its writable layer is destroyed. A volume is a directory that is mounted into the container and managed by Docker. Data written to the volume survives the container’s lifecycle.

A network is how containers communicate. Docker creates a default bridge network for containers on the same host. Custom networks allow containers to resolve each other by name. Port mapping (-p) exposes a container’s port to the host.

The essential commands are:

# Pull an image from a registry
docker pull ubuntu

# List local images
docker images

# Create and run a container
docker run -it ubuntu /bin/bash

# List running containers
docker ps

# List all containers (including stopped)
docker ps -a

# Stop a running container
docker stop <container-id>

# Start a stopped container
docker start <container-id>

# Remove a container
docker rm <container-id>

# Remove an image
docker rmi <image-id>

# View container logs
docker logs <container-id>

# Execute a command in a running container
docker exec -it <container-id> /bin/bash

The docker run -it ubuntu /bin/bash command starts an Ubuntu container and opens an interactive shell inside it. The -i flag keeps stdin open, and -t allocates a pseudo-terminal. This is how you explore a container’s filesystem and run commands inside it.


Complete Example Session

This session builds a containerized Node.js application, runs it, and demonstrates the core Docker commands.

# ============================================
# PART 1: THE APPLICATION
# ============================================

# Create the project directory
mkdir quote-api && cd quote-api

# Create a minimal Node.js server
cat > server.js <<'EOF'
const http = require('http');
const quotes = [
  "The best way out is always through.",
  "Simplicity is the soul of efficiency.",
  "Make it work, make it right, make it fast."
];

const server = http.createServer((req, res) => {
  const quote = quotes[Math.floor(Math.random() * quotes.length)];
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end(quote + '\n');
});

server.listen(3000, () => console.log('Server on port 3000'));
EOF

# ============================================
# PART 2: THE DOCKERFILE
# ============================================

cat > Dockerfile <<'EOF'
FROM node:20-alpine
WORKDIR /app
COPY server.js .
EXPOSE 3000
CMD ["node", "server.js"]
EOF

# ============================================
# PART 3: BUILD THE IMAGE
# ============================================

docker build -t quote-api:1.0 .
# Sending build context to Docker daemon
# Step 1/5 : FROM node:20-alpine
# Step 2/5 : WORKDIR /app
# Step 3/5 : COPY server.js .
# Step 4/5 : EXPOSE 3000
# Step 5/5 : CMD ["node", "server.js"]
# Successfully built abc123
# Successfully tagged quote-api:1.0

# ============================================
# PART 4: RUN THE CONTAINER
# ============================================

docker run -d -p 3000:3000 --name quote-api quote-api:1.0

# Verify it is running
docker ps
# CONTAINER ID   IMAGE           COMMAND                  PORTS
# a1b2c3d4e5f6   quote-api:1.0   "node server.js"         0.0.0.0:3000->3000/tcp

# ============================================
# PART 5: TEST THE APPLICATION
# ============================================

curl http://localhost:3000
# The best way out is always through.

# ============================================
# PART 6: VIEW LOGS
# ============================================

docker logs quote-api
# Server on port 3000

# ============================================
# PART 7: EXECUTE A COMMAND INSIDE THE CONTAINER
# ============================================

docker exec -it quote-api /bin/sh
# Inside the container:
ls
# server.js
node --version
# v20.x.x
exit

# ============================================
# PART 8: STOP AND REMOVE
# ============================================

docker stop quote-api
docker rm quote-api

# The image remains
docker images
# REPOSITORY    TAG       IMAGE ID       SIZE
# quote-api     1.0       abc123         50MB

# ============================================
# PART 9: THE LAYER CACHE
# ============================================

# Modify server.js
echo "// comment" >> server.js

# Rebuild — only the COPY layer and below are rebuilt
docker build -t quote-api:1.1 .
# The FROM and WORKDIR layers are cached.
# Only COPY and CMD are re-executed.

# ============================================
# PART 10: THE VOLUME FOR PERSISTENCE
# ============================================

# Create a volume
docker volume create app-data

# Run a container with the volume mounted
docker run -d \
  -v app-data:/data \
  --name data-container \
  alpine \
  sh -c "echo 'persistent' > /data/file.txt && sleep 3600"

# The data survives even if the container is removed
docker rm -f data-container

# Verify the data persists in a new container
docker run --rm -v app-data:/data alpine cat /data/file.txt
# persistent

The ten parts cover the application, the Dockerfile, the build, the run, testing, logs, exec, stop and remove, the layer cache, and volumes.


Quick Reference

The Docker Objects

ObjectPurpose
ImageRead-only template for containers
ContainerRunning instance of an image
DockerfileText file with build instructions
RegistryStorage for images (Docker Hub, ECR, GCR)
VolumePersistent storage for container data
NetworkCommunication between containers

The Essential Commands

CommandPurpose
docker pull <image>Download an image
docker imagesList local images
docker build -t <name> .Build an image from a Dockerfile
docker run <image>Create and start a container
docker psList running containers
docker ps -aList all containers
docker stop <id>Stop a container
docker start <id>Start a stopped container
docker rm <id>Remove a container
docker rmi <id>Remove an image
docker logs <id>View container logs
docker exec -it <id> shRun a shell in a container

The Dockerfile Instructions

InstructionPurpose
FROMBase image
WORKDIRSet working directory
COPYCopy files into the image
RUNExecute a command during build
EXPOSEDocument the port
CMDDefault command when container starts

The Container vs VM

AspectContainerVM
VirtualizesOSHardware
KernelSharedSeparate
SizeMBGB
StartupMillisecondsMinutes
IsolationLightweightStrong
DensityHighLow

Best Practices

✅ Do This:

# Use minimal base images
FROM node:20-alpine                                       # ✅
# Copy dependency files first for layer caching
COPY package*.json ./
RUN npm install
COPY . .                                                  # ✅
# Use volumes for persistent data
docker run -v app-data:/data my-app                       # ✅
# Tag images meaningfully
docker build -t my-app:1.0 .                              # ✅
# Clean up unused resources
docker system prune                                       # ✅

❌ Don’t Do This:

# Don't use large base images unnecessarily
FROM ubuntu:latest                                        # ❌ use alpine
# Don't copy everything before installing dependencies
COPY . .
RUN npm install                                           # ❌ breaks cache
# Don't store data in the container filesystem
# Data is lost when the container is removed.            # ❌
# Don't run containers as root without isolation
docker run --privileged my-app                            # ❌

Common Pitfalls

PitfallWhy It HappensFix
Image too largeLarge base image, no multi-stage buildUse alpine, distroless
Build cache invalidatedCOPY before dependency installCopy package files first
Data lost on restartNo volume mountedUse -v
Port not accessibleNo port mappingUse -p host:container
Container exits immediatelyNo foreground processEnsure CMD runs in foreground

Real-World Examples

1. Pull an Image

docker pull nginx

2. Run a Web Server

docker run -d -p 80:80 nginx

3. Interactive Shell

docker run -it ubuntu /bin/bash

4. Build an Image

docker build -t my-app:1.0 .

5. List Containers

docker ps -a

6. View Logs

docker logs my-app

7. Execute in Running Container

docker exec -it my-app /bin/sh

8. Persistent Volume

docker run -v data:/var/lib/postgresql postgres

9. Docker Compose

docker compose up -d

10. Clean Up

docker system prune -a

Visual

The Docker Architecture

┌──────────────────────────────────────────────┐
│  DOCKER ARCHITECTURE                         │
│                                              │
│  ┌─────────────┐                             │
│  │ Docker CLI  │  docker run, build, pull    │
│  └──────┬──────┘                             │
│         │ REST API                           │
│         ▼                                    │
│  ┌─────────────┐                             │
│  │ Docker      │  Manages containers,        │
│  │ Daemon      │  images, networks, volumes  │
│  └──────┬──────┘                             │
│         │                                    │
│  ┌──────▼──────┐                             │
│  │ Docker      │  Pulls/pushes images        │
│  │ Registry    │                             │
│  └─────────────┘                             │
│                                              │
└──────────────────────────────────────────────┘

The Image and Container

┌──────────────────────────────────────────────┐
│  IMAGE vs CONTAINER                          │
│                                              │
│  Dockerfile                                  │
│       │                                      │
│       ▼                                      │
│  docker build                                │
│       │                                      │
│       ▼                                      │
│  IMAGE (read-only)                           │
│    ├─ Layer: FROM node:20-alpine             │
│    ├─ Layer: WORKDIR /app                    │
│    ├─ Layer: COPY . .                        │
│    └─ Layer: CMD ["node", "server.js"]       │
│       │                                      │
│       ▼                                      │
│  docker run                                  │
│       │                                      │
│       ▼                                      │
│  CONTAINER (writable layer on top)           │
│    └─ Running process                        │
│                                              │
└──────────────────────────────────────────────┘

Container vs VM

┌──────────────────────────────────────────────┐
│  CONTAINER vs VM                             │
│                                              │
│  Container:                                  │
│  ┌─────────┐ ┌─────────┐                     │
│  │ App A   │ │ App B   │                     │
│  ├─────────┤ ├─────────┤                     │
│  │ Bins/Libs│ │ Bins/Libs│                   │
│  └────┬────┘ └────┬────┘                     │
│       │           │                          │
│  ┌────▼───────────▼────┐                     │
│  │    HOST KERNEL      │                     │
│  └─────────────────────┘                     │
│                                              │
│  VM:                                         │
│  ┌─────────┐ ┌─────────┐                     │
│  │ App A   │ │ App B   │                     │
│  ├─────────┤ ├─────────┤                     │
│  │ Guest OS│ │ Guest OS│                     │
│  └────┬────┘ └────┬────┘                     │
│  ┌────▼───────────▼────┐                     │
│  │     HYPERVISOR      │                     │
│  └─────────────────────┘                     │
│                                              │
└──────────────────────────────────────────────┘

The Layer Cache

┌──────────────────────────────────────────────┐
│  LAYER CACHE                                 │
│                                              │
│  FROM node:20-alpine    ← cached             │
│  WORKDIR /app           ← cached             │
│  COPY package*.json ./  ← cached             │
│  RUN npm install        ← cached             │
│  COPY . .               ← REBUILT (changed)  │
│  CMD ["node", "server.js"] ← REBUILT         │
│                                              │
│  Only layers after the changed layer         │
│  are rebuilt.                                │
│                                              │
└──────────────────────────────────────────────┘

Summary

ItemValue
Docker definitionPlatform for packaging and running containers
Released2013
ContainerIsolated process sharing host kernel
ImageRead-only template for containers
DockerfileBuild instructions for an image
RegistryStorage for images (Docker Hub default)
Daemondockerd, manages Docker objects
Clientdocker, communicates with daemon
VolumePersistent storage
NetworkContainer communication
LFCA weightDevOps Fundamentals, 12–16%

Key takeaways:

  • Docker is a platform for building, distributing, and running containers. A container is an isolated process that shares the host kernel and contains the application and its user-space dependencies. It is not a virtual machine.
  • An image is a read-only template; a container is a running instance of an image. The image is built from a Dockerfile, stored in a registry, and pulled to the host. The container is created from the image and runs as a process.
  • Docker uses a client-server architecture. The Docker client (docker) sends commands to the Docker daemon (dockerd), which manages images, containers, networks, and volumes. The client and daemon communicate through a REST API.
  • Docker Hub is the default public registry. Images are pulled from and pushed to registries. Private registries can be used for internal images.
  • Containers are ephemeral; volumes provide persistence. Data written to the container’s writable layer is lost when the container is removed. A volume is a directory managed by Docker that survives the container lifecycle.
  • Containers share the host kernel, so they start in milliseconds and consume megabytes. This is the source of their speed and density. It is also the source of their weaker isolation compared to VMs.
  • Docker is the foundation of modern DevOps workflows. It enables consistent environments from development to production, fast CI/CD pipelines, and portable workloads across laptops, data centers, and clouds.

Remember: Docker is the tool that made containers accessible. It packages an application and its dependencies into an image, runs that image as a container, and distributes it through a registry. The container is not a VM — it shares the host kernel and contains only the application layer. This is why it is fast, dense, and portable. The LFCA exam tests the definition, the architecture, the objects, and the distinction from virtual machines. Docker is the entry point to the container ecosystem, and understanding it is the prerequisite for everything that follows.


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!