Skip to content
Preptima

DevOps and cloud fundamentals

What a container actually is, why a pod gets killed, what Terraform state is for, where a cloud bill really comes from, and the practices — promotion, rollback, postmortems, restore rehearsals — that decide whether any of it survives a bad day. Fifty-seven items, twelve worked through.

57 questions

Go deeper on DevOps & Cloud
Standard Sheet View

Containers and images

What is a container, and how is it not a virtual machine?

A container is a normal process on the host kernel, isolated by namespaces — which restrict what it can see — and limited by cgroups, which restrict what it can consume. A virtual machine runs its own kernel on virtualised hardware. That difference explains everything practical: containers start in milliseconds because there is no kernel to boot, they are far denser because they share one, and the isolation is weaker because a kernel vulnerability is shared by every container on the host.

Show me what an image actually is.

Not a filesystem snapshot but a stack of read-only layers, each the diff produced by one build instruction.

FROM node:22-slim          # layer 1: the base
WORKDIR /app
COPY package*.json ./      # layer 2: two small files
RUN npm ci                 # layer 3: node_modules, ~200MB
COPY . .                   # layer 4: your source, ~2MB
CMD ["node", "server.js"]

Each layer is content-addressed, so identical layers are stored once and transferred once no matter how many images share them. A running container adds a thin writable layer on top, and everything written there disappears when the container does — which is why persistence needs a volume and why "it worked until we restarted" is a container-shaped bug.

The build cache follows the same structure: an instruction is only re-executed if it or anything before it changed. That is the reason the two COPY lines above are split. Copying package.json alone before npm ci means a source-only change invalidates layer 4 and reuses the cached layer 3, so the install is skipped entirely.

Reverse those lines — COPY . . before RUN npm ci — and every one-character source change invalidates the install layer, turning a fifteen-second build into a three-minute one. That single ordering decision is the most common Dockerfile review comment there is.

Show me a multi-stage build and what it removes.

Build tools are needed to produce the artefact and are pure liability in the image that runs it.

FROM golang:1.23 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server ./cmd/server

FROM gcr.io/distroless/static-debian12
COPY --from=build /app/server /server
USER nonroot:nonroot
ENTRYPOINT ["/server"]

The first stage has a compiler, a package manager, a shell and the full source tree. The second has one static binary and nothing else. Only the final stage becomes the image, so the result is a few megabytes rather than nine hundred.

Size is the least interesting benefit. The real one is attack surface: a distroless image has no shell, so an attacker who achieves execution inside it cannot run sh, cannot curl a second payload, and cannot use any of the standard tooling. Most container exploitation chains assume a shell exists.

It also cuts vulnerability noise dramatically. A scanner against a full base image reports hundreds of CVEs in packages your service never invokes, and that volume is what causes teams to stop reading scan results at all.

The trade is debuggability: you cannot exec into a shell that is not there. The answer is ephemeral debug containers that attach tooling to a running pod temporarily, rather than shipping the tooling permanently in production.

Why should a container not run as root?

Because the container's root is the host's root in the relevant namespace unless user namespaces are configured, so a container escape starts from the strongest possible position. Running as an unprivileged user costs one line and removes an entire escalation step. The same reasoning covers dropping capabilities, mounting the root filesystem read-only, and refusing privileged mode — each removes a mechanism an attacker would otherwise have available for free.

Why deploy by digest rather than by tag?

Because a tag is a mutable pointer. myapp:1.4.2 can be repushed, and latest is repointed constantly, so the image you tested and the image that starts on a node an hour later may differ with nothing in your history recording it. A digest is the content hash: myapp@sha256:9f2c... is exactly one set of bytes forever. Tags remain useful for humans; deployments should pin the digest, which also makes a rollback a specific, reproducible artefact.

What is the difference between CMD and ENTRYPOINT?

ENTRYPOINT declares the executable the container runs, and CMD supplies default arguments to it — so docker run image --flag appends to the entrypoint rather than replacing it. Using only CMD means any argument passed at run time replaces the whole command, which is convenient for a general-purpose image and wrong for a service, because a stray argument silently starts something else. The other detail is the exec form versus the shell form: the shell form wraps your process in /bin/sh -c, so your application is not PID 1 and does not receive SIGTERM, which quietly breaks graceful shutdown.

What is the difference between a volume and a bind mount?

A bind mount maps a host path into the container, so it depends on that host's layout and is mostly a development convenience. A volume is managed by the runtime or the orchestrator, has a lifecycle independent of any container, and can be backed by network storage that follows a workload between nodes. In an orchestrated environment only the second is meaningful, because a pod rescheduled to another node has no relationship with the previous node's filesystem.

What belongs in an image and what belongs in the environment?

The image holds the application and its dependencies — everything identical across environments. Configuration, endpoints, credentials and feature settings come from the environment at start-up, because otherwise you build a different image per environment and have therefore tested none of the ones you ship. The practical test is whether the same digest can run in staging and production with only its environment differing; if it cannot, something environment-specific has been baked in.