Moving Development Environment to Containers with Podman
What Is Podman and Does It Work?
Podman is a replacement for Docker for local development of containerized applications. Podman commands map 1 to 1 to Docker commands, including their arguments. You could alias docker with podman and never notice that there is a completely different tool for managing your local containers.
One of the core features of Podman is its focus on security. There is no daemon involved in using Podman. It uses a traditional fork-exec model instead and also heavily utilizes user namespaces and network namespaces. As a result, Podman is a bit more isolated and in general more secure to use than Docker. You can even be root in a container without granting container or Podman any root privileges on the host — and user in a container won't be able to do any root-level tasks on the host machine.
A good example of how Podman's model can lead to better security is covered in an article, "Podman: A more secure way to run containers." If you want to learn more about how Podman leverages Linux namespaces, start with, "Podman and user namespaces: A marriage made in heaven" article. Finally, if you want to read about possible obstacles that you might have with this approach, then read, "The shortcomings of rootless containers."
For most of the users, the internals of Podman should not matter too much in a day-to-day use. What does matter is that Podman provides the same developer experience as Docker while doing things in a slightly more secure way in the background. Let's see if that's true.
Local Development Environment of mkdev.me
The main web application behind mkdev.me is written in Ruby on Rails. For a developer to be able to run this application locally he or she needs:
PostgreSQL server;
Redis server;
Mattermost instance (for our chat solution);
Mattermost test instance (to be used during automated tests);
In total, that's five services to run locally (including web application itself). One can imagine that for any new developer to install and configure all of it by hand can take quite some time. And once it's done, there is no guarantee that resulting local environment is close to the production one: a developer could install different PostgreSQL or Mattermost versions, that were not yet tested to work with mkdev.
Wouldn't it be great to bootstrap a complete development environment with one command and get a production-like setup running in seconds? That's what Docker and Docker Compose provided developers with. That's what Podman can provide as well.
Podman's Pods and What They Are Good For
On top of the regular containers, Podman has pods. If you ever heard of Kubernetes, this concept is familiar to you. In Kubernetes, a pod is the smallest deployment unit that consists of one or more containers. Podman's pods are exactly the same. All containers inside the pod share the same network namespace, so they can easily talk to each other over localhost without the need to export any extra ports.
There are three possible use cases for pods.
1. Prepare Your Application for Running on Kubernetes/Openshift
You could use pods in Podman as a preparation step before moving it to Kubernetes. In many cases, for real-world web applications, you probably will be better off using minikube, which will guarantee you the same APIs and functionality Kubernetes has. You would want to have Deployments, Services, and other resources, that would be a vital part of your setup in production. Just having a way to simulate pods with Podman won't be of much benefit for this.
2. Run Your Application with Podman in Production
You could decide that complete container orchestration is an overkill for you (and that would be a very good decision in many cases). Then it would make sense to still use containers for packaging and delivering your application. And in certain cases, you could benefit from not just running one container, but running multiple ones inside the pod on your production server. The question is what exactly will be the benefit of putting your containers inside the pod versus just running them as separate systemd managed services? I don't have a good answer here, but the feature is there and someone might find a use case for it in production.
3. Simplifying Your Development Environment
The final and the most attractive reason for developers is to use Podman pods to automate development environment. In this case, you would run all the services your application depends on inside the same pod. This is absolutely not something you should ever do in production environment on a real Kubernetes cluster, as your services should be running in different pods behind different replication controllers and service endpoints. But for local development doing it this way is convenient.
Podman Pods and Kubernetes Pods
Before we move to some real examples, we need to learn about one pod-related feature of Podman: play kube
. Podman doesn't have a replacement to Docker Compose. There is a third-party tool podman-compose that might bring this functionality, but we at mkdev didn't get to test it yet.
Instead of Docker Compose, Podman has pods and a way to run them out of YAML definition. This YAML definition is compatible with Kubernetes pods YAML, meaning that you can take this YAML, load it into your Kubernetes cluster and expect some pods running.
Out of scope: Supporting docker-compose. We believe that Kubernetes is the defacto standard for composing Pods and for orchestrating containers, making Kubernetes YAML a defacto standard file format. - Podman documentation
You could use pods in Podman as a preparation step before moving it to Kubernetes. In many cases, for real-world web applications, you probably will be better off using minikube, which will guarantee you the same APIs and functionality Kubernetes has. You would want to have Deployments, Services, and other resources, that would be a vital part of your setup in production. Just having a way to simulate pods with Podman won't be of much benefit for this.
Basic Usage of Podman
We first need to create a new pod that will expose port 5432:
We can see running pods with podman pod ps
command:
When you create a new pod, Podman automatically starts infra
container, which you can see by running podman ps
.
Let's start a PostgreSQL container inside this pod:
If you don't have postgres:latest
image yet, Podman will pull it automatically, from Docker Hub — the same experience you would have with Docker CLI.
Let's start another container inside postgresql
pod: with a PostgreSQL Prometheus exporter:
We can see top processes inside the pod with podman pod top postgresql
command. And we can access PostgreSQL metrics if we curl localhost:9187/metrics
.
If we want to create the same setup again without running imperative shell commands and to store this setup as a declarative code, we can run podman generate kube postgresql > postgresql.yaml
which will result in a Kubernetes-compatible pod definition. If you follow the link and examine this YAML file, you will see that Podman correctly configured all the ports and even exported all the environment variables, which you can cleanup if you want to rely on the image defaults.
Remove the pod with podman pod rm postgresql -f
. Then, instead of running all of the commands again, simply run podman play kube postgresql.yaml
to get the same result. You could also kubectl apply -f postgresql.yaml
and get this PostgreSQL running on your Kubernetes cluster.
Warning: if you happen to use Podman 1.4.2, then at this point you will hit a bug described in this GitHub Issue. Let's hope by the time you read it the issue is fixed. If it's not fixed, then follow steps to fix your YAML from the Issue description or simply copy contents of my gist, which already contains a fixed definition.
The YAML file generated by Podman should not be used "as is," because Podman dumps all environment variables, securityContext and other things that you could leave without in your development environment and that might have better defaults in your Kubernetes cluster. Consider it a convenient scaffolding, not a final result.
Using Podman in a Real Ruby on Rails Application
At mkdev we completely automated our development environment with Podman. New developers (assuming they have a Linux machine running) can run a single script ./script/bootstrap.sh
to get the application running. The script itself looks like this:
Reference
Source -> https://dzone.com/articles/dockerless-part-3-moving-development-environment-t
Comments
Post a Comment