From Procrastination to Containers: My Messy Docker Journey on Windows 10

"Make sure you have Node 16, not 17. Install Python 3.9, not 3.10. Oh, and PostgreSQL needs to be version 13 with these specific extensions..."
I was getting tired of saying this every time someone new joined our team. We were building an application with a React frontend, FastAPI backend, and PostgreSQL database, and onboarding was a nightmare. Every time a new developer joined the team, we'd spend half a day getting their environment set up with the exact right versions. Dependencies broke constantly, and I'd become the unofficial "why won't this run on my machine?" support person.
I knew Docker could solve this, but every time I tried to learn it, the tutorials felt overwhelming. They assumed I knew things I didn't, or jumped straight into complex orchestration setups. So I kept putting it off, telling myself I'd figure it out when I had more time.
After the third developer couldn't get our project running because of some Python version conflict, I decided to start simple. I'd learn Docker basics with something I could actually understand – serving a basic HTML page from a container.
Why I Finally Stopped Avoiding Docker
The dependency management problems at work were getting worse, but I needed to understand Docker fundamentals before I could tackle our complex application stack. Starting with a simple HTML container seemed like the right approach – I could focus on learning the core concepts without getting lost in the specifics of React builds or database configurations.
Getting Docker Running on Windows 10
I'm on Windows 10 Pro 22H2. Getting Docker to work meant enabling Hyper-V and setting up WSL2, which required a restart. My laptop wasn't happy about it, but eventually Docker Desktop started up.
I opened Ubuntu through WSL and poked around the terminal for a bit. Everything seemed to be working, so I decided to try something simple first.
The Hello World Test
I started with the basic test everyone mentions:
docker run hello-world
It worked immediately. The container downloaded, ran, and showed me a message explaining what just happened.
Seeing Docker actually do something concrete helped. It wasn't some abstract concept anymore – it was a thing that could download and run code on my machine.
Apache: Where I Hit My First Real Problem
Next, I tried running Apache:
docker run httpd
The container started without any errors. I opened my browser and went to localhost... nothing. Just a blank page.
The container was running fine according to Docker, but I couldn't see the website. This is where I realized I didn't understand how containers actually connect to the outside world.
Learning About Ports and Container Management
I needed to figure out Docker's command-line flags. Turns out they're not optional extras – they're how you make containers actually useful.
Port mapping was the first thing I needed:
-p 8081:80
This connects port 8081 on my laptop to port 80 inside the container, where Apache runs. After adding this flag, I could finally see Apache's default page at localhost:8081.
Detached mode solved another problem:
docker run -d -p 8081:80 httpd
Without the -d flag, the container would take over my terminal. I'd have to open a new tab every time I wanted to run another command. With -d, the container runs in the background and gives me my terminal back.
Naming containers made everything easier to manage:
--name apache_container
Instead of dealing with random names like "cranky_tesla" or "boring_lovelace," I could give my container a name that made sense to me. This made stopping and starting it much simpler.
Volume Mounts: My Most Frustrating Hour
I wanted to serve my own HTML files instead of Apache's default page. This meant mounting my local folder inside the container. My first attempt didn't work:
-v $pwd:/usr/local/apache2/htdocs
Docker gave me error messages I didn't understand. After some googling and trial and error, I figured out two problems:
Bash needs
$(pwd)instead of$pwdThere can't be spaces around the colon
The working version:
-v $(pwd):/usr/local/apache2/htdocs
When this finally worked, I could edit files on my Windows machine and see the changes immediately in the browser. That felt pretty satisfying.
Creating My First HTML File (And Messing It Up)
I tried to create a simple HTML file from the command line:
echo"<h1>Hello World</h1>" index.html
Bash threw an error because I forgot the space after echo. Fixed:
echo "<h1>Hello, this is my first Docker-served page!</h1>" > index.html
Small mistake, but it reminded me that command-line syntax matters more than I usually pay attention to.
Writing a Script to Automate Everything
I kept running the same commands: stop the container, remove it, start it again with the right flags. After doing this about ten times, I wrote a script:
#!/bin/bash
docker stop apache_container || true
docker rm apache_container || true
docker run -d -p 8081:80 --name apache_container -v $(pwd):/usr/local/apache2/htdocs httpd
echo "✅ Apache is running. Open http://localhost:8081 in your browser."
Made it executable:
chmod +x run_apache.sh
Now I could just run ./run_apache.sh and my website would be live. Much better than typing out that long docker command every time.
Debugging When Things Went Wrong
When containers didn't work (which happened more than I'd like to admit), I learned to check the logs:
docker logs apache_container
This showed me what Apache was actually doing inside the container. Instead of guessing why something wasn't working, I could see the actual error messages.
Putting Everything on GitHub
After I got the setup working reliably, I wanted to document it. Partly for other people, but mostly so I wouldn't forget how I did it.
I initialized a git repo:
cd ~/my_website
git init
git add .
git commit -m "Initial commit with website and Docker script"
Created a README that explained what each piece does:
# My Website (Apache + Docker)
## How to use this
1. Make sure Docker is installed and running
2. Run the script: `./run_apache.sh`
3. Open http://localhost:8081 in your browser
## What the flags do
- `-d` runs the container in the background
- `-p` connects your computer's port to the container's port
- `--name` lets you give the container a memorable name
- Volume mounting makes your file changes show up immediately
Then pushed it to GitHub:
git remote add origin https://github.com/yourusername/my_website.git
git branch -M main
git push -u origin main
Now anyone can clone it and have a working setup in a few seconds.
What I Actually Learned
This whole process taught me that Docker isn't as complicated as I made it out to be. The core concepts are straightforward once you get past the initial confusion about how containers work.
The main things I learned:
Start with something simple and build from there
Docker error messages are usually helpful if you actually read them
Document your setup while it's fresh in your mind
If you're running the same commands repeatedly, write a script
Pay attention to syntax – Docker cares about spaces, parentheses, and colons
The End Result
What started as a simple HTML exercise turned into a solid understanding of Docker fundamentals. I have a working Apache container, a script that makes restarting it easy, and documentation that explains the whole process.
This simple HTML project built the foundation for containerizing more complex work applications. Once I understood ports, volumes, and container management through this basic example, tackling our React-FastAPI-PostgreSQL stack became much more approachable. No more "works on my machine" problems or spending hours debugging someone's Python version conflicts.
Docker doesn't intimidate me anymore. When people mention containerizing applications, I actually understand what they're talking about instead of just nodding along.
The whole experience taught me that breaking down intimidating technologies into small, concrete steps makes them much more approachable. Starting with a simple HTML page was exactly what I needed to build confidence before tackling our actual work problems.


