At some point, every beginner runs into this question:
Should I use
docker run, or should I use Docker Compose?
The practical answer is simple:
- Use
docker runwhen you want to start one container quickly - Use Docker Compose when you want to define and manage one or more containers as a reusable setup
You can think of it like this:
docker run= one command, typed by handdocker compose= a saved recipe in adocker-compose.ymlfile
| Use case | Better choice |
|---|---|
| Quick test | docker run |
| Learning basic flags | docker run |
| Reusable setup | Docker Compose |
| Multi-container app | Docker Compose |
| Team sharing | Docker Compose |
| Easier updates | Docker Compose |
flowchart LR
A[docker run] --> B[One command typed manually]
B --> C[One container starts]
D[docker compose] --> E[YAML file defines services]
E --> F[One command starts full stack]
If you installed Docker Desktop, Compose is already included as docker compose.
If you want to install it explicitly:
winget install -e --id Docker.DockerComposeVerify:
docker compose versiondocker run -d `
--name my-nginx `
-p 8080:80 `
--restart unless-stopped `
nginx-d→ run in background--name→ container name-p→ port mapping (host:container)--restart→ restart policynginx→ image
Open: http://localhost:8080
services:
nginx:
image: nginx
container_name: my-nginx
ports:
- "8080:80"
restart: unless-stoppedRun:
docker compose up -d- No need to remember long commands
- Easy to edit and reuse
- Shareable config
- Cleaner structure
docker volume create portainer_data
docker run -d `
--name portainer `
-p 9000:9000 `
--restart always `
-v /var/run/docker.sock:/var/run/docker.sock `
-v portainer_data:/data `
portainer/portainer-cedocker volume create→ persistent storage-v host:container→ mount volume/var/run/docker.sock→ allows Portainer to control Dockerportainer_data:/data→ saves app data--restart always→ auto restart
services:
portainer:
image: portainer/portainer-ce
container_name: portainer
ports:
- "9000:9000"
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
volumes:
portainer_data:Run:
docker compose up -ddocker compose updocker compose up -ddocker compose downdocker compose down -vdocker compose restartdocker compose stopdocker compose startdocker compose psdocker compose logsdocker compose logs -fdocker compose pulldocker compose up --builddocker compose up -d --force-recreatedocker compose up -d --remove-orphansIn docker run:
--restart alwaysIn Compose:
restart: alwaysnoalwaysunless-stoppedon-failure
- Use
docker runfor quick tests - Use Docker Compose for anything you want to keep
That’s the real difference.