Docker Image and Container Mental Model
Use this note as a practical mental model for pulling and running containers. It explains what Docker downloads, what starts at runtime, where data lives, and how common docker run flags change the container.
Image vs container
Section titled “Image vs container”| Concept | Meaning |
|---|---|
| Image | Packaged application template with userland, app files, libraries, dependencies, startup scripts, and default ENTRYPOINT or CMD |
| Container | A running instance created from an image |
| Disposable container | Container removed after exit, usually with –rm |
| Persistent data | Data kept outside the disposable container through bind mounts or named volumes |
Registries and pull
Section titled “Registries and pull”docker pull downloads an image from a container registry. Docker Hub is the default registry when no registry hostname is provided.
docker pull owner/image-name
# Equivalent default formdocker pull docker.io/owner/image-name:latest
# General formdocker pull registry/namespace/image:tagdocker pull nginxdocker pull postgres:16docker pull redis:7-alpinedocker pull docker.io/library/ubuntu:24.04docker pull ghcr.io/owner/image:tagPull vs run
Section titled “Pull vs run”| Command | Effect |
|---|---|
| docker pull image-name | Downloads or updates the image locally |
| docker run image-name | Creates and starts a new container from the image |
| docker run missing-image | Pulls automatically first, then starts the container |
Use explicit docker pull when you want to update the local image before running it.
Tags and layers
Section titled “Tags and layers”docker pull image-name:latestdocker pull image-name:1.2.3- latest is convenient but can change over time.
- Fixed tags are better for stable deployments.
- Images are built in layers such as base distro, system packages, language runtime, app code, and startup scripts.
- docker pull downloads only missing or changed layers.
Container OS and host kernel
Section titled “Container OS and host kernel”The image provides the container userland, such as Debian, Ubuntu, Alpine, or Fedora. The host provides the Linux kernel. An Ubuntu container on an Arch host runs Ubuntu binaries and libraries while sharing the Arch host kernel.
docker run --rm image-name cat /etc/os-releasedocker run --rm image-name uname -a- /etc/os-release shows the container distro.
- uname -a shows the host kernel because Linux containers share the host kernel.
Startup behavior
Section titled “Startup behavior”ENTRYPOINT and CMD define what starts by default when the container runs.
docker inspect image-name --format 'Entrypoint: {{json .Config.Entrypoint}}Cmd: {{json .Config.Cmd}}WorkingDir: {{json .Config.WorkingDir}}'# Use the default image startup behaviordocker run image-name
# Start a shell instead of the default applicationdocker run -it --rm --entrypoint bash image-namedocker run -it --rm --entrypoint sh image-name
# Pass command arguments to the image's default entrypoint behaviordocker run --rm image-name command argsInteractive and disposable runs
Section titled “Interactive and disposable runs”| Flag | Meaning |
|---|---|
| -i | Keep STDIN open |
| -t | Allocate a terminal |
| -it | Use for shells, CLIs, TUIs, REPLs, and interactive agents |
| –rm | Remove the container automatically after it exits |
docker run -it --rm image-namedocker run image-nameBind mounts
Section titled “Bind mounts”A bind mount makes a host path appear inside the container. Reads and writes are bidirectional.
docker run -it --rm \ -v "$HOME/my-data:/data" \ image-name| Host path | Container path |
|---|---|
| $HOME/my-data | /data |
| $HOME/my-data/file.txt | /data/file.txt |
- If the image already has files at /data, the bind mount hides those image files while the mount is active.
- The mounted path is the host folder, not image contents plus host contents.
Named volumes
Section titled “Named volumes”docker volume create app-data
docker run -it --rm \ -v app-data:/data \ image-name| Storage type | Best use |
|---|---|
| Bind mount | Explicit host paths, projects, configs, and local files you want to inspect from the host |
| Named volume | Docker-managed persistent data for databases and app state |
Workspace pattern
Section titled “Workspace pattern”A common project pattern is to mount the current host folder into /workspace and start the container there.
docker run -it --rm \ -v "$PWD:/workspace" \ -w /workspace \ image-nameEnvironment and user
Section titled “Environment and user”docker run --rm \ -e APP_ENV=development \ -e API_KEY="$API_KEY" \ image-namedocker run --rm \ --user "$(id -u):$(id -g)" \ -v "$PWD:/workspace" \ image-name- -e passes environment variables into the container for config, credentials, runtime settings, and user IDs.
- –user runs the process as the host UID and GID, which helps avoid root-owned files in bind-mounted folders.
- Some images use APP_UID and APP_GID style environment variables instead of –user.
Ports and background services
Section titled “Ports and background services”# Host port 8080 maps to container port 80docker run --rm \ -p 8080:80 \ image-name
# Localhost-only binding on the hostdocker run --rm \ -p 127.0.0.1:8080:80 \ image-namedocker run -d \ --name app-name \ --restart unless-stopped \ image-name- -d runs the container in the background.
- –name gives the container a stable name.
- –restart unless-stopped restarts the container after reboot or crash unless it was manually stopped.
Inspect containers
Section titled “Inspect containers”| Command | Use |
|---|---|
| docker ps | Show running containers |
| docker ps -a | Show running and stopped containers |
| docker logs -f container-name | Follow container logs |
| docker exec -it container-name bash | Enter a running container with bash |
| docker exec -it container-name sh | Enter a running container with sh |
| docker inspect container-name | Show container metadata |
Resolve name conflicts
Section titled “Resolve name conflicts”Docker container names are unique across the Docker daemon. A stopped container can still hold a name.
docker ps -a --filter "name=test"docker rm -f testInspect image contents
Section titled “Inspect image contents”Start a temporary shell without mounts to inspect what the image ships by default.
docker run -it --rm \ --entrypoint sh \ image-namecat /etc/os-releasepwdls -lah /ls -lah /optfind / -maxdepth 2 -type d 2>/dev/null | headAdd mounts when you want to compare raw image contents with runtime mounted contents.
docker run -it --rm \ -v "$HOME/my-data:/data" \ --entrypoint sh \ image-nameClean up
Section titled “Clean up”docker system prune
docker volume lsdocker volume rm volume-name- docker system prune removes unused containers, networks, images, and build cache.
- It does not remove active containers.
- Remove named volumes only when you are sure the stored data is no longer needed.
Mount safety
Section titled “Mount safety”| Pattern | Risk |
|---|---|
| -v “$PWD:/workspace” | Safer project-scoped workspace |
| -v “$HOME/safe-folder:/data” | Safer explicit data folder |
| -v “$HOME:/workspace” | Risky because it exposes the whole home directory |
| -v “/:/host” | Risky because it exposes the host root filesystem |
| -v “$HOME/.ssh:/root/.ssh” | Risky because it exposes SSH credentials |
| -v “/var/run/docker.sock:/var/run/docker.sock” | Risky because it gives host-level Docker control |
| –privileged | Very risky because it grants broad container privileges |
| –network host | Very risky because it removes normal network isolation |
Mount only what the container should access.
Reusable run template
Section titled “Reusable run template”docker run -it --rm \ --name app-test \ -e APP_ENV=development \ -v "$HOME/app-data:/data" \ -v "$PWD:/workspace" \ -w /workspace \ image-name:tag- Replace app-test with the container name.
- Replace APP_ENV with the environment variables the image needs.
- Replace $HOME/app-data with a persistent data path if needed.
- Replace $PWD with the project or workspace path.
- Replace image-name:tag with the Docker Hub or registry image.