Technology / DevOps

How to Create a Podman File

How-to-Create-A-Podman-File
Follow us
Published on August 6, 2025

Quick Answer: When people talk about creating a Podman file, they're usually referring to a text document called a Containerfile that contains step-by-step instructions for building container images using Podman. It works just like a Dockerfile but runs in Podman's rootless, daemonless environment for better security.

Creating container images manually gets old really fast. The general steps usually go something like: install packages, copy files, then configure settings. Then, the best part—repeat the whole process again when you need to make changes. 

This is fine for a few images, but when you need to scale to tens or hundreds of installs, then you see the problem. The good news is that there is a much easier way to get the job done, and with less repetition. Podman files come to the rescue and automate everything so you can build repeatable container images with just a single command.

Podman is a solid alternative for developers who want container technology without Docker's security woes. It runs without root privileges and doesn't need a daemon running in the background either. When you create a Podman file, you're really just building images in a more secure way, and keeping the syntax that Docker users already know.

This guide walks you through creating your first Podman file from scratch. You'll see the basic commands and how to stay away from common issues so that you can build images that actually work in production. 

What is a Podman File?

When you create a Podman file, you're actually creating what's technically called a Containerfile —a script that tells Podman how to build a container image automatically. It's a plain text file that has instructions like "install this package, copy these files, run this command." Podman reads these instructions and executes them step by step to create your final image.

Podman files work almost exactly like Dockerfiles with the same syntax, the same commands, and the same logic. Podman automatically looks for a file named "Containerfile" first, then falls back to "Dockerfile" if that's all you have. This means your existing Docker experience won't go to waste because it shares a lot of compatibility with Podman.

Podman files are very handy for automation. Instead of manually configuring containers every time, you only need to write the instructions once. Then you can build identical images across development, testing, and production environments way more easily.

The real difference between Docker and Podman is how Podman executes these instructions in the Podman file. Podman runs rootless by default, which means better security. It also doesn't need a background daemon, so your system resources stay cleaner and you avoid the single point of failure that daemon-based systems can stumble on.

How to Set Up Your Environment

But before you can create a Podman file, you need Podman installed and working on your system. The installation process depends on your operating system, but most modern Linux distributions include Podman in their package repositories, so it isn’t hard to do.

Installing Podman

On Red Hat-based systems like RHEL, CentOS, or Fedora, install Podman with your package manager:

For RHEL/CentOS/AlmaLinux

sudo dnf install podman

For Ubuntu/Debian

sudo apt update && sudo apt install podman

Verifying Your Installation

Once you’ve finished installing, you should verify that everything works by checking the version and pulling a test image:

Check Podman version

podman --version

Test by pulling a small image

podman pull alpine:latest

List images to confirm it worked ok

podman images

If these commands run without errors, then you're ready to start building. The Alpine image is small and downloads quickly, making it perfect for testing your setup.

Required Tools for Development

You'll need a text editor to create your Podman files. Any editor works, but having syntax highlighting for Dockerfile format makes life a lot easier. VS Code, vim, nano, or even Notepad will do in a pinch. It is good to get into the habit of keeping your files simple and easy to read.

Next, you’ll need terminal access because you'll be building and testing images from the command line. Podman works well with most shells, so use whatever you're comfortable with or what you have available should be fine.

What is the Anatomy of a Podman File?

Every Podman file uses the same basic building blocks. These are instructions that tell Podman what base image to start with, then what software to install, which files to include, and how to run the finished container.

Essential Directives in a Podman File

FROM sets your starting point. Every Podman file begins with a FROM instruction that specifies the base image:

FROM ubuntu:22.04

This tells Podman to start with Ubuntu 22.04 as your foundation. You can use any image from container registries like Docker Hub, Quay.io, or your own private registry, if you have one.

RUN executes the commands during the build process. Use RUN to install packages, create directories, or configure your environment:

RUN apt-get update && apt-get install -y nginx

Each RUN instruction creates a new layer in your image. Combining commands with && keeps the layer count down and makes your builds faster.

COPY adds files from your local system into the container image:

COPY ./app /usr/src/app

This copies everything in your local ./app directory to /usr/src/app inside the container. File permissions and ownership carry over, so watch out for permission issues if you find that things are not running properly.

CMD and ENTRYPOINT define what happens when someone runs your container. CMD provides default arguments that can be overridden like:

