Podman Basics

I needed to test some scripts on Linux (I’m on a Mac) and figured why not take this time to learn how to build some containers with Podman. I specifically chose Podman as it’s free and open source, making it a great Docker alternative especially for enterprises.

To setup podman cli, we can install it from brew or download the pkg directly from the website and follow the instructions to init and start.

Some basic podman commands to know:

  • podman search - searches registry for images
  • podman pull <image_name> - pulls an image from a registry
  • podman ps -a - shows all running containers (even stopped ones)
  • podman images - shows all images downloaded
  • podman rmi <image_name> - remove image
  • docker build -t <image_name> . - build a custom image using the Dockerfile in the current directory
  • docker run -it --name <container_name> <image_name> - run in a new container and creates a new container from an image
  • podman exec - run a process in a container

Dockerfile

We can build custom images by creating a Dockerfile, which basically is a set of instructions to follow when building an image.

Here’s a sample Ubuntu image Dockerfile, created with the help of chatgpt:

FROM ubuntu:latest

# Install required tools
RUN apt update && apt upgrade -y && apt install -y \
   curl \
   gnupg2 \
   vim \
   net-tools \
   wget \
   unzip \
   netcat \
&& rm -rf /var/lib/apt/lists/*

# Download and add GPG key for gopass repo
RUN curl -fsSL https://packages.gopass.pw/repos/gopass/gopass-archive-keyring.gpg | \
   gpg --dearmor -o /usr/share/keyrings/gopass-archive-keyring.gpg

## Add gopass repository to apt sources
RUN echo "deb [signed-by=/usr/share/keyrings/gopass-archive-keyring.gpg] https://packages.gopass.pw/repos/gopass stable main" \
   > /etc/apt/sources.list.d/gopass.list

# Update package index and install gopass
RUN apt update && apt install -y \
   gopass \
   gopass-archive-keyring \
&& rm -rf /var/lib/apt/lists/*

# Clean up
RUN rm -rf /usr/share/keyrings/gopass-archive-keyring.gpg

# Copies local file called bashrc & vimrc in local host directory to /tmp/bashrc & /tmp/vimrc on container
COPY bashrc /tmp/bashrc
RUN cat /tmp/bashrc >> ~/.bashrc

COPY vimrc /tmp/vimrc
RUN cat /tmp/vimrc >> ~/.vimrc

# Set the working directory
WORKDIR /root

# Defines default command
CMD ["/bin/bash"]

First we pull the image we want from the registry after searching for it.

❯ podman search ubuntu
INDEX       NAME                                      DESCRIPTION                                      STARS       OFFICIAL    AUTOMATED
docker.io   docker.io/library/ubuntu                  Ubuntu is a Debian-based Linux operating sys...  16977       [OK]        
docker.io   docker.io/library/ubuntu-debootstrap      DEPRECATED; use "ubuntu" instead                 52          [OK]        
docker.io   docker.io/library/neurodebian             NeuroDebian provides neuroscience research s...  107         [OK]        
docker.io   docker.io/library/websphere-liberty       WebSphere Liberty multi-architecture images ...  298         [OK]        
docker.io   docker.io/library/open-liberty            Open Liberty multi-architecture images based...  64          [OK]        
docker.io   docker.io/library/ubuntu-upstart          DEPRECATED, as is Upstart (find other proces...  115         [OK]        
docker.io   docker.io/ubuntu/nginx                    Nginx, a high-performance reverse proxy & we...  112                     
...

❯ podman pull ubuntu                   
Resolved "ubuntu" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
Trying to pull docker.io/library/ubuntu:latest...
Getting image source signatures
Copying blob bccd10f490ab done  
Copying config ca2b0f2696 done  
Writing manifest to image destination
Storing signatures
ca2b0f26964cf2e80ba3e084d5983dab293fdb87485dc6445f3f7bbfc89d7459

❯ podman images
REPOSITORY                TAG         IMAGE ID      CREATED      SIZE
docker.io/library/ubuntu  latest      ca2b0f26964c  5 weeks ago  80.4 MB

After pulling the image, we can create a custom image using the Dockerfile. The beginning of the dockerfile specifies a base image we can use: FROM ubuntu:latest

❯ podman build -t ubuntu_custom_image . 
STEP 1/12: FROM ubuntu:latest
STEP 2/12: RUN apt update && apt upgrade -y && apt install -y    curl    gnupg2    vim    net-tools    wget    unzip    netcat && rm -rf /var/lib/apt/lists/*
...

❯ podman images
REPOSITORY                     TAG         IMAGE ID      CREATED         SIZE
localhost/ubuntu_custom_image  latest      6d689e465837  22 seconds ago  285 MB
docker.io/library/ubuntu       latest      ca2b0f26964c  5 weeks ago     80.4 MB

Now we can create a container and run an interactive shell using the -it option. They stand for “interactive” and “pseudo-TTY”. The -i option makes the session interactive, and the -t option allocates a pseudo-TTY, allowing you to interact with the shell.

❯ podman run -it --name ubuntu_container ubuntu_custom_image
root@1623365303af:~# ls -a
.  ..  .bashrc  .profile  .vimrc

We can check the status of our container.

❯ podman ps -a
CONTAINER ID  IMAGE                                 COMMAND     CREATED        STATUS                         PORTS       NAMES
1623365303af  localhost/ubuntu_custom_image:latest  /bin/bash   2 minutes ago  Exited (0) About a minute ago              ubuntu_container

To get back in, we need to make sure that it’s started.

❯ podman start ubuntu_container             
ubuntu_container

❯ podman ps -a                              
CONTAINER ID  IMAGE                                 COMMAND     CREATED        STATUS            PORTS       NAMES
1623365303af  localhost/ubuntu_custom_image:latest  /bin/bash   4 minutes ago  Up 6 seconds ago              ubuntu_container

❯ podman exec -it ubuntu_container /bin/bash #this starts an interactive shell 
root@1623365303af:~# 

We can also just execute the command without an interactive shell from within the container.

❯ podman exec ubuntu_container ls -la  
total 24
drwx------ 1 root root 4096 Apr  3 07:18 .
dr-xr-xr-x 1 root root 4096 Apr  3 07:17 ..
-rw------- 1 root root   16 Apr  3 07:23 .bash_history
-rw-r--r-- 1 root root 3237 Apr  3 07:16 .bashrc
-rw-r--r-- 1 root root  161 Jul  9  2019 .profile
-rw-r--r-- 1 root root  100 Apr  3 07:16 .vimrc

❯ podman exec ubuntu_container cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.4 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

Now we can run whatever we want on our containers! It’s a pretty light and easy way to test things without impacting our host system or running a VM with a gui.