What Does Build, Ship and Run Any App, Anywhere Really Mean?
If you're new to Docker, it can be difficult to see the benefits of build, ship and run any app, anywhere. So, let's talk about it here.
Before we can talk about Docker’s motto in the context of Docker, we need to talk about what life is like without Docker. This is necessary because it’s important to understand the process of how to build, ship and run an application without Docker.
I personally develop web applications, so I’m going to explain this in the context of web app development, but it applies to any type of application.
Building a Web Application without Docker
I’m sure you know the drill here. You’ve picked your favorite web framework of choice. It doesn’t matter if it’s Ruby on Rails, Express, Django, Laravel or something else.
Prior to developing your application, you had to do a few things:
You needed to install a programming run-time on your development box. This could be Ruby, NodeJS, Python, PHP or whatever language your web framework uses. You probably used a version managing tool that caused a lot of headaches as well.
Then you had to install all of your web application dependencies. These would be packages located in a
composer.jsonfile, but you knew that already.
The instructions on how to do this will be drastically different depending on if you’re using MacOS, Linux or Windows. Heck, it’s going to change even between different versions of the same OS.
Running a Web Application without Docker
Once your web application is built, you can run it. This usually starts with at least running your web application’s app server.
For example with Rails that could be
unicorn. With Express that would be the
node server, and if you’re into Django or Flask that would be
uswgi most likely.
However, chances are your web application isn’t that simple. You probably need a database. So now you have to figure out how to install
MySQL, or whatever database you decided to pick.
How you install this will depend on what OS you’re using. Hopefully at the very least you use the same version that you plan to run in production.
It doesn’t stop here too right? Real world web applications are more complex than this. Honestly, I haven’t built a single web app in the last 3 years that didn’t also use Redis and a background worker.
Now it’s on you to install
Redis and run your background worker too. A background worker would be something like
resque in the Rails world. For Python that would be
celery and if you’re in Node land, you would just write a heaping pile of spaghetti driven callbacks RIGHT?
Our Basic Web Application Is Ready
In any case, we’ve hit a reasonable point for most entry level web applications. We have an app server, a background worker, a database and a queue/cache back-end (Redis).
So what do you do at this point? You need to come up with a way to run these 4 services together when you start up your application. There are tools in most languages to do this. Something like
foreman in Ruby or
honcho in Python, and Node also has a
foreman clone too.
Cool, you finally have things running in development.
I’m going to save you the torturous story of trying to upgrade and manage your language’s versions on your dev box, or even worse, trying to get your buddy set up with the code base on their machine. If you’re reading this article, you already know how rage inducing that is.
Shipping a Web Application without Docker
There are lots of options here and I’m not going to write about them in detail, because the only thing that’s important to say is it involves getting your web application from your development box onto 1 or more production servers.
The major problem here is that your dev box is very likely not using the same exact OS as what you’re using in production so you’re stuck going on a witch hunt while you solve mysterious issues that are foreign to you while you encounter error after error along the way.
Long story short, it’s a painful process and your confidence level that things will work exactly the same in development and production are dangerously low…
…and we didn’t even talk about setting up a proper web server like
nginx or dealing with
SSL. Both of which are necessary in production in my opinion.
Heh, we didn’t even talk about how to push new builds of your app over to your server after you have your server up and running. There’s many ways to do that but that’s a story for another time.
Finally, It’s Running in Production!
After all that, you finally have things running in production, but what happens if you want to scale beyond 1 server? It’s back to the drawing board, and you’re going to end up spending many months lost in the woods while you research and tinker with load balancers and rolling restarts.
At this point you might be wondering “how does this guy know all of this?”, and the answer to that is, I’ve experienced this entire story first hand for many years. Around 6 or 7 years ago I decided I wanted to be an “ops” guy in addition to being a developer so I experienced all of these pains.
Hell, I can’t even tell you if I started working on the ops side of things 6 or 7 years ago because after using
Chef for 6 months back then my sense of time was altered. It was such a horrifying experience that it felt like I was trapped in an event horizon while being sucked into a black hole.
Build, Ship and Run Your Apps with Docker
Ok, now we can have a discussion about Docker, and luckily it won’t take nearly as long to explain.
Building a Web Application with Docker
Instead of worrying about installing programming language run-times and dependencies on your dev box directly, they will be built into a Docker image.
Docker images are created through a thing called a
Dockerfile. You can think of it as a recipe for how to set up your application. You only need to define this file once, and then build it. Once that Docker image is built, all you have to do is move it to another machine and run it.
There are no complex steps of having to re-install all of your dependencies because everything needed for your app to run is included.
Oh and if you’re wondering yes, Docker does have services and commands that let you easily move Docker images between servers or machines. It honestly can’t be easier.
Running a Web Application with Docker
There’s a tool called Docker Compose, which is a part of Docker’s overall ecosystem.
It lets you run 1 or more “Dockerized” services easily. So in our above example of having 4 different services to run, we would just define them in a single file and run that file with Docker Compose.
Of course you could do this without Docker Compose by using Docker directly, but this use case is what Docker Compose was built for so you should use it.
The awesome thing about this is, when it comes time to sharing this code base with your buddy, or another computer, all you have to do is install Docker and run the same Docker Compose command.
It doesn’t matter if you’re running the app on Ubuntu, MacOS or Windows because as long as you have Docker installed, Docker knows what to do.
Shipping a Web Application with Docker
This is where things get interesting. Once you have Docker installed on your server, all you have to do is run the same Docker Compose command you ran in development, and minutes later everything will work as expected.
This is perfect for when you need to deal with single server deploys.
In the more complex example of wanting to use more than 1 server, you can use another tool in Docker’s ecosystem called Docker Swarm. Swarm lets you spin up and manage a cluster of servers.
It does quite a few things, but its main perks are letting you scale services up and down, deal with load balancing and let you perform rolling restarts so that you can deploy your web applications without downtime.
Build, Ship and Run Any App, Anywhere
So that covers it.
Docker really does let you build your apps and then run them anywhere. It doesn’t matter what tech stack you use, or where you run it. As long as you have Docker installed and know how to use it then you’re good to go.
What type of success stories have you had with Docker?