Hands-on, evergreen guides for developers. Each one is built around real commands and worked examples, and says plainly when not to use the thing it covers.
Browse everything below, newest first.
Hands-on, evergreen guides for developers. Each one is built around real commands and worked examples, and says plainly when not to use the thing it covers.
Browse everything below, newest first.
You pull the latest main and Git stops with CONFLICT (content): Merge conflict in checkout.js. You resolve it, and the log now shows a commit called Merge branch 'main' into feature/checkout sitting on top of the three commits you actually wrote. Four commits, one real change. A teammate reading that history next month can’t tell which is which. git merge and git rebase both answer the same question: how do I bring my branch up to date with changes made elsewhere. They leave very different traces behind, and picking the wrong one on a shared branch causes real damage. ...
Ask a general-purpose LLM about your company’s refund policy or last week’s support tickets, and it will either say it doesn’t know or invent something plausible. Its knowledge stops at whatever was in its training data. It has never seen your documents, and it cannot go and look them up mid-conversation. Retrieval-augmented generation (RAG) is the fix: before the model answers, a separate step finds the relevant text in your own data and hands it to the model as part of the prompt. ...
docker build && docker push from your laptop works until someone else has to ship the same image, or it has to happen on every merge without you at the keyboard. GitHub Actions runs that build on GitHub’s runners, tags the image from whatever triggered the workflow, and pushes it to a registry your deploy step can pull from. Nothing runs locally. What it takes to build and push a Docker image from CI Five pieces have to be in place before a runner can push an image: ...
Run kubectl run nginx --image=nginx:1.27 and Kubernetes creates exactly one Pod named nginx. Delete it with kubectl delete pod nginx and it is gone for good — nothing notices, nothing replaces it. A Pod is the smallest deployable unit in Kubernetes: one or more containers that share a network namespace and a set of volumes, scheduled together onto a single node. That single Pod is a dead end in production. If the container inside it crashes, the kubelet restarts the container in place. If the node reboots, or someone deletes the Pod, nothing recreates it. A bare Pod has no memory of the fact that it is supposed to exist. ...
Where a container’s environment variables end up Start a container with -e DB_PASSWORD=hunter2 and run docker inspect on it: 1 2 docker run -d --name api -e DB_PASSWORD=hunter2 nginx:alpine docker inspect --format '{{json .Config.Env}}' api 1 ["DB_PASSWORD=hunter2","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"] The password sits there in plain text, readable by anyone with access to the Docker socket, by docker exec api env, and by any process running inside the container. That is not a bug — it is what environment variables are for. The problem is using them for values that should never be that visible. ...
Why a Docker image ends up ten times bigger than the app A Node service with a few hundred kilobytes of source code ships as an image over 1 GB. That is the normal outcome of a working build, not a mistake anyone made on a particular line. The weight comes from a base image carrying a full OS, a build toolchain the running app never calls, and a package manager cache nobody told the build to delete. ...
What a bad Dockerfile costs you 1 2 3 4 5 6 FROM node:latest COPY . . RUN npm install CMD ["node", "server.js"] Four lines, and every one of them costs you something. docker build re-runs npm install on every code change, because COPY . . breaks the layer cache before the install step ever gets a chance to be reused. The final image carries the full Debian base, the entire node_modules tree including dev dependencies, and whatever build tools npm install pulled in to compile native modules. Nothing is discarded. The container runs as root, because nothing tells it not to, and node:latest means the base image can change under you between one build and the next, with no record of what you actually shipped. ...
Why two containers on the same host can’t reach each other by default Start Postgres and your API with plain docker run and the API cannot reach the database, even though both containers sit on the same machine. 1 2 docker run -d --name db postgres:16 docker run -d --name api myapp Both land on Docker’s default bridge network, where every Docker container goes unless you say otherwise. They get IP addresses. What they don’t get is any way to find each other by name, so the API would have to hardcode the database’s internal IP — an address that changes every time the container restarts. ...
The problem Compose solves A real application is rarely one container. A web API needs a database, the database needs a volume so its data survives a restart, and then you add a Redis cache and a background worker. That is four docker run commands, each with its own flags for ports, volumes, environment variables and a shared network. In the right order. Every time you sit down to work. ...
Docker and Podman run the same images with the same commands. What separates them is architecture: Podman has no background daemon and runs rootless by default, while Docker brings the mature tooling, Docker Desktop, and first-class Compose. Below, the differences that actually affect your work — daemon, root, Compose, and pods. What is Podman? Podman (Pod Manager) is a tool for managing containers and pods, developed by Red Hat as an open source alternative to Docker. Its main feature? It doesn’t need a daemon running. ...