Docker for absolute beginners: the difference between an image and a container
Learn the difference between Docker images and containerscontainers and images are different + practical code examples
Learn the difference between Docker images and containers + practical code examples
Containers, images, environments, building, running, virtual machines.. when you’re new to Docker all of these abstract terms can be a bit confusing. In this article we’ll go through all of them and get an understanding of each term. We’ll focus on explaining the difference between images and containers and how they work together, but along the way we’ll explore other Docker-related things. At the end of this article you’ll:
- understand how to build an image
- understand how to spin up an image
- understand the difference between an image and a container
- understand how to user Docker better in your day-to-day work
Let’s code!
Docker in a nutshell
Docker is the answer to ‘but it worked on my machine!’ Imagine that you’ve written a small program on your laptop: let’s say that it’s a simple Python API. Now you want to deploy this program on a laptop of a coworker or on a server. You copy the code, spin up the API and it crashes. Why?
There reasons for this can be many: maybe Python isn’t installed. Maybe the other machine has an OS that’s incompatible with your code. In other words: your program is built in one environment and doesn’t work in another.
Docker’s solution to this problem is very simple and very clever at the same time: instead of just deploying the code, we’ll deploy our environment as well. Docker creates a box, installs an OS in the box and copies over your source code. Then we give others the box. This is brilliant because once your code runs in this environment (box) that means that it runs anywhere.
In this article we’ll focus on how we build these boxes and how to share them. In other words: how we build images, spin them up into containers and deploy them on a server for example!
1. Creating an image
In the previous part we saw that with Docker we package our code with our environment so that we can run that. What we called a ‘box’ in the previous part is called an image. An image is the result of Docker’ build process. In the build process we use a Dockerfile. This is a file with instructions for building the container.
We’ll use lot of command line for the next part. If you are unfamiliar with using a terminal check out this article.
1.1 The dockerfile
Let’s check out a very simple dockerfile. Imagine we have a website that we want toFROM nginx:alpineCOPY c:/myproject/htmlfolder /usr/share/nginx/html
Two things happen here:
1. With the FROM keyword we tell Docker to pull a base image. In this case we use an image with nginx installed.
2. With COPY we instruct Docker to copy some code on our computer into the image. In this case we copy all code in our htmlfolder into the specified folder in the image. Nginx will host all code in this folder.
1.2 Building the image
Remember that so far we’ve only specified some instructions. Now we can actually build the image with docker build . -t my_image:v1
.
The .
in this command implies that docker can use a file called dockerfile
in the current directory. You can also specify your Dockerfile if it is located elsewhere or named differently with docker build -f c:/things/mydockerfile -t my_image:v1
As you can see we use the -f flag to pass the path to our dockerfile (called mydockerfile
in this example.
With the -t
flag we name and optionally tag our image in the name:tag
format. Tagging our image makes it easier to work with later.
2. Spinning up a container
So far we’ve built an image with a Dockerfile. The resulting image, however, is not doing anything yet. We need to run it. You can spin up an image in two ways: with docker run
and with a compose file. We’ll go through both.
Once an image is running it’s called a container.
2.1 Docker run an image
In this case we’ll run the image we’ve previously built. The easiest way is: docker run -p "81:80" my_image:v1
. This runs our previously built image and maps port 81 on our laptop to port 80 in the container, which is where nginx is serving our website. This means that we can go to localhost:81
on our laptop to see the website. Easy!
2.2 Running images with docker-compose
If we have a lot of images we will spend a lot of time typing all of the docker run commands from the previous part. With docker-compose we can put this run configuration in a file so that we don’t have to type it every time. Install docker compose before continuing.
Another advantage of compose is that we can use it to link containers together. More on this in this article.
We’ll translate the command from the previous part to a run-configuration in docker compose. We’ll create a file called docker-compose.yml
with the following content:version: "3.8"services:
my_site:
container_name: my_site
hostname: my_site
image: my_image:v1
ports:
- "81:80"
As you see the -p "81:80"
translates to the last two lines. Also we’ve added some extra information about our host- and container-name. We specify that we want to run the image called my_image:v1
on the 7th line.
Notice that, like the Dockerfile, the docker-compose.yaml is nothing but a file that contains instructions. We have to run it in order to do something. We can just call docker-compose up
if we’re in the same folder as the docker-compose.yml file or specify this file if it is located elsewhere or named something else with docker-compose -f c:/snacks/my_docker-compose.yml up
.
Docker-compose makes it easy to run many (connected) images with one command and saves you a lot of typing.
3. The differences between images and containers
Now that we have some hands-on experience we can determine the differences between images and containers.
An image is like a class: a blueprint
A container is like an instance of a class
The most important difference is that an image is a logical object; it’s like a blue print while a container is a real-life object. An image is created only once ; containers, using the image, are created any number of times
A Dockerfile is more like a recipe: instructions for how to build something.
A compose file is more like a manual: instructions for how to use something.
You use a Dockerfile to build an image. This image is the combination of an OS and your source code.
Next you can spin up your image, resulting in container. You can spin up/run an image using docker run
or a docker-compose.yml
file in which you specify how it should run. A running image is called a container. Here is where you specify how the container fits in your deployment and here is also where you can link together containers e.g.
Conclusion
I hope that after reading this article you have a more clear understanding of both the vocabulary Docker uses, and the way Docker works. I hope this article was clear but if you have suggestions/clarifications please comment so I can make improvements. In the meantime, check out my other articles on all kinds of programming-related topics like these:
- Docker for absolute beginners
- Docker Compose for absolute beginners
- Turn Your Code into a Real Program: Packaging, Running and Distributing Scripts using Docker
- Why Python is slow and how to speed it up
- Advanced multi-tasking in Python: applying and benchmarking threadpools and processpools
- Write you own C extension to speed up Python x100
- Getting started with Cython: how to perform >1.7 billion calculations per second in Python
- Create a fast auto-documented, maintainable and easy-to-use Python API in 5 lines of code with FastAPI
Happy coding!
— Mike
P.S: like what I’m doing? Follow me!