Like announced at the beginning of the new year, I am writing a series about managing Kubernetes with DevOPs methods. Having started with a little warm-up about Kubernetes and a short comparison of VM vs Bare Metal, this post will shed a bit of light onto the container platform Docker itself. While Docker works equally good on major operating systems like Windows, MacOS and various Linux distributions, I’ll focus solely on Linux as main cloud OS.
If you never worked with Docker before, now it should be a good time to start, better late than never. A great starting point would be the docker docs web page, where you find everything you need. Most likely you will go and install the docker engine first time manually, as described here for CentOS. That tutorial will show you the manual way, which is good to know for the various and tedious steps normally required. There is also a Docker Desktop, but most likely you will not need that, at least I never did. I decided to include the main steps here as well to deliver a one-stop-shop, it might make things easier for the beginner.
In CentOS, much like with every RedHat based destribution, you need to work with Yum repositories. Much software is already included via the main distribution, i.e. base or extra repos. Docker lives in the latter one. To install it, do the following steps:
yum-utils package (which provides the
yum-config-manager utility) and set up the stable repository.
$ sudo yum install -y yum-utils $ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
Afterwards you can right away install Docker:
$ sudo yum install docker-ce docker-ce-cli containerd.io
Go and enable the service:
$ sudo systemctl start docker
Well done, you are set to get in action.
Unlike a Virtual Machine, which still operates a full blown OS and applications on top, a Docker container shares resources like Memory, CPU, Disk space etc. with the host. It contains ( hence the word
Container) only what is required to run your application, which often is only a few MegaBytes worth of size. The container will live in its own container network, which is exposed to the host and thus to the outside world, if allowed via firewall rules etc. One of the most important things is that typically you will be able to run your desired app with default settings to get started quickly. For instance, running a full blown apache web server typically takes a good number of steps for installation and configuration first. Using it in a docker container takes much less steps and can be done within a few minutes. Of course providing the stuff you want to have displayed, aka your website, still is a requirement.
The manual way is adding a docker group, but is not adding a user to it. As long as your user is not part of this group, you will have to be using sudo commands to work your way around Docker. There is pro’s and con’s to both ways, but when using DevOPS methods, you get away nicely with a good and secure compromise. Your developers would have docker locally installed on their workstations to do their deeds, and have their user added locally for convenience. When you roll out the docker images to your infrastructure through things like Puppet, Ansible or similar things, you won’t need that there. More about the Puppet way later below.
Docker standalone is allowing you to run one or more containers simultaneously, but you will have to do all the resource management yourself, at least in the manual way. You will need to choose what to run where, i.e. which container on which host, and make sure the required resources i.e. RAM, CPU cycles etc are available.
Once you enabled and started the docker service, you are pretty good to go for your first docker container:
$ sudo docker run hello-world
Details about the available docker commands can be found here. Usually you will use additional parameter on CLI, like -p to specify ports, -d to run in the background, -n for a name, -v for volumes, and -e for environmental values:
$ docker run -d -n -my-app -v /data/share/my-app:/etc/my-app -p 8080:80 -e MY_ENV_LOG_INT=1s
These are example values of course. When developing applications in docker, you most likely will be using some of them as that is essential for testing your stuff. Even though on a certain level you will likely start using automated testing pipelines on Jenkins, Gitlab.ci etc, the first steps always include local manual testing, like docker build etc.
The section above briefly described Docker using CLI methods. When you first start with Docker, you probably will use those. Sooner or later you probably will run into multi-container scenarios like a dynamic website with database, which need to run in a specific order and setup. While this can be managed with CLI or docker config files, there is a better option called docker compose. Here you define all your settings in a yaml file called docker-compose-yml, and simply use the
docker compose up command to run your predefined app. Using such files is a great thing, as you can store that versioned in your software repository, for instance via gitlab and very easily use it with CICD pipelines.
Those yaml files are your best friend, because they are used as well with Docker Swarm and Kubernetes for defining everything about your app. More about this in coming posts.
Automating Docker standalone with Puppet
Now that you discovered the manual way as starting point, let’s have a look at the automated way via
Infrastructure as Codemethods. While I will write a series about Puppet itself soon, this article here is not the right place to go into all that just now.,
Assuming you have a proper Puppet infrastructure in place, the easiest way is to include the docker module from the puppet forge in your catalog. This module allows you to automatically install the correct docker components, as well as defining desired container options etc. It will create a service for the docker container itself, so Puppet can manage the status of the container as required. The how to is documented on the linked page.
This way, you can run the container landscape via infrastructure as Code and can rely on Puppet to have things done for you. Each time the puppet agent runs, it will check for the given desired status and can run corrective actions if needed. For instance, Docker standalone will not automatically restart failed containers, as it lacks the features for that. The Puppet run however will see if the container is not running as desired, and will start it for you.
In case you are not satisfied with the external module for some reason ( i.e. when having requirements it cannot deliver or you want it more simple), you can always write your own module, as I did. The problem with modules from the Puppet forge is always, that they are built for many different scenarios, operating systems, use cases etc. , where you probably have the need for much less complexity. Nonetheless, this particular one I have worked with for a previous customer, and can recommend it indeed for a Docker standalone environment. Once you come to using Docker Swarm or Kubernetes, this likely changes as the requirements and solutions for those are quite different. However, this very much depends a lot on your business – and infrastructure needs , as is always the case.