4 min read

How to Run Secure Pods with Podman

How to Run Secure Pods with Podman

What is Podman?

Podman is a Red Hat container engine that allows users to manage containerized applications and their resources. Unlike other container engines such as Docker, Podman operates as a standalone application instead of a daemon. Podman could be a Docker replacement.

As I stated in my previous article Docker, Docker was unsupported by Kubernetes a few years ago. But don't worry! Kubernetes does not support Docker as a runtime (dockershim), but images are still supported; Docker images are Open Container Image (OCI).

More information about this deprecation can be found here.

Return to the main topic! Podman provides a command-line interface (CLI) through which users can create, manage, and deploy containers in either rootless or rootfull mode. Podman runs containers as non-root users in rootless mode, which improves security by lowering the attack surface. Podman can run as the root user in rootfull mode, which provides access to system resources.

One of the key features of Podman is its support for pods, also known as Kubernetes, which are groups of containers that share the same network and storage resources. Pods enable users to deploy and manage complex applications that require communication between multiple containers, such as a database and a web application.

Don't worry! Podman also supports a variety of container image formats, including the Docker format, for close friends Dockerfile. This enables users to easily move containerized applications between container engines and platforms.

First, install Podman on your operational system by following the official instructions.

1. Choosing an image

Because size is an important consideration when selecting an image, let's keep Alpine Linux as our base mage. Just 40MB to lightweight and secure system. Only 40MB are required for a lightweight and secure system.

It is important to note that podman works with any Docker Registry, such as DockerHub images or Red Hat Quay.

2. Creating Containerfile

It's time to use Podman to build your pod. Let's create some asset files so we can build the container image. This time I choose Elixir application, on which I have been working for the last few years. The application will show a random fruit.

Elixir is a fabulous function language that runs on top of Erlang and was created by Brazilian JosΓ© Valim.
  • mix.exs
defmodule Fruit.MixProject do
  use Mix.Project

  def project do
    [
      app: :fruit,
      version: "0.0.1",
      elixir: "~> 1.14",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

  # Run "mix help compile.app" to learn about applications
  def application do
    [
      extra_applications: [:logger]
    ]
  end

  # Run "mix help deps" to learn about dependencies
  defp deps do
    [
      {:plug_cowboy, "~> 2.5"}
    ]
  end
end
  • server.ex
require Logger

defmodule Fruit.Plug do
  import Plug.Conn

  @fruits [
    "πŸ₯",
    "πŸ“",
    "πŸ₯­",
    "🍍",
    "🍊",
    "πŸ‹",
    "🍈",
    "πŸ‘",
    "πŸ‡",
    "πŸ‰",
    "πŸ₯‘",
    "πŸ…",
    "🍌",
    "🍐",
    "🍎",
    "🍏"
  ]

  def init(options), do: options

  def call(conn, _opts) do
    fruits_size = Kernel.length(@fruits)
    index = :rand.uniform(fruits_size - 1)
    fruit = Enum.at(@fruits, index)

    conn
    |> put_resp_content_type("text/plain">)
    |> send_resp(200, "What kind of fruit is that? #{fruit}")
  end
end

Logger.info("Starting application")

Plug.Adapters.Cowboy.http(Fruit.Plug, [], ip: {0, 0, 0, 0}, port: 3000)
  • Containerfile
I named the file Containerfile, but the syntax is same to Dockerfile.
FROM docker.io/library/elixir:1.14-alpine

ENV MIX_ENV=prod

MAINTAINER [email protected]

WORKDIR /app

RUN mix local.hex --force && \
    mix local.rebar --force

COPY mix.exs server.ex ./

RUN mix deps.get --all

RUN mix compile

EXPOSE 3000

CMD mix run --no-halt server.ex

3. Building a pod

Next, we'll use the build to command to convert our Containerfile into an image called my-first-pod.

podman build -t [image-name] [base-directory]
podman build -t  my-first-pod .

4. Running a pod

We can run a pod in two modes: foreground mode (with your terminal attached) or background mode (with your terminal detached).

# attached
podman run --name my-first-pod --rm -p 3001:3000 my-first-pod

# detached
podman run -d --name my-first-pod -p 3001:3000 my-first-pod

# run command inside pod
podman exec -it my-first-pod sh
  • --name to set a container unique name;
  • --rm remove container after stop container;
  • -p 3001:3000 indicate that public port 3001 will be forwarded in container to private port 3000;
  • -d run at background mode with detached terminal;

Testing the pod

Then we'll use curl to send a request to your endpoint (http://localhost:3001/).

curl  --location  http://localhost:3001/
> What kind of fruit is that? πŸ…

Pod inspection

podman ps -a
podman images
podman logs -f my-first-pod
> fruit: 🍏

podman exec -it my-first-pod sh
  • ps list all pods available, without argument -a list only running pods;
  • images list all built images;
  • logs inspect what pods are written to sdout or stderr;
  • execrun a command in a running container, -it changes our terminal inside the container as interactive mode.

Cleanup

podman stop my-first-pod
podman rm my-first-pod
podman rmi my-first-pod
  • stopstop pod execution;
  • rm remove defintive pod;
  • rmiremove pod

Final thoughts

If you prefer, you can clone the repository

Today, we'll build a pod with Podman. As you can see, Podman uses the same commands and syntax as Docker, making migration and replacement a breeze. As I said before, Docker is not completely incompatible with Kubernetes; however, Podman is an option; as Rockets(rkt), you should consider what fits your current Project or Team.

In the coming articles, I'll go over how to add multiple containers within pods, just like we did in Kubernetes.

Your kernel has been updated! God bless your day.

References