Note: There is a better way to go about this, Guix now contains rootless-podman-service-type
which will take care of it all pretty much for you. This article is thus outdated, and explains how we did things before that!
Thanks Hugo Buddelmeijer for alerting me to that, he wrote a blog post here: https://entropynaut.com/post/guixpodman/
Have you ever heard about Docker ? Containerization has revolutionized the way we deploy and manage applications. By isolating processes and their dependencies, containers offer a lightweight and efficient solution for software deployment and help reproducibility.
GNU Guix, a powerful and pure functional system and package manager, provides a robust foundation for building and managing software systems.
By leveraging Podman, a daemonless container engine, we can achieve rootless containerization, enhancing security and flexibility.
In this post I will explain what it takes to setup Podman in a root-less manner, for your user in Guix.
Every engineer in anno 2024 ends up spinning a “Docker” container or two in their job or as a hobby, so for me it’s important to be able to do this seamlessly in my beloved Guix system, or as I have recently taken to calling it, Supreme Sexp System - see more here.
# Why not Docker?
Podman is basically an upgrade in several fronts:
- Security
- Simplicity
- Modularity
- Consistency
- Features (pods, compose, kube, etc)
Basically all the functionality of the docker, but a bit cleaner implementation and organization wise.
# Adding to Guix
Make sure to remove Docker installation first completely and then the docker
group from your users, if you previously used docker:
(user-account (name "joe") (group "users") (supplementary-groups '("wheel" "netdev" "audio" "video" "input")))
Then we will need to allocate some sub-uids and sub-gids, and for that we create a etc-service
with Guix:
(define sss-joe-subuid (simple-service 'podman-subuid-subgid ;; If subuid/subgid will be needed somewhere else, the service must be ;; created to handle it. etc-service-type `(("subuid" ,(plain-file "subuid" (string-append "joe" ":100000:65536\n"))) ("subgid" ,(plain-file "subgid" (string-append "joe" ":100000:65536\n"))))))
iptables
service or equivalent is necessary for networking in Podman:
(define sss-iptables (service iptables-service-type (iptables-configuration)))
You can feel free to also alias in your shell docker to podman, to help you rebuild muscle memory, e.g. .
alias docker-compose="podman-compose" alias docker="podman" alias podman-unix-socket="podman system service --time=0 unix:///tmp/podman.sock"
For running with Testcontainers, one should use the Unix socket.
podman system service --time=0 unix:///tmp/podman.sock
DOCKER_HOST
should be set to the socket you use, e.g. unix:///tmp/podman.sock
You can do this with Guix home or manually before running certain programs.
You should also configure container registries and policies, for example with Guix Home:
`((".config/containers/registries.conf" ,(plain-file "registries.conf" "unqualified-search-registries = ['docker.io', \ 'registry.fedoraproject.org', \ 'registry.access.redhat.com', \ 'registry.centos.org']")) (".config/containers/policy.json" ,(plain-file "policy.json" "{\"default\": [{\"type\": \"insecureAcceptAnything\"}]}")) )
You will then need some packages from Guix packages:
slirp4netns podman podman-compose passt
# Testing
Make sure you reboot and have cleaned any previous trace of Docker.
Check if things work then:
podman ps -a podman run --rm alpine ls / -lia podman images podman ps -a podman run -dt -p 8080:80/tcp httpd podman stop -l podman rm -l
Or run your favourite integration test pipeline.
# Enjoy
🎉 Now you should be set to run testcontainers, even with Ryuk. Otherwise make sure to tweak ~/.testcontainers.properties
.
Podman is in technical terms also superior and cleaner than Docker, as well as a more permissive license.
Using a root-less setup (no sudo for docker) one achieve more stability and flexibility in the system.
Podman is also daemon-less, which brings great benefits, but can be used via Unix sockets too on demand.
See the official documentation of Podman root-less here: https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md https://github.com/containers/podman/blob/main/rootless.md https://opensource.com/article/19/2/how-does-rootless-podman-work
# Shoutout to Andrew!
Make sure to check Andrew Tropin’s video for another great explanation on this interesting topic:
https://www.youtube.com/watch?v=CC7t7foYkko&list=LL&index=1&t=305s