Docker 101: Basic Theory
This is the beginning of a short blog series about docker containers, where we will explore the world of containerisation from the ground up. I will be assuming the respectable readers have no prior experience with docker 👾
What is Docker and why is it useful? 💬
Essentially, Docker is an ecosystem (or a platform) around creating and running containers. This ecosystem includes the docker client, docker server, docker compose, images, Hub and machine. Docker makes is super easy to install and run software without having to bother with setup or dependencies.
Okay, but what is a container?
A container is an instance of an image and it runs a program. This program has its own set of isolated resources, meaning the running program inside of the container does not have the ability to access/ “see” any resources outside of it. There are, of course, ways to have a container be exposed to other containers using docker compose which is something we will have a go at during future blogs.
An image, also known as a docker image, is a single file with all the dependencies and configuration required to run a program and is “built” to create an instance of a container.
Docker also makes use of namespacing and control groups (cgroups) where docker isolates resources per process (or group of) and limit the amount of resources used (memory, CPU usage, network bandwidth etc)
Image => Container 📸
An image contains a file system snapshot and a start up command. For instance, if we pull the busybox image from docker hub, build a container from it and list the files and folders within the root directory, we may see something like “bin”, “dev”, “etc”, “home” and so on. Respectively, the instructions for the start up command are stored within that file system and will be executed as soon as we start running our container.
When we build and start our container from the image, we are essentially copying over the file system to the container with isolated resources and executing the start up command.
The Whole Process 📈
Using a pre-existing image (pulled from Docker Hub): this approach is really simple, we simply run “docker run <container_name>” and docker will go ahead and pull the image from docker hub, build it and run it. The next time we use the docker run command for that particular image, we skip the build process and use the cached version. Super fast!
Using our own image: this approach involves a few more steps;
- firstly, we create our image using a Dockerfile (it’s just a text file called “Dockerfile”)
- we build the image into a container using “docker build . ” (assuming we are located at the directory of the Dockerfile)
- from the terminal we locate our built container’s ID using “docker ps -all”
- we use that ID to run the container using “docker run <container_id>
- and voila 🎉 we have a running container
That’s it for now ^.^
We have learned a little bit about what containers are and how they work, in the next blog we will start playing around with the docker client and put our theory to the test. See you there! 👋🏻