My Docker Learning Journey: Struggles, Headaches, and Small Wins

I recently decided to Dockerize my FastAPI project and learned a lot along the way – from container mishaps to unexpected errors. Here’s a look at what went wrong, what I fixed, and what I’d do differently next time.
I wanted to use Docker with my FastAPI projects mainly to learn more about it and to use the image on both of my computers. I thought this plan was a great way to start with Docker. As I worked on my FastAPI project across different machines, I quickly realized that getting everything to work the same way on both Mac and Windows was a real challenge. Installing dependencies, setting up Postgres, and ensuring my Python environment was identical everywhere felt like a never-ending task, as fixing one issue often led to another.
Docker helped eliminate these headaches by providing a consistent and repeatable environment. Whether I was working on my Mac or my Windows PC, Docker would launch the same containers with the exact same setup every time.
Additionally, knowing I could version control my development environment with docker-compose.yml
gave me peace of mind. I no longer had to worry about "but it worked on my machine!" Docker allowed me to package everything—FastAPI, Postgres, and even Redis if I wanted—into neat containers that always run the same way.
In the beginning, I ran into the issue of figuring out when I needed to rebuild my Docker image because of changes in my codebase. At first, I thought restarting the containers would be enough, but it turns out that if I change anything in the Dockerfile (like adding a new dependency), I actually need to rebuild the image entirely. Just restarting the containers wouldn’t pick up those changes.
It took me a while to realize that commands like docker-compose up
vs docker-compose up --build
make a big difference. If I didn’t rebuild, my app would still run with the old dependencies, which was pretty confusing in the beginning.
Another early challenge was dealing with containers that wouldn't run or would crash right away. Sometimes I'd type docker ps
and see them exit immediately without a clear error message. Usually, the issue was that the database wasn't ready yet, or there was a typo in my environment variables.
Then came the confusion with Docker Compose. At first, I didn't realize that Docker Compose is essentially a way to start all my containers at once instead of typing separate docker run
commands for each one. Learning to use it also meant understanding the difference between commands like docker-compose up
, docker-compose down
, and docker-compose up -d
. It was overwhelming at first, but I persisted.
The final challenge was getting the database tables to exist! My app would start but crash with an error saying something like relation "users" does not exist
. That's when I learned I needed to apply my migrations (like Alembic) to create those tables before my app could do anything. It was one of those moments where everything clicked and Docker was working, my containers were communicating, but I still had to ensure the database was properly set up.
I learned a lot during this process, and one key takeaway was to apply my migrations as soon as I updated something. Making sure everything was properly integrated before running saved me a lot of headaches. I know this is probably common practice, but I learned it the hard way.
Another lesson was the importance of understanding the logs. At first, I’d just see errors and get frustrated, but once I started reading the logs closely, I could pinpoint exactly what was going wrong—like missing tables or incorrect environment variables. Now I always check the logs first whenever something isn’t working.
Finally, I realized how important it is to set up my .env
file and docker-compose.yml
cleanly from the start. Before, I’d just throw things together as I went, but that always caused problems later. Keeping these files tidy and version-controlled made my environment much easier to manage.
Initially, Docker seemed like a big mystery. I encountered random errors, and everything seemed to break in new ways. But after working through those initial challenges, I feel much more comfortable using it. I now know how to manage my containers, read the logs, and maintain a consistent environment, no matter which machine I'm using.
I realize there's still a lot more to learn, but Docker isn't as intimidating to me as it was a few weeks ago. I'm excited to continue building with it and see how it can enhance my workflow for future projects.
If anyone has tips or tricks for using Docker, I would love to have a conversation!
Subscribe to my newsletter
Read articles from Jared Lemler directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Jared Lemler
Jared Lemler
Backend developer with a background in electrical work, now building APIs, databases, and dev tools with FastAPI, PostgreSQL, and Docker. Sharing everything I learn as I transition into tech.