Most tutorials, guides, and walkthroughs lose their viewers within minutes because they are overly complex, wordy, and don’t get straight to the point. They also fail to understand a basic concept when teaching a beginner — the why is more powerful than the what.
The goal of this guide is to explain Docker to a programming beginner, who is unfamiliar with Docker and containerization technology. If both of those terms mean very little to you, but you know how to code, this guide is what you’re looking for.
Why Docker?
Simply put, Docker allows code to be run on different computers. Why is this important? Well, there are many different types of computers, and even the smallest changes between them can make running your code difficult.
You have a Mac but your teammate has Windows; that’s a problem. Your computer has Python installed, but your teammate’s computer does not; that’s a problem. Your teammate downloads Python, so that should fix it, right? Wrong. They have a different version of Python than you, so now it’s a problem again.
The point is, as soon as you download something onto your computer or change some settings, its state has changed, and it is effectively a different computer than before. Since software developers have highly customized computers, and the programs they work on often require even more complexity, this creates a ton of variance between developing environments. Thus, it can be extremely difficult to get code running from one machine to the next.
Docker’s technology allows the same code to be run on (almost) every computer, regardless of how the computer is configured previously.
Have a Raspberry Pi? Docker can run your app. Have an old Dell laptop that is 10 years old and takes 10 minutes to start up due to all the junk on it? Docker can run your app. Have a massive supercomputer in the middle of Wyoming that hosts half the internet? Docker can run your app.
What is Docker?
Docker acts as a layer on top of your computer. It effectively resets it to a clean, brand-spanking new slate. Imagine if you factory reset your computer and deleted everything off it, then only installed what was necessary to run your code; and everyone who did this decided to use the same operating system (usually Linux).
No one wants to delete their whole computer just to run their friend’s program. That would be madness. Since Docker is just a layer on top of your computer, it happens to be very convenient. When this Docker layer finishes running your program, it disappears, and it won’t change anything on your computer unless you tell it to.
If you are familiar with virtual machines, their purpose overlaps a good amount, however, Docker does not install an entire operating system and everything else with it. Since it is just the barebones technology needed to run specific code, it is a lot faster and more lightweight than virtual machines, which is a big reason they are an industry standard for deploying applications today.
How do I use it?
Docker makes itself (relatively) easy to use. The only requirement your computer must have is to download and install it. Thankfully, Docker is extremely popular and supported, so it can be used on almost every modern computer.
As for getting a program up and running, Docker handles most of the heavy lifting, so most of our work will be with these two tasks:
- Handling versions of our program
- Configuring Docker to replicate our computer’s state
Handling versions
Why is this important? Well, Docker works in three main steps:
- It first creates an image, which is like a snapshot of our computer. “Snapshot of our computer” is another way of saying Docker is replicating our computer’s state, with all the necessary files, installed programs, etc.
- Then it stores each image, so each one can be easily referenced later. Building the same image over again is a waste of time and computer power.
- Finally, it runs the image (the same as running our application) on our computer, in the form of a container. (Don’t worry about what a container is for now, just understand it is a running instance of an image).
Since Docker is storing these images, we need to spend some time making sure it is using the correct ones. This is where the versioning comes in. This isn't necessary if you only build and run one image for the rest of your life. But for everyone else, we will most likely have many images, and we will need to identify and separate them.
Remember, an image is just a replication of what is necessary from our computer’s state to run our program.
Configuring Docker
Since Docker acts as a clean slate on the computer, this clean slate needs to be configured. This involves adding any necessary files, passwords to store, programs to be installed, etc.
Thankfully Docker makes this pretty simple too. All of this configuring is done via a single file, which is called a Docker file. It is really just a set of instructions; as if you were working from your computer’s command prompt or terminal. When it finishes running, it spits out an image we can run on any other computer with Docker installed.
To give an idea of what this file looks like, below is an example of creating an image for running a custom JavaScript program.
- For those unfamiliar with Node.js, it is a JavaScript runtime environment, which allows a computer to run JavaScript code.
# import and start from a Node.js base image
FROM node:8.11-slim
# store an environment variable to our "computer"
ENV workdirectory /usr/node
# use the variable to set the working directory in our "terminal"
WORKDIR $workdirectory
# get the list of dependencies for our app to run
COPY package.json .
# install those dependencies
RUN npm install
# add our main JavaScript application file, which contains our program
ADD index.js .
# deploy our Node.js app
ENTRYPOINT ["node"]
One cool aspect of Docker is each line in the file actually creates an image in and of itself. So think of each line as an image building upon the previous one. We really only care about the final image Docker gives us at the end of the file, but this functionality is important. Why?
Since images can be built from one another, we can treat images like building blocks and reuse other peoples’ images. If you take a look at the sample file above, you’ll see FROM node:8.11-slim. This is an image the creators of Node.js have published to make it easy for everyone to deploy Node.js applications. It saves us a lot of busywork and headache in trying to automate a Node.js environment into our Docker file ourselves.
Taking this one step further, if someone ever wants to use our program, we can publicly publish our image for others to use. In addition to running it, they can also build on top of the image.
Wrapping up
In very simplified terms, this is the core functionality and value proposition Docker provides — isolate and run applications, regardless of machine. Of course, there is a ton going on under the hood, and most engineers require more than just creating and running images:
What about scaling instances of our application as traffic demands change? What happens when we run our image and it stops working?
Fun times…
Though, since Docker is lightweight and portable, it actually sets itself up very well for solving those problems. But for now, this is hopefully enough information to get an idea of why Docker exists and what it is used for. If you want to learn more, I highly suggest dipping your toes into reading the official docs and writing a Dockerfile for your own app.
Additional resources and acknowledgments
If you enjoy guided videos with hands-on coding, I found this tutorial by Arthur Ulfeldt to be well done. Be aware this is paid course through LinkedIn Learning, and I’m sure there are other free alternatives. If I come across any I believe are as effective, I will add them here.
The technology Docker uses is called containerization, and it isn’t necessarily novel. There are a decent amount of alternatives for developers to pick from. For a quick overview of containerization, AWS provides a solid guide.
Top comments (0)