Using Docker At Your Own Pace
“Operating a piece of technology at a professional level turns out to be really hard. It’s easy to get started with a lot of technology, but harder to do a really good job with it.”
“If you decide to try out a new piece of technology, you should figure out low-risk ways to get started.”
These quotes are from boringtechnology.club. I love everything about them.
Docker is one of those things, which you probably don’t want to start using in production right away. Going from “that’s neat” to production-ready is a huge leap to take. Of course, production doesn’t have to be a big deal, but it’s still a much less stressful experience to take your time and get to know Docker at your own pace.
You’ll have a much better experience with taking smaller steps and building some confidence with them before moving on. Slow and steady wins the race!
Here’s an actionable and easy to implement roadmap towards making use of Docker for your project. Starting with simple ways of getting value out of it, and ramping up the scope as well as usefulness.
Each step will help you get to know a small part of the tool in a safe environment, without having to solve all problems at once.
First, play around
You probably have taken this step already, but have you explored it in-depth, by choice? The better your understanding the basics of Docker, the less you’ll stumble over them later on.
There are a lot of great getting-started tutorials out there. Make sure you’ve tried to:
- Pull an image
- Run a container from it, exit the session
- Check the container state (ps)
- Run a new bash inside the container (exec)
- Stop and remove the container
- Run a custom entrypoint command
- Remove the image - clean up
There’s a lot more to try here, and knowing the mechanics will help you a lot! Don’t skip on the basics. It’s a good idea to learn continuously and dive into the basics every once in a while to see what you might have missed.
Write a docker-compose file
Knowing how to use the Docker CLI is great, but docker-compose is a much more convenient tool to run multiple containers at once locally.
There’s no need to write a custom Dockerfile at this point - you can use docker-compose for one of your projects with off-the-shelf Docker images from the public registry. Think of them, as reusable building blocks.
One neat superpower you get at this stage, is the ability to dockerize your backing services. Here’s a guid on how to run Redis and PostgreSQL.
Write your own docker-compose.yml file, and start using it. Get comfortable starting and stopping the container stack. Try using these dockerized services while working on your app locally. Make sure that you’re using the same versions of backing services as you are running in production, for some of that sweet dev/prod parity.
Now you can run an independent stack of backing services for any project’s development environment, whenever you want. That’s pretty darn neat!
Dockerize your app in development mode
The “development mode” is pretty important here. You’re not going to deploy this dockerized version of your app.
You will probably also don’t really use this during day-to-day development. Some people seem to learn Docker and try to use it everywhere, for everything, whenever they can. Personally, I strongly dislike running an application I’m working on inside of a container during development. It feels clunky, and it interferes with my workflows and tooling without making up for those downsides.
This step is not about putting your development server into Docker and never going back.
The goal here is to create an automated example development stack which comes up with a single command. A completely functional state of your development environment. Think of this as a “blueprint” or “functional README section” on setting this project up for development. Anybody will be able to check out the Dockerfile, and see what needs to be installed and configured.
You’ll need to write your own Dockerfile to harbor your application. You’ll be able to take any Docker tutorial for your stack and use it without any second thoughts. After all, this stack will never be used in production, and won’t be a crucial part of your development experience. No need to figure out how to make Docker builds fast at this point, or what best practices are. You just want to make it work - and that’s completely fine!
This is not a replacement for the backing-service stack from above. Rather a standalone new docker-compose file.
At this point, you’ll have two different docker-compose files: one to bring up a complete stack (adjust your Dockerfile, to make sure it waits for the database and other services to be up). And one to only start the backing services, so you can run a development server locally, out of Docker.
You’ve completed this step, once you can run
docker-compose up, and access your application on a local port. This can also come in very handy if you want to provide front-end developers with an out-of-the-box working local backend.
A docker-compose stack which is closer to your production setup
One more docker-compose file! This time, we’ll want to start paying attention to details. Your application should be packaged into a Docker image which is very similar to the way it runs in production. Check out this review of dockerizing Flask for some pointers on what to look out for.
You can start fixing frequent issues with your Dockerfile (stop using the root user, if you’re using Django: don’t rely on runserver, handle static files properly, make sure to use a WSGI server.
You can see about getting the size of the Docker image as low as possible, speed up the image build by making sure to use caching the right way and learn more about Docker tagging.
The road ahead… Or not
All of these steps are useful at their own, and don’t require you to ship dockerized code in production. You’ve taken the time to learn and get comfortable with it.
Getting to know Docker, and using it with confidence doesn’t need to be drastic or scary. It’s okay to adopt it step by step. Take time to get comfortable at each stage, and move on once you have made sure that you’re feeling comfortable.
You already leveled up your Docker skills to create real value and get real work done. Now you’re in a better position to decide whether Docker can make your life easier, or if you’re happy without putting it into production.