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
| 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
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 form
docker pull docker.io/owner/image-name:latest
# General form
docker pull registry/namespace/image:tagdocker pull nginx
docker pull postgres:16
docker pull redis:7-alpine
docker pull docker.io/library/ubuntu:24.04
docker pull ghcr.io/owner/image:tagPull 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
docker pull image-name:latest
docker 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
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-release
docker 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
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 behavior
docker run image-name
# Start a shell instead of the default application
docker run -it --rm --entrypoint bash image-name
docker run -it --rm --entrypoint sh image-name
# Pass command arguments to the image's default entrypoint behavior
docker run --rm image-name command argsInteractive 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-name
docker run image-nameBind 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
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
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
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
# Host port 8080 maps to container port 80
docker run --rm \
-p 8080:80 \
image-name
# Localhost-only binding on the host
docker 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
| 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
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
Start a temporary shell without mounts to inspect what the image ships by default.
docker run -it --rm \
--entrypoint sh \
image-namecat /etc/os-release
pwd
ls -lah /
ls -lah /opt
find / -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
docker system prune
docker volume ls
docker 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
| 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
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.