Run your first Docker container
Learn to run your first Docker container with a hands-on tutorial that covers core concepts, step-by-step instructions, troubleshooting, and the next steps in your Docker learning path.
Focus: run your first docker container
You've installed Docker, maybe run docker --version to confirm it's there—but now you're staring at a blinking cursor, unsure what to actually do. The problem isn't understanding containers in theory; it's turning that theory into a running process that outputs something real. Without that first successful docker run, the whole ecosystem feels like an abstract promise. Let's fix that right now.
The problem this lesson solves
When you first approach Docker, the gap between "I understand what a container is" and "I can launch one that does something useful" feels huge. You might have read about images, layers, and registries, but none of that matters until you see a container actually run and produce output you can touch. The pain is real: tutorials assume you know the command, search results show 20 flags at once, and you end up copying snippets without understanding what docker run really does. This lesson cuts through that noise.
Pro tip: Container beginners often confuse "running a container" with "starting a VM." A container shares the host OS kernel—it starts faster and uses fewer resources. Keep that mental model in your back pocket.
Core concept / mental model
Think of Docker as a self-contained lunchbox for your application. The image is the recipe and ingredients all packed together (the lunchbox itself). The container is the lunchbox when you open it and start eating—it's the image in action. When you run docker run, you're telling Docker: "Take this lunchbox, open it, and let me see what's inside."
What happens when you run a container
- Docker checks if the requested image exists locally.
- If not, it pulls the image from a registry (like Docker Hub).
- Docker creates a writable layer on top of the read-only image.
- Docker sets up the filesystem, networking, and process isolation.
- The specified command executes inside that isolated environment.
- When the command finishes, the container stops.
Image vs. container: the critical distinction
| Concept | Analogy | Mutable? | Persisted? |
|---|---|---|---|
| Image | A blueprint or template | No (immutable) | Yes, stored on disk |
| Container | A running instance of that blueprint | Yes, you can write files inside | No, ephemeral by default |
How it works step by step
Let's walk through the exact sequence of docker run with a simple Alpine Linux container that just prints "Hello from PythonSkillset!" and exits.
Step 1: Identify the image and command
The basic syntax is:
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
For our first run, we'll use:
- Image: alpine:latest — a tiny Linux distro (~5 MB)
- Command: echo "Hello from PythonSkillset!"
Step 2: Pull the image (if needed)
Docker checks locally first. If the image isn't cached, it pulls from Docker Hub:
docker pull alpine:latest
This downloads layers. You'll see progress bars. Once complete, the image is stored locally.
Step 3: Execute with docker run
Now run the container:
docker run alpine:latest echo "Hello from PythonSkillset!"
Docker starts the container, runs the echo command inside it, prints the output, and the container exits. It's that simple.
Blockquote: The container stops immediately after the command finishes. You're not leaving anything running—it's a one-shot job.
Hands-on walkthrough
Let's do three exercises that build confidence.
Exercise 1: Hello from a container
Run your first container with a simple Alpine image:
docker run alpine:latest echo "I just ran my first container!"
Expected output:
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
... (pull progress)
Status: Downloaded newer image for alpine:latest
I just ran my first container!
If the image was already cached, you'll just see the greeting line.
Exercise 2: List containers (including stopped ones)
See all containers, including the one that just exited:
docker ps -a
Expected output (similar):
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 alpine:latest "echo 'I just ran…'" 2 minutes ago Exited (0) 2 minutes ago romantic_feistel
Notice the STATUS column says "Exited (0)". Exit code 0 means success.
Exercise 3: Interactive shell inside a container
Run a container interactively so you can explore:
docker run -it alpine:latest /bin/sh
Now you're inside the container shell! Try:
/ # ls
bin dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var
/ # cat /etc/os-release
NAME="Alpine Linux"
VERSION_ID=3.20.0
/ # exit
After exit, you're back on your host. The container stopped.
Pro tip: The
-itflag is shorthand for--interactive(keep stdin open) and--tty(allocate a pseudo-terminal). Almost always needed together for shell access.
Compare options / when to choose what
Different scenarios call for different docker run patterns. Here's a quick reference:
| Use case | Recommended flags | Example |
|---|---|---|
| One-shot command | (none) | docker run alpine:latest date |
| Interactive shell | -it |
docker run -it ubuntu:latest bash |
| Detached (background) | -d |
docker run -d nginx:latest |
| Auto-remove after exit | --rm |
docker run --rm alpine:latest echo "cleanup" |
| Name the container | --name |
docker run --name myalpine alpine:latest |
| Map host ports to container | -p |
docker run -p 8080:80 nginx:latest |
When to choose each:
- Use --rm for one-shot commands to avoid clutter from stopped containers.
- Use -d for services like web servers that should run in the background.
- Use -it when you need to debug or explore the container's filesystem.
Troubleshooting & edge cases
The container ran but I don't see any output
Some images like ubuntu:latest don't run a command by default—they just start and exit. Always specify a command that produces output:
docker run ubuntu:latest echo "I'll produce output"
Permission errors when running Docker
You see Got permission denied while trying to connect to the Docker daemon socket. This means your user isn't in the docker group. Either:
- Add yourself: sudo usermod -aG docker $USER (then log out/in)
- Or prefix every command with sudo (not recommended for daily use)
The container exits immediately and I need it to stay running
If you want a container to keep running, it needs a foreground process. For example, nginx starts as a daemon by default. Use -d and check logs:
docker run -d nginx:latest
docker logs <container-id>
"Unable to find image" but I already pulled it
You might have pulled a different tag. Always specify the full image name and tag, e.g., alpine:latest vs. just alpine. If you mistype, Docker will try to pull a possibly nonexistent image.
What you learned & what's next
You now understand the core idea behind running a Docker container: pulling an image, executing a command inside an isolated environment, and seeing the result. You can:
- Explain the difference between an image and a container (key point)
- Run a one-shot command and an interactive shell
- List containers with
docker ps -a - Troubleshoot common beginner issues
This is the foundation for everything else in Docker. In the next lesson, you'll learn how to manage container lifecycle — starting, stopping, and removing containers properly. You'll also explore docker start, docker stop, and docker rm to keep your environment clean. Understanding docker run first makes those next steps feel natural.
Remember: every advanced Docker workflow—multi-stage builds, Compose, Kubernetes—builds on this single docker run command. Master it today, and tomorrow's challenges shrink.
Practice recap
Pick a command you run frequently on your host (like grep or curl) and run it inside an Alpine container: docker run --rm alpine:latest grep --help. Then try running a web server: docker run -d -p 8080:80 nginx:latest and visit http://localhost:8080 in your browser. Finally, stop and remove the nginx container with docker stop <ID> and docker rm <ID>.
Common mistakes
- Forgetting
-itwhen trying to run an interactive shell — you get no terminal and the container exits immediately. - Running
docker run ubuntuwithout a command — the container starts and stops silently, leaving you confused about what happened. - Not using
--rmfor one-shot commands, causing an ever-growing list of stopped containers that clutterdocker ps -a. - Confusing image name with container ID — you try to
docker runa container ID instead of an image name.
Variations
- Use
docker container runinstead ofdocker run— it's the newer, more explicit syntax (both work identically). - Pull the image explicitly first with
docker pull, then run it — useful when you want to separate download from execution for diagnostic purposes. - Run in detached mode (
-d) combined with--namefor service containers that outlive your terminal session.
Real-world use cases
- Running a one-off data processing script in an isolated Python environment without installing dependencies on your host.
- Spinning up a local PostgreSQL database for development using
docker run --name mydb -e POSTGRES_PASSWORD=secret -d postgres:latest. - Testing a new software version (like Node.js 20) in a disposable container without affecting your existing development tools.
Key takeaways
docker runcreates and starts a container from an image; the container exits when its main command finishes.- Always specify a command after the image name for one-shot containers, or use
-itfor interactive sessions. - Approximately 5 MB images like
alpine:latestare great for learning because they pull quickly and start instantly. - Use
docker ps -ato see all containers, including stopped ones — essential for debugging non-output runs. - Flags like
--rm,-d,-it, and--nametailordocker runto your specific use case — one-shot, background, or interactive. - The container is ephemeral by default: any files you create vanish when the container is removed (unless you use volumes).
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.