CMD ["nginx", "-g", "daemon off;"]

ENTRYPOINT creates a container that runs like a specific command. The choice between them depends on how flexible you want your container to be.

Advanced Instructions

WORKDIR sets the working directory for future instructions when the container is running. It's like running cd (change directory) in your shell:

WORKDIR /usr/src/app

ENV creates environment variables that are available in the running container:

ENV NODE_ENV=production

EXPOSE takes note of which ports your application uses. It doesn't actually publish ports - that only happens when you run the container:

EXPOSE 80 443

Step-by-Step Guide to Creating a Podman File

Let's build a real Podman file that creates a web server image. This example shows you how to make one from the base image selection to final testing.

Step 1: Define the Base Image

Start with a base image that matches what you need for your application to run. For a Python web app, you’ll use a Python image. For a simple web server, Alpine Linux works great:

FROM alpine:latest

Alpine images are tiny and secure, so they’re perfect for production deployments where resources are expensive. They include just enough Linux to run your application without extra bloat, giving your application more headroom to run properly.

Choosing the right base image affects several key areas, including security level, container size, and compatibility with other systems. The official images that come from Docker Hub usually get regular security updates and tend to follow best practices. If you are looking at production deployments, then you should avoid random user-created images unless you know exactly what they do.

Step 2: Add Layers with Commands

Next, you’ll want to install your application's dependencies by using RUN instructions. Like we mentioned earlier, you can group related commands together to minimize layers in your image:

RUN apk update && \
    apk add --no-cache nginx && \
    mkdir -p /var/www/html

The backslash lets you split long commands across multiple lines for better readability. (It may not seem important now, but if you come back to your file after a few months, you’ll be glad you kept things tidy and easy to read.) The --no-cache flag tells Alpine's package manager not to store downloaded packages, keeping your image smaller.

Best practice is to clean up package caches and temporary files in the same RUN instruction where you create them. This stops these files from adding to your final image size.

Step 3: Include Application Files

The next step is to copy your application code and configuration files into the image:

COPY ./html /var/www/html
COPY ./nginx.conf /etc/nginx/nginx.conf

The first path is relative to where your build is (the directory where you run podman build). The second path is the destination inside the container. Make sure your local files exist before you start your build, or Podman will throw an error. (It happens to the best of us.)

File permissions can be tricky when copying files. If your application needs specific ownership or permissions, use the RUN commands to set them after copying:

COPY ./app /usr/src/app
RUN chown -R nginx:nginx /usr/src/app

Step 4: Set the Default Command

Next, you’ll want to configure what happens when someone runs your container. For a web server, you want nginx to start automatically:

CMD ["nginx", "-g", "daemon off;"]

The "daemon off" flag keeps nginx running in the foreground. Containers need their main process to stay running, or they'll exit immediately.

Step 5: Build and Test Your Podman File

Save your instructions in a file named "Containerfile" and then build your image:

podman build -t my-web-server .

The -t flag tags your image with a name you'll remember. The dot at the end tells Podman to use the current directory as the build context that it will reference for copying over files.

Finally, you can test your new image by running it:

podman run -d -p 8080:80 my-web-server

This starts your container in the background (-d) and maps port 8080 on your host to port 80 in the container. Open a browser to http://localhost:8080 to see if it works.

Best Practices for Creating Podman Files

Writing Podman files takes a little practice, but if you follow set patterns, it will save you time, and you’ll create better images in the long run. Here are some basics on these patterns. They’ll help you steer clear of common mistakes, and you’ll be able to build images that work consistently.

Keep Layers Minimal and Efficient

Every instruction in your Podman file creates a new layer. More layers mean larger images and slower builds. You can combine related commands into a single RUN instruction:

Instead of this:

RUN apt-get update
RUN apt-get install -y python3
RUN apt-get install -y pip

Do this:

