跪拜 Guibai
← All articles
Backend · Docker · Containers

Docker from Zero: What Every Flag in `docker run` Actually Does

By Jasper_L ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Most Docker introductions start with abstract concepts; this one anchors every term to a single, real command a developer would actually type. The progression from `docker run` flags to Dockerfile, multi-stage builds, and Compose mirrors the path from quick experiment to production setup, giving a newcomer the full arc in one sitting.

Summary

Starting from a concrete problem — running an Nginx reverse proxy for a local Node.js service without polluting the host — the piece unpacks every flag in `docker run --name my-nginx-demo -p 80:80 -v ... -d nginx`. It explains images as layered, read-only templates; containers as stateless running instances; port mapping as the bridge between host and container network stacks; and bind mounts as the mechanism for injecting host files like `nginx.conf`.

A dedicated section covers the `host.docker.internal` DNS name that Docker Desktop provides so containers can reach services on the host, a common pain point when a reverse proxy runs containerized but the backend does not. The article then builds toward production patterns: writing a Dockerfile for the Node service, using `.dockerignore` to keep images small, multi-stage builds to strip dev dependencies, and Docker Compose to orchestrate both services so they communicate by service name instead of host hacks.

A command-reference table and a side-by-side comparison of containers versus virtual machines round out the piece, making it useful as both a tutorial and a cheat sheet.

Takeaways
An image is a read-only layered template; a container is a stateless running instance of that image — delete the container, lose the data.
`-p 80:80` maps host port 80 to container port 80; without it, the container's network is unreachable from the host.
`-v /host/path:/container/path` injects host files into the container; getting the container-side path wrong silently falls back to defaults.
`host.docker.internal` lets a container reach the host on Docker Desktop; on Linux, use `--add-host` or the bridge gateway IP.
Always pin exact image tags (`nginx:1.25.3`) in production; `:latest` shifts underneath you.
Use `--env-file .env` instead of `-e` for secrets to avoid leaking them into shell history.
Multi-stage builds separate the build environment from the runtime, slashing final image size by excluding dev toolchains.
Docker Compose creates an internal network where containers reach each other by service name, eliminating `host.docker.internal` hacks.
Conclusions

Teaching Docker through a single, flawed command — and then fixing each misconception — is more effective than listing concepts in isolation. The `docker run` invocation becomes a syllabus.

The `host.docker.internal` workaround is a Docker Desktop crutch that vanishes when both services are containerized and placed on the same Compose network, which is the real end state worth aiming for.

Bind mounts are the right call for config injection during development, but the article correctly flags that Volumes are the production choice — a distinction many tutorials blur.

Concepts & terms
Image layering
Docker images are built from stacked, read-only filesystem layers. Each Dockerfile instruction (RUN, COPY) creates a new layer. Layers are cached and shared across images, so rebuilding only touches changed layers and pulling only downloads missing ones.
Bind mount vs. Volume vs. tmpfs
Three Docker persistence mechanisms. Bind mounts map an arbitrary host path into the container (good for dev config injection). Volumes are managed by Docker in `/var/lib/docker/volumes/` and are portable across hosts (good for production databases). tmpfs mounts live in host memory and are lost on reboot (good for temporary secrets).
Multi-stage build
A Dockerfile pattern using multiple FROM statements. The first stage installs build toolchains and compiles artifacts; later stages copy only the runtime artifacts, discarding compilers and dev dependencies. Final images contain only what the app needs to run.
host.docker.internal
A special DNS name provided by Docker Desktop (Windows/macOS) that resolves to the host machine's IP from inside a container. It lets a containerized process reach a service running directly on the host. Not available by default on Linux; use `--add-host` or the bridge gateway IP instead.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