Docker

Docker - Medium

Page 2 of 2

Health Checks

By default, Docker only knows whether a container's main process is still running - not whether the app inside is actually working correctly. A process can be alive and completely broken at the same time (stuck, deadlocked, unable to reach its database). A HEALTHCHECK tells Docker how to actually ask.

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:3000/health || exit 1
docker ps      # a healthy/unhealthy container shows its current health status here

This matters a lot more once you're running multiple containers or an orchestrator like Kubernetes - "is this actually ready to receive traffic" is a genuinely different question from "is the process still alive," and health checks are how you answer it.


Resource Limits

Without limits, a single container with a memory leak or a runaway process can consume the entire machine's resources and take down everything else running alongside it - including containers that had nothing to do with the problem.

docker run --memory=512m --cpus=1 my-app

If a container exceeds its memory limit, it gets killed (an OOMKilled event, which you'll see referenced constantly once you're debugging containers in production) rather than being allowed to take the whole host down with it. Setting limits, even generous ones, is one of the cheapest ways to make a multi-container setup more resilient.


Logging

The convention in container-land is that your app should write its logs to stdout/stderr - the same output you'd see if you ran it directly in a terminal - rather than to a log file somewhere inside the container's own filesystem.

docker logs my-container
docker logs --since 10m my-container       # only logs from the last 10 minutes

The reason this convention exists: Docker (and every orchestrator built on top of it) already knows how to capture and forward stdout/stderr to a central place. A log file buried inside a disposable container's filesystem just disappears the moment that container is removed - exactly the kind of thing you'd want to look at after something went wrong.


Docker Registries

A registry is where images live so they can be shared - Docker Hub is the default public one, but plenty of teams run a private registry for their own images.

docker tag my-app myregistry.example.com/my-app:1.0
docker push myregistry.example.com/my-app:1.0
docker pull myregistry.example.com/my-app:1.0

The naming convention - registry/repository:tag - is worth internalizing early, since almost every real deployment pipeline is built around exactly this pattern: build an image, tag it, push it somewhere, pull it from there onto whatever's actually running it.


Restart Policies

What should Docker do if a container crashes, or if the whole machine reboots? By default: nothing - it just stays stopped. A restart policy changes that.

docker run --restart=unless-stopped my-app
  • no (the default) - never restart automatically.
  • on-failure - restart only if it exited with an error.
  • always - always restart, even after a reboot.
  • unless-stopped - like always, but respects it if you deliberately stopped the container yourself.

unless-stopped is the one you'll reach for most often in practice - it recovers from crashes and reboots without fighting you when you actually meant to stop something.

    Welcome to OpsQuiz!

    Real scenario-based DevOps questions, hands-on practice, and clear explanations for every answer.