Docker Basics for Developers: 5 Container Commands That Actually Work

Last Tuesday, I spent two hours debugging a Python app that worked perfectly on my machine but exploded on my teammate’s laptop. The culprit? A tiny version mismatch in the SQLite library — the kind of “it works on my machine” nightmare that makes you want to throw your keyboard out the window. If you’ve been there, you know the pain. That’s exactly when I decided to learn Docker basics for developers who have never used containers. And here’s the good news: you only need five container commands to fix this mess for good. In this article, I’ll walk you through the exact commands that actually work — no fluff, no theory, just practical steps you can use today.
1. docker pull — Getting Your First Image Without the Overhead
When I first heard about Docker, I thought I needed to build everything from scratch. Wrong. The magic starts with docker pull. Think of a Docker image as a pre-packed lunch — someone else has already cooked the meal, and you just grab it from the shelf. You don’t need to install Python, Node.js, or PostgreSQL on your host machine; the image has everything bundled inside.
Let’s try it. Open your terminal (after installing Docker Engine or Docker Desktop — yes, you need that, but it takes under five minutes on macOS, Windows, or Linux) and run:
docker pull nginx:alpine
This pulls the official Nginx web server image, but a super-lightweight version based on Alpine Linux (around 5 MB instead of 100+ MB). You’ll see progress bars as Docker downloads layers — each layer is a snapshot of files, like a Lego brick. Once it finishes, you have a local copy. No installation wizard, no dependency conflicts, no “missing libssl.so.1.1.” Just a clean, ready-to-run image.
Here’s the counter-intuitive insight: you don’t need to understand image layers to benefit. Treat docker pull as your “download and trust” button. For Docker beginners, this is the safest way to start because official images are vetted and updated regularly. Just remember: pulling an image doesn’t run anything — it’s like buying groceries. You still need to cook (or in Docker terms, run) the meal.
2. docker run — Spinning Up a Container in One Line
Now the fun part: turning that image into a running container. docker run is where the rubber meets the road. I’ll show you a concrete example that gives immediate feedback.
After pulling nginx:alpine, run:
docker run -d -p 8080:80 --name my-nginx nginx:alpine
Let’s break this down:
- -d (detached mode): runs the container in the background so you get your terminal back.
- -p 8080:80 (port mapping): connects port 8080 on your host to port 80 inside the container. Now open your browser and go to
http://localhost:8080— you’ll see the Nginx welcome page. That’s your container serving content. - --name my-nginx: gives the container a friendly name so you don’t have to remember a random ID.
When I first ran this, I literally leaned back in my chair. A web server, up and running in seconds, with zero configuration. No editing nginx.conf, no sudo, no “are you sure you want to install this?”. This is the killer feature of Docker basics for developers: you can test any software in isolation without polluting your system.
Pro tip: If you get a port conflict error (like “port is already allocated”), just change the host port — for example, -p 8081:80. Or run docker stop my-nginx first. More on stopping in section 4.
3. docker ps — Seeing What’s Actually Running (and What’s Not)
A few weeks ago, a colleague complained that his database container wasn’t responding. He’d run a dozen commands and couldn’t figure out why. I asked him to type docker ps — and guess what? The container wasn’t even running. He’d forgotten to start it after a reboot. That’s the power of docker ps: it tells you the truth.
Run docker ps and you’ll see a table with columns like CONTAINER ID, IMAGE, COMMAND, CREATED, STATUS, PORTS, and NAMES. The STATUS column is gold — it shows “Up X minutes” for healthy containers, “Exited (0)” for ones that shut down cleanly, or “Exited (1)” for crashes.
But here’s the trick most tutorials skip: use docker ps -a to see all containers, including stopped ones. This is a lifesaver when debugging. For example, if you run docker run without -d, the container runs in the foreground and exits when you press Ctrl+C. Without -a, docker ps shows nothing, leaving you wondering what happened. docker ps -a reveals the exited container, and you can inspect its logs or remove it.
Personally, I alias docker ps -a to dpsa in my shell. It’s that useful. For Docker beginners, this command answers the question “Is my app actually running?” before you spend 30 minutes restarting services.
4. docker stop and docker rm — Cleaning Up Without Fear
I used to be terrified of deleting things in Docker. “What if I lose my work? What if I can’t get the container back?” Spoiler: you won’t. Containers are ephemeral by design — they’re like paper plates, not heirloom china. You can always recreate a container from its image.
To stop a running container gracefully, use:
docker stop my-nginx
This sends a SIGTERM signal, giving the process time to clean up (e.g., flush logs, close connections). After a few seconds, the container stops. Verify with docker ps — my-nginx should be gone from the list.
To remove it permanently (freeing up disk space), run:
docker rm my-nginx
Wait — what if you want to stop and remove in one step? Docker has your back: docker rm -f my-nginx forces removal even if the container is running. I use this all the time when I’m iterating on a setup and want a clean slate.
For bulk cleanup, the game-changer is:
docker container prune
This removes all stopped containers in one go. You’ll get a confirmation prompt (type y). If you want to also delete unused images, networks, and build cache, run docker system prune -a. Warning: this is aggressive — it’ll remove images you’re not currently using. Only do this when you’re sure you don’t need them. I use it monthly to keep my disk from filling up with old test images.
The honest truth: you won’t lose work because your data lives either in the image (which you can repull) or in volumes (which are separate). For Docker beginners, cleaning up is a skill that prevents the dreaded “no space left on device” error. Practice stopping and removing a container a few times — it becomes muscle memory.
5. docker exec — Getting Inside a Running Container for Debugging
Here’s a scenario from last month: I was testing a Node.js app inside a container, and it kept throwing a cryptic error. Logs weren’t enough — I needed to inspect the filesystem, check environment variables, and run a few commands interactively. That’s where docker exec shines.
To open a bash shell inside a running container, use:
docker exec -it my-nginx /bin/sh
Let’s decode the flags:
- -i (interactive): keeps STDIN open so you can type commands.
- -t (tty): allocates a pseudo-terminal, giving you a proper shell prompt (like
$or#). - /bin/sh: the command to run inside the container (many lightweight images use
shinstead ofbash).
Once inside, you can ls, cat config files, check env, or even install temporary debugging tools (like curl or ping). When you’re done, type exit to return to your host terminal. The container keeps running — you only exited the interactive session.
One original take I’ve learned the hard way: don’t use docker exec to make permanent changes to a container. Containers are meant to be disposable. If you edit a config file inside, that change disappears when the container restarts (unless you mount a volume). Instead, use docker exec for investigation only — checking logs, testing connectivity, or running one-off commands. For permanent changes, modify the Dockerfile or use volumes.
For example, if your app isn’t connecting to the database, run:
docker exec -it my-app-container ping database-container
You’ll see instantly whether network isolation is blocking communication. This beats guessing every time.
Conclusion: Your Next Steps After These 5 Commands
Those five commands — docker pull, docker run, docker ps, docker stop/rm, and docker exec — are the foundation of Docker basics for developers who have never used containers. They solve the “it works on my machine” problem, let you test software in isolation, and give you a debugger’s superpower. I use them daily, and they’ve saved me countless hours.
Here’s your action plan: this week, pull the python:3.11-slim image and run a simple python -c "print('hello from Docker')" via docker run. Then stop, remove, and try docker exec on a web server container. You’ll be amazed how quickly it clicks.
After you’re comfortable, look into Dockerfiles (to build your own images) and Docker Compose (to run multi-container apps). But for now, master these five. They’re the only ones you actually need to start shipping with confidence.
Worth bookmarking before your next debugging session — trust me, you’ll thank yourself later.
