I have been using Docker for a while now, it’s being used to provide services to friends and family.
I was always intimidated by the large amount of packages that were needed to get Docker and docker-compose up and running, and I did not have experience with Docker at the time (almost two years ago) so I decided to go the easy route and use the SlackBuilds.org scripts when I first needed to run a Docker container. I wrote a blog about that even, it explained how to run an Outline server to allow journalists to do their work in repressive countries but the article also shares the details how to build the Docker packages and run the daemon.
If you want to read some background information about Docker’s strength and what its use-cases are, I encourage you to start reading here: https://docs.docker.com/get-started/overview/ .
Essentially, Docker uses Linux kernel and filesystem capabilities to isolate an application and its dependencies from the host computer it is being executed on. Docker provides powerful means to connect multiple containers via internal (virtual) networking and can expose ports to the network outside of your container. It enables you to run applications reliably without having to worry about the underlying Operating system. You can even run Docker on a MS Windows computer but your containerized application running inside Docker will not be aware of that.
This is sometimes called ‘light-weight virtualization’ because unlike real virtualization solutions like QEMU, Virtual Box or VMWare, the containerized application still runs on your host’s kernel. This is why you can run a 32-bit container image on a 64-bit (Linux 64-bit kernel has that capability to execute 32-bit binaries) host but you cannot run a 64-bit image on a 32-bit host kernel.
Now that I am more familiar with Docker, have been running multiple services in containers for more than a year, and have created and published my own images (more about that later) I decided to create my own set of Docker packages. Having pre-built packages will make it a lot easier for people to start exploring the usefulness of Docker containers.
One thing upfront: I have significantly decreased the total amount of packages you need to run Docker.
I have combined the SlackBuilds.org packages ‘docker’, ‘docker-cli’, ‘docker-proxy’ and ‘tini’ into a single package called ‘docker’ and also added ‘docker-buildx’ to that docker package. Also, the re-write of docker-compose from Python to Go has the benefit that the run-time package dependencies for ‘docker-compose’ have been reduced from thirteen to zero.
Starting with my Docker packages
As stated in the subject: the packages I created are for Slackware-current only. If you want to compile this yourself on Slackware 14.2, I cannot guarantee success since I did not try compiling them there myself – but in any case you’ll have to build and install libseccomp from SlackBuilds.org, this is part of -current but not 14.2.
What you need from my repository to run Docker is: runc, containerd, docker and docker-compose. Four packages – that’s it.
If you want to be able to (re-)compile these packages, you will additionally need google-go-lang. After installing google-go-lang you need to logoff and login again (or run the command “source /etc/profile.d/go.sh” in your terminal) to give Google’s version of Go preference over the GCC version of Go that’s probably already installed on your computer.
The ‘docker’ package installation script will add a couple of lines to “/etc/rc.d/rc.local” and “/etc/rc.d/rc.local_shutdown” to make Docker start on boot and properly stop during shutdown of the computer. The docker rc script “/etc/rc.d/rc.docker” will initially be installed without the execute bit, so if you actually want to start using Docker you have to make the script executable. This is a one-time action. Future package upgrades will honor the executable status of that script.
# chmod +x /etc/rc.d/rc.docker
You can start the Docker daemon now if you don’t want to waste time with a reboot:
# /etc/rc.d/rc.docker start
The package installation will also trigger the creation of a new group called ‘docker’. If you want to be able to run and manage your Docker images and containers as your own non-root user account, you need to add your user account to this ‘docker’ group and then logoff/login again, and restart the docker deamon. Otherwise, all Docker operations can only be executed by the root user.
# gpasswd -a <your_useraccount> docker # /etc/rc.d/rc.docker restart
After doing all the prep work, your account added to the ‘docker’ group and the daemon running, it’s time for a first test. Run the following command:
$ docker run hello-world
You’ll see the following output:
Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 2db29710123e: Pull complete Digest: sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly ...
What you will have validated here is the proper functioning of your Docker installation:
- The Docker command-line client contacted the Docker daemon.
- The Docker daemon downloaded (or ‘pulled‘) the “hello-world” image from the Docker Hub.
- The Docker daemon created a new container from that image which runs the executable that produces the output you could read on your terminal just now.
- The Docker daemon streamed that output to the Docker client, which sent it to your terminal.
The “hello-world” image is of course trivial, but there are many more with real-life use-cases which you can find on Docker Hub, https://hub.docker.com/. You can download these images freely but if you want to upload (or ‘push’) an image which you created yourself, you’ll have to create an account on Docker Hub. Free acccounts allow the creation of one single private repository and unlimited public repositories.
Slackware Docker images
I have a repository on Docker Hub where I share my base images for stable Slackware versions (that’s the 14.2 release right now). Go get them at https://hub.docker.com/r/liveslak/slackware/tags . These “base images” are roughly 55 MB compressed, which means they are really basic. They are created using a script (create_slackware_docker_image.sh) which takes its inspiration both from the liveslak scripts and of Vincent Batts‘ work on Docker images for Slackware. Essentially, the script installs some packages into a package root, uses tar to put all of that in a tarball and loads the tarfile into Docker which will then make it into an actual image for you. That image wille be called “slackware:base_x64_14.2” (unless you specified a different architecture and release of course) and that’s what I uploaded to the Docker Hub.
My tiny Slackware docker-images are not really meant to be used as-is. Instead, they can act as the foundation for Slackware-based Docker images that you might want to build yourself – any Docker image starts with some existing base image and adds new layers on top. Base images like mine above don’t inherit from a lower-level image and are a special case, read more here: https://docs.docker.com/develop/develop-images/baseimages/
Now let’s pull that Slackware base image from the Hub and peek inside!
$ docker run -ti liveslak/slackware:latest /bin/bash -l
The “-ti” parameters tell docker to assign a pseudo-tty and run an interactive session on your terminal.
The convention for the image name is “username/imagename:tag” which shows that “liveslak” is the user who hosts the image on Docker Hub; “slackware” is the name of the image and it has a tag “latest” which means: just give me the latest version that I can get. For the slackware image, this means you get the 64-bit variant (I also have a 32-bit image) of Slackware 14.2.
The “/bin/bash -l” at the end is the command which Docker should run after bringing the container online. Remember, the base image contains nothing but a small amount of installed Slackware packages and does not start any application by itself. More complex Docker images may run all kinds of applications, some in the background and some meant to be interacted with such as the bash shell.
Running the above command yields this result:
Unable to find image 'liveslak/slackware:latest' locally latest: Pulling from liveslak/slackware 6c721e5d29bd: Pull complete Digest: sha256:352219d8d91416519e2425a13938f94600b50cc9334fc45d56caa62f7a193748 Status: Downloaded newer image for liveslak/slackware:latest root@b0264b9e59ff:/#
And we end up at the command prompt of our running container. The container user is ‘root’, it’s the only user in that base image. You do not have to enter a password.
Let’s play a bit:
root@b0264b9e59ff:/# ls /var/log/packages/ | wc -l 77 root@b0264b9e59ff:/# cat /etc/os-release NAME=Slackware VERSION="14.2" ID=slackware VERSION_ID=14.2 PRETTY_NAME="Slackware 14.2" ANSI_COLOR="0;34" CPE_NAME="cpe:/o:slackware:slackware_linux:14.2" HOME_URL="http://slackware.com/" SUPPORT_URL="http://www.linuxquestions.org/questions/slackware-14/" BUG_REPORT_URL="http://www.linuxquestions.org/questions/slackware-14/" root@b0264b9e59ff:/# exit logout $
Suppose you want want to download and use the 32-bit Slackware 14.2 base image instead. Then you would run:
$ docker run -ti liveslak/slackware:base_ia32_14.2 /bin/bash -l
Here ends my very brief introduction to Docker on Slackware. Let me know what you think of this! Is there anything you would like to see explained in more detail?
Update 2022-jan-13: I have added packages for Slackware 14.2 (32bit and 64bit) to my repository.