RUN apt-get update && \
    apt-get install -y python3 pip && \
    rm -rf /var/lib/apt/lists/*

The last line removes package cache files afterwards, which stops them from bloating your final image. This cleanup must happen in the same RUN instruction where you download packages, or else those files will stick around and become part of your build.

Use .containerignore to Control Build Context

Create a .containerignore file (or .dockerignore for compatibility) to exclude files from your build context that you don’t want added. This speeds up builds and stops unwanted files from accidentally getting copied over:

# .containerignore
.git
node_modules
*.log
.env

Large directories like node_modules or .git can make builds painfully slow. Excluding them also prevents your secret environment files, such as passwords and tokens, from being included in your image.

Optimize for Caching

Podman caches each layer during builds. If a layer hasn't changed, Podman reuses the cached version instead of rebuilding to speed things up. Order your instructions to take advantage of this:

Copy dependencies first (changes less often)

COPY package.json /app/
RUN npm install

Copy application code last (changes more often)

COPY . /app/

This kind of pattern makes sure that dependency installation only runs when the package.json file changes, not every time you make changes to your app’s code. This is good because then the only thing that needs to actually copy over will be changed in your code. You won't have to wait for everything to download and build every time, which makes your builds faster and keeps your file sizes down.

Use Specific Image Tags

You should always specify the exact versions for your base images instead of using "latest":

Instead of this:

FROM node:latest

Do this:

FROM node:18.17-alpine

The version that the "latest" tag references changes over time as the versions are updated, which means your builds can start acting a little unpredictably. Specific tags help ensure that your images build consistently months later because you are staying on a set version number.

How to Troubleshoot and Debug

Building container images involves many moving parts, and things don't always work on the first try. Knowing how to debug build failures and runtime issues saves hours of frustration.

Common Build Errors and Fixes

Package installation failures usually happen because package repositories are outdated. Always update package lists before installing.

This might fail:

RUN apt-get install -y python3

This works better:

RUN apt-get update && apt-get install -y python3

File not found errors during COPY operations mean your source files don't exist or you're specifying the wrong path. Double-check your directory structure and make sure you're running podman build from the right location, and then try again.

Permission denied errors usually happen when your application tries to write to directories it doesn't own. You can use RUN instructions to fix ownership issues after copying files.

Debugging with Verbose Output

When builds fail mysteriously, use Podman's debug output to see exactly what's happening:

podman build --log-level debug -t my-app .

This shows every command Podman runs and any error messages that might be getting lost along the way. The output can be really dense, but it usually points you toward the real problem if you dig into it.

You can also build images step by step by commenting out later instructions and building each part one at a time. If you're unsure why your build is failing, this tool helps you isolate the instruction causing problems because it errors out during a specific step.

Checking Container Runtime Issues

If your image builds successfully but the container doesn't work properly, check the logs:

See what your container is doing:

podman logs <container-name>

Follow logs in real-time:

podman logs -f <container-name>

Some of the runtime issues that you’re more likely to come across will be things like apps trying to bind to ports that are already being used, missing config files, or processes that exit as soon as they try to start. The logs will usually tell you exactly what went wrong, so be prepared to wade through the text that they produce.

Interactive debugging is really useful, so if you want to, you can run your container with a shell instead of the default command:

podman run -it my-app /bin/sh

This drops you into a shell inside the container where you can poke around and test things manually.

Conclusion

Learning how to create a Podman file changes how you build and deploy applications. Instead of endlessly configuring containers every time you want to deploy an update, you just type out the instructions once. The great thing about this approach is that your builds will be consistent across all your environments. Automation like this finally gets rid of configuration differences and the "well it works on my machine" problems that we come across in dev work.

It might not seem like much, but the skills you've learned here are the start of even more advanced container workflows. Red Hat Certified Specialist in Containers (EX188) Online Training builds on these fundamentals and shows you how to manage containers at enterprise scale.

Start small with simple apps and get the basics right, and you’ll gradually work up to more complex builds. Every Podman file you create teaches you something new about containerization and helps you spot patterns that will make your future projects seem easier.

Want to try a CBT Nuggets course? Get a free 7-day trial.


DownloadUltimate DevOps Cert Guide

By submitting this form you agree to receive marketing emails from CBT Nuggets and that you have read, understood and are able to consent to our privacy policy.


Don't miss out!Get great content
delivered to your inbox.

By submitting this form you agree to receive marketing emails from CBT Nuggets and that you have read, understood and are able to consent to our privacy policy.

Get CBT Nuggets IT training news and resources

I have read and understood the privacy policy and am able to consent to it.

© 2025 CBT Nuggets. All rights reserved.Terms | Privacy Policy | Accessibility | Sitemap | 2850 Crescent Avenue, Eugene, OR 97408 | 541-284-5522