Most people searching for this want a container running inside a minute, and docker run is the quickest way to get one. The slower route is docker create followed by docker start. Both land in the same place.
Every request goes through the docker CLI to the docker daemon, which lives in Docker Engine on Linux or Docker Desktop on Windows and macOS. Each container ends up with its own filesystem, network interface, and process tree.
Docker Docs (2026) document that docker start relaunches a stopped container with all its previous changes intact, because the writable layer survives until the container is removed.
What Is a Docker Container?
Docker takes an image, puts one writable layer on top, and runs the result as an isolated process on the host kernel. That running instance is the container. It starts in seconds because no guest operating system has to boot.
The image underneath is a read-only template and never changes. The writable layer is the part that disappears when the container is removed.
Isolation comes from Linux namespaces and cgroups. Namespaces separate process IDs, hostnames, and IPC, while cgroups cap memory and cpu.
A request passes through a few separate pieces of software before anything runs. The docker CLI sends the create or run command, and dockerd receives it and manages the container. Below that, containerd starts and supervises the process, and runc spawns it with namespaces and cgroups applied.
This model is called containerization. A virtual machine boots its own kernel, but a container shares the host’s.
The Open Container Initiative (OCI) defines the image and runtime formats, so any OCI-compliant runtime starts the same image.
Docker usage reached 71% among respondents in the 2025 Developer Survey, a 17-point jump from 2024 (Stack Overflow, 2025). More Docker statistics cover adoption and usage.
What Do You Need Before Creating a Docker Container?
You need a running Docker daemon, the Docker CLI, and permission to reach the daemon socket. Docker Engine covers Linux, Docker Desktop covers Windows and macOS, and a single docker run hello-world tells you whether the setup works.
Docker Engine or Docker Desktop
| Platform | Install | Backend |
|---|---|---|
| Linux | Docker Engine | Daemon runs natively as root |
| Windows | Docker Desktop | WSL 2 |
| macOS | Docker Desktop | Lightweight Linux VM |
Engine is what you want on servers and CI runners. Desktop makes more sense on a laptop, where the bundled CLI, GUI, and Compose save you some setup.
Docker Desktop also ships for Linux, but Engine alone stays lighter. Full steps live in the guide on how to install Docker.
Verify the Installation
Start with docker version, which prints client and server versions. An error in the server section means the daemon is unreachable. Then docker info shows the storage driver, cgroup version, and container count.
The last test is docker run hello-world. It pulls a small test image, runs it, prints a message, and exits.
If any of that fails, check whether Docker is running before anything else. Then start the service.
On Linux, permission denied on the socket means the user lacks access. Add the user to the docker group with sudo usermod -aG docker $USER, then log out and back in.
The docker group grants root-level privileges (Docker Docs, 2026). On a shared machine, use sudo or rootless mode instead.
How Do You Create a Docker Container With docker run?

The form is docker run [options] image [command]. Docker pulls the image if it is missing, creates the container, and starts it, in that order. Add -d to run it in the background.
The default value of --pull is missing (Docker Docs, 2026). Docker contacts the registry only when the image is not in the local cache.
A container stops when its main process exits. That is why docker run ubuntu returns to the prompt at once.
Here is a first container, built step by step.
- Pull the image with
docker pull nginx:alpine(optional, since run pulls it too). - Run it detached with a port using
docker run --name web -d -p 8080:80 nginx:alpine. - Confirm it runs.
docker pslists the container with status Up. - Test the response with
curl http://localhost:8080, which returns the nginx welcome page.
A few flags come up constantly. -d runs in the background and prints the container ID. -it keeps STDIN open and allocates a pseudo-TTY, which you need for a shell. And --rm removes the container and its anonymous volumes on exit.
Every container starts from a Docker image, so the image name is the only required argument.
Keep the Docker cheat sheet open for the full flag list.
What Is the Difference Between docker create and docker run?
The docker create command builds a container in the created state and stops there. docker run does the same and then starts it. docker start moves a created or stopped container to running.
| Command | Pulls image if missing | State afterward | Typical use |
|---|---|---|---|
| docker create | Yes | created | Pre-stage a configuration |
| docker run | Yes | running | Immediate launch |
| docker start | No | running | Start a created or stopped container |
Create is handy when you want ports, volumes, and variables settled now and the container started later. Run is what you use when you want to watch the output right away, which is most of the time.
Docker Docs show the pair side by side. docker create -it --name mycontainer alpine followed by docker start --attach -i mycontainer equals docker run -it --name mycontainer2 alpine.
The command-group forms docker container create and docker container run behave the same as the short forms.
Volumes initialize during the create phase. So docker run and docker create mount them identically.
How Do You Choose the Image for a Docker Container?
An image reference breaks down into registry, repository, tag, and digest. Pull official images from Docker Hub, pin a version tag or digest instead of latest, and pick Alpine Linux for size or Ubuntu for compatibility.
Tags and Digests
The registry is the host that stores the image, and Docker Hub is the default. The repository is the image name, such as nginx. A tag is a mutable label such as alpine, and latest applies when you give none. The digest is an immutable @sha256: hash of the exact image content.
Tags move. A digest never does. For anything you keep running, pin one of them.
Registries
Docker Official Images cover nginx, Redis, PostgreSQL, Ubuntu, and Alpine Linux. They live on Docker Hub, the default registry.
GitHub Container Registry and Amazon ECR work as alternatives. Prefix the image name with the registry host, such as ghcr.io/owner/image.
A private container registry keeps internal images off the public hub. Pull explicitly with docker pull to fail early on a bad tag.
Then run docker scout cves nginx:alpine to list known vulnerabilities before creating the container.
Alpine Linux or Ubuntu as a Base Image
Alpine gives you a small image footprint and fewer packages to patch. The price is musl libc, so some prebuilt binaries compiled for glibc fail. It also uses apk and ships fewer debugging tools by default.
Ubuntu is the easier choice when something needs to just work. It has glibc, apt, broad package availability, and tooling you probably already know from debugging. It is also larger, and more installed packages means more to update.
How Do You Set Ports, Names, Environment Variables, and Restart Policy?
All of these are flags on the create or run command. -p host:container maps a port, --name names the container, -e sets an environment variable, and --restart picks the restart policy. They combine freely in one command.
Port Mapping
The -p flag publishes a container port on the host. The host port comes first, the container port second, so -p 8080:80 forwards host port 8080 to container port 80. The capital -P publishes every exposed port on a random host port instead.
A busy host port fails with “port is already allocated”. Pick another host port, since the container port stays the same.
Name and Environment Variables
Use --name web to give the container a fixed identifier. Skip it and the daemon assigns a random name such as vibrant\_cannon.
For variables, -e KEY=value sets one and --env-file loads many from a file.
Some images refuse to start without variables. The official PostgreSQL image needs POSTGRES_PASSWORD, as in docker run --name db -e POSTGRES_PASSWORD=change-me -d postgres.
On a user-defined bridge network, other containers reach this one by its name through DNS (Docker Docs, 2026).
Be careful with secrets. Values passed with -e show up in docker inspect. Prefer --env-file and keep that file out of version control.
Restart Policy
| Value | Behavior |
|---|---|
| no | Never restarts (default) |
| on-failure | Restarts after a non-zero exit code, with an optional retry limit |
| always | Restarts on any exit and when the daemon starts |
| unless-stopped | Same as always, except a stopped container stays stopped, even after the daemon restarts |
Docker Docs list no as the default (Docker Docs, 2026). A crash then leaves the container in the exited state until someone starts it.
Entrypoint and User Overrides
--entrypoint replaces the image’s default ENTRYPOINT, and -u sets the username or UID the process runs as.
Use -u 1000:1000 to keep the process from running as root inside the container.
How Do You Persist Data in a Docker Container?
Mount a named volume with -v name:/path or --mount and the data outlasts the container. The writable container layer is deleted with the container, while volumes and bind mounts live outside it.
A volume outlives its container, and Docker never removes it automatically. Removal is a separate step: docker volume rm or docker volume prune.
On Linux, Docker stores volume data under /var/lib/docker/volumes/ on the host. The full breakdown of where Docker volumes are stored covers the host paths.
Named volumes are managed by Docker, so they are easier to back up or migrate. They work for Linux and Windows containers, and a new volume can be pre-populated from the container’s contents. They are a poor fit when the host needs direct access to the files.
Bind mounts map a host directory straight into the container, and host edits appear inside it at once. The catch is that they depend on the host’s directory structure and operating system. There is also a quirk with -v: Docker silently creates a missing host directory, while --mount fails with an error. I prefer the error.
As of Docker Engine 23, the -v flag accepts relative host paths such as -v ./content:/content (Docker Docs, 2026).
Redis stores its data in /data, so docker run -d --name cache -v redisdata:/data redis keeps its data files across removals.
PostgreSQL needs the same treatment, but the data path differs across major versions. Read the image page on Docker Hub for the correct mount point.
Mounting a non-empty volume over a directory hides the files already there. Mounting an empty volume copies those files into the volume by default (Docker Docs, 2026).
Which Network Mode Should a Docker Container Use?
The default bridge network suits one throwaway container. A user-defined bridge is better when containers talk to each other, host mode helps when NAT overhead matters, and none fits a container that needs no network. Each mode trades isolation against convenience.
| Mode | Network isolation | Name lookup between containers | -p flag |
|---|---|---|---|
| bridge (default) | Isolated from other networks | IP address only | Works |
| User-defined bridge | Scoped to attached containers | By name or alias | Works |
| host | None, shares the host stack | Not applicable | Ignored |
| none | Complete | Not applicable | Not applicable |
Docker Docs call the default bridge network a legacy detail and advise against it in production (Docker Docs, 2026). Every container started without --network lands on it, so unrelated containers can reach each other.
User-Defined Bridge Networks
Create the network with docker network create my-net. Start a container on it using docker run -d --name api --network my-net nginx:alpine. To attach one that is already running, docker network connect my-net api works with no restart.
Pulling a container off the default bridge takes a stop and a recreate. User-defined networks connect and disconnect on the fly.
Overlay networks, which span several hosts in swarm mode, turn unstable at 1000 containers co-located on the same host (Docker Docs, 2026).
Host and None Modes
Host mode drops network isolation. The container shares the host network stack and gets no IP address of its own.
The command docker run --rm -d --network host --name my_nginx nginx binds nginx straight to port 80 on the host.
Published ports do nothing here. -p and -P are discarded with a warning. Host mode works with Docker Engine on Linux, or Docker Desktop 4.34 and later after you turn on host networking in Settings, and only for Linux containers.
The none mode isolates the container from the host and from every other container.
Choosing by Workload
A single app is fine on the default bridge with -p. An app plus a database belongs on one user-defined bridge, and there is no reason to publish the database port. For a performance-sensitive service, host mode is worth trying if the host port is free.
Skip host mode on a machine that runs several services on the same port. Two containers cannot bind one host port.
How Do You Limit Container Memory and CPU?
Pass --memory to cap RAM and --cpus to cap processor time when you create the container. Docker applies both through cgroups, and a container without them uses whatever the host kernel scheduler allows.
Memory Limits
--memory sets the hard cap, with a minimum of 6m (Docker Docs, 2026). --memory-swap covers memory plus swap combined, so --memory=300m --memory-swap=1g allows 700m of swap. The soft limit, --memory-reservation, only applies under host memory contention.
Set both hard flags to the same value and the container gets no swap at all.
CPU Limits
On a 2-CPU host, --cpus=1.5 caps the container at one and a half CPUs. Docker Docs list the same cap as --cpu-period=100000 --cpu-quota=150000, and the short flag reads better.
--cpu-shares sets a relative weight, default 1024, enforced only under CPU contention. To pin a container to specific cores, use --cpuset-cpus=0-3.
Put together, it looks like this: docker run -d --name api --memory=512m --memory-swap=512m --cpus=1.5 nginx:alpine.
When a Container Runs Out of Memory
The kernel kills a process inside the container. Exit status 137 means SIGKILL (signal 9) ended it (Docker Docs, 2026).
An OOM kill is one cause. docker kill and a daemon restart produce the same code, so check docker inspect for the OOMKilled flag before raising limits.
Docker leaves the OOM priority of containers untouched, so a container dies before the daemon does. Never set --oom-kill-disable without -m, or the host loses processes instead.
docker stats --no-stream prints live memory and cpu use per container. Read it before picking a number.
How Do You Check, Stop, and Remove a Docker Container?
Run docker ps to list running containers and docker logs to read output. docker stop ends one, and docker rm deletes it. Add -a to docker ps to include stopped containers.
Docker Docs (2026) define 7 container states: created, restarting, running, removing, paused, exited, and dead. SIGTERM is the default stop signal. The default stop timeout is 10 seconds for Linux containers and 30 seconds for Windows containers. A dead container cannot restart, only be removed.
Check a Container
docker ps shows running containers only, and docker ps -a shows every container, stopped ones included. To narrow it to one state, use docker ps --filter status=exited.
For the output itself, docker logs web is the command. docker inspect web dumps the full configuration and state as JSON.
An exited container shows its exit code in the STATUS column, such as Exited (0).
Stop a Container
The stop command sends SIGTERM to the main process. Once the grace period ends, Docker sends SIGKILL.
Stretch the wait with docker stop -t 30 web when an app needs time to flush data. docker kill web skips the grace period.
The walkthrough on how to stop a Docker container covers more cases.
If the first signal needs to change, set --stop-signal at creation, or use STOPSIGNAL in a Dockerfile.
Remove a Container
docker rm web deletes a stopped container, and docker rm -f web force-removes a running one. Add -v to also remove its anonymous volumes. For a bulk cleanup, docker container prune removes every stopped container after a confirmation prompt.
Filter the cleanup with docker container prune --filter "until=24h". Only stopped containers created more than 24 hours ago go.
How Do You Create a Docker Container From Your Own Dockerfile?
Write a Dockerfile, build it with docker build -t name:tag ., then create the container with docker run name:tag. The build turns the Dockerfile and the build context into an image, and the container starts from that image.
A minimal Dockerfile for a static site:
FROM nginx:alpine
COPY site/ /usr/share/nginx/html/FROM sets the base image and COPY adds files from the build context. There is no CMD here, since the nginx image already defines one and your image inherits it.
- Build the image with
docker build -t mysite:1.0 . - Confirm it exists using
docker image ls mysite. - Create and start the container with
docker run --name mysite -d -p 8080:80 mysite:1.0. - Test the response with
curl http://localhost:8080.
Build Context and .dockerignore
The trailing dot in the build command is the build context. It holds every file the build can reach, subdirectories included (Docker Docs, 2026).
A .dockerignore file strips files from the context before the build starts. Typical lines are node\_modules and .git. You get a smaller context and faster builds, most of all with a remote builder.
BuildKit is the default builder in current Docker Engine releases. A line like !README.md adds an exception to an ignore rule.
When the Build Fails
The usual culprit is a missing file. A COPY of a path outside the context stops with a “not found” error.
A Dockerfile piped through stdin has no filesystem context at all. COPY cannot reach local files in that case.
When Does docker run Not Apply, and What Goes Wrong?
The docker run command fits one container on one host. Multi-container applications belong in Docker Compose, and multi-host scaling and self-healing belong in Kubernetes. Beyond that, five common errors block a clean start: immediate exit, port conflicts, socket permissions, platform mismatch, and lost data.
When Compose or Kubernetes Replaces docker run
| Situation | Tool |
|---|---|
| One container, one host | docker run |
| Several containers sharing networks and volumes | Docker Compose |
| Many hosts, scaling, self-healing | Kubernetes |
Docker Compose describes services, networks, and volumes in one compose.yaml file. docker compose up starts everything, and docker compose down stops and removes it (Docker Docs, 2026).
Read what Docker Compose does before moving a stack over.
Kubernetes schedules containers across several machines and replaces failed ones. See how Kubernetes compares with Docker for the trade-offs.
Common Creation Errors
| Symptom | Cause | Fix |
|---|---|---|
| Container exits immediately | Main process finished, or the CMD is wrong | Read docker logs, add -it for a shell image |
| Port is already allocated | Another process holds the host port | Find it, or pick a new host port |
| Permission denied on docker.sock | User lacks socket access | Join the docker group or use sudo |
| Platform mismatch | Image built for a different OS or architecture | Pass --platform, or switch Docker Desktop to Linux containers |
| Data gone after removal | No volume mounted | Mount a volume before creating |
For port conflicts, docker ps --filter publish=8080 shows which container owns a host port. If the culprit is a non-Docker process, check the listening sockets on the host instead.
An exit code of 0 means the process finished cleanly, so the fix is a longer-running command. A non-zero code points to an application error, and docker logs names it.
FAQ on How To Create A Docker Container
How does a docker container differ from a virtual machine?
Containers share the host kernel and run as isolated processes. A virtual machine boots a full guest operating system on a hypervisor. Because containers carry no kernel of their own, they start in seconds and stay small.
Can Podman create containers with the same commands?
Yes, for most of them. Swap the word docker for podman in podman run or podman create, and images pull from Docker Hub the same way. Podman needs no daemon and runs rootless by default.
How do you run a container as a non-root user?
Pass -u 1000:1000 to docker run, or set a USER instruction in the Dockerfile. Both change the user inside the container. Running the docker daemon itself without root is a separate setup called rootless mode.
How do you remove a container automatically after it exits?
Add --rm to docker run. Docker then deletes the container and its anonymous volumes when the main process exits. Named volumes stay in place, so data written there survives the cleanup.
How do you open a shell inside a running container?
Run docker exec -it web sh. It starts a new process inside the running container, and typing exit leaves the container running. Alpine Linux images ship sh only, while Ubuntu images include bash.
What Should You Fix First in How To Create A Docker Container?
Data persistence, without much competition. A missing named volume loses data permanently at removal, while a missing image pin or memory cap costs only a restart to correct.
So mount a named volume first. After that, pin a version tag or image digest, and set --memory along with a restart policy.
Pinning a digest trades automatic security patches for reproducible builds, so schedule a monthly rebuild against the newest base image.
This order holds for Docker Engine releases current on September 29, 2026. A change to default volume or restart behavior reorders it.
Once the container runs, the next skill is to restart a Docker container cleanly without losing that data.
- How to Turn On Dark Mode in Notepad++ (Built-In, No Plugin) - October 3, 2026
- PostgreSQL Cheat Sheet - October 2, 2026
- How to Repair a Corrupt SQL Server Database Without Any Data Loss - October 2, 2026



