Podman: How do I get and edit an image on MacOS?

This article is part of a series.

This may all be obsolete when using MacOS 26 because of the containers announced at WWDC25, but there is an open source version of docker called podman that complies with the same Open Container Initiative specs as the Apple containers.

Why use podman now when I’ve avoided containers like the plague? I was looking to deploy a swift server and came across the swift container plugin thanks to the Hummingbird folks, and was interested in seeing how it worked. What could it make easier about sharing swift server examples?

The plugin requires a registry, which I made on Digital Ocean (affiliate link, why not), but I had troubles with it (the DO error code left something to be desired) and needed to explore containers in general to do a bit more to troubleshooting. Including figure out how to run a registry locally on my own computer.

And because Docker irritated. me. so. much. the last time I used it, enter Podman.

Podman “is an open source Open Container Initiative (OCI)-compliant container management tool from Red Hat used for handling containers, images, volumes, and pods” (https://en.wikipedia.org/wiki/Podman)

Some tutorials are difficult to follow because they try to leverage a knowledge of Docker, and everything I learned about Docker a few years a go I’ve tried to actively forget. But these resources provided a nice base.

Install Podman

There are two options for installing podman on the mac. CLI only (first) and CLI with GUI (second).

I don’t find the GUI that intuitive, so while I do have it installed, I haven’t been using it. The install process may have tweaked some settings around docker and it installed a couple extra tools. I will be keeping a look out for commands that might work differently because I installed it, but nothing I’ve done so far appears to have changed from before and after.

(As a note, one can’t stop the podman server from running if the GUI is open.)

## CLI Only
brew install podman
## install GUI that will also install CLI
brew install --cask podman-desktop

Note: to use docker.io later to retrieve the base project one option is to install it and login that way. I think you could leave it out and choose a different base project, but I was just following along. At least it made ME do that. YMMV.

brew install docker
## will lead you through the steps to create a login and that shell will be able
## to access docker.io just fine at the least. 
docker login 
## it doesn't change .zprofile but it does create a config file. For more info:
# cat ~/.docker/config.json

Afterwards I realized there was a podman login command, but I have yet to try it.

Set up and launch the podman VM

Podman is a linux only tool, so on the Mac podman runs in a linux VM that will need to be created and then ssh’d into to configure.

podman machine init
podman machine start

If for any reason you want to nuke it and start again:

podman machine stop
podman machine rm
podman machine init
podman machine start

You can find out more information about your set up by running info and version

podman info
podman version

Updating the registries.conf file to control what registries podman will search isn’t in the getting started tutorial, but it is in the video.

What the video skips, is that on the mac, in order to update the VM running the podman tool, you’ll need to ssh into it and then follow tutorial instructions.

# https://docs.podman.io/en/latest/markdown/podman-machine-ssh.1.html
podman machine ssh

Once in, add the registries to a config file in the VM user’s directory so you don’t have to change the main one for the whole VM, but on the VM it’s less of a big deal to change the main one than when running directly on a linux box, I would suspect.

Look at the VM’s main file:

cat /etc/containers/registries.conf

Make a local user one if desired (this one matches the video tutorial):

echo -e 'unqualified-search-registries = ["docker.io", "ghrc.io", "quay.io", "registry.fedoraproject.org"]' > $HOME/.config/containers/registries.conf

Get an Existing Container Image

The getting started tutorial picks a really simple http server which is perfect to kick off with.

The tutorial of course starts with showing how to search for it.

# all the things with that name
podman search httpd
# flagged official
podman search httpd --filter=is-official

From the documentation, supported filters are:

Pull the desired container image onto your machine and run it.

podman pull docker.io/library/httpd:latest 
podman run -dt -p 8080:80/tcp docker.io/library/httpd

Run is used for when the container doesn’t exist yet. Some folks add a --rm to the command so a container being created that one doesn’t intend to edit will get zotted when it’s wound down. --rmi will delete the image!

This example command uses -d for detached. That will let the process run in the background. The -t also adds a pseudo-tty to run arbitrary commands in an interactive shell.

The string of numbers you’ll see after executing is the full ID string of the container that has been made from the image.

If you forget that string you can get it again by running ps which shows the running containers. The shortened string works just as well as an id later.

# currently running
podman ps
# even ones that have been stopped.
podman ps -a

To end a specific process use stop using that ID number. If you didn’t add -rm, it can be restarted with start.

podman stop {$CONTAINER_ID}
podman start {$CONTAINER_ID}

With this image up and running you should be able to hit the demo web page:

curl http://localhost:8080
#<html><body><h1>Still works!</h1></body></html>

Make changes to it…

Let’s say you wanted to change that web page. With the container still running, launch its bash with exec -i -t, where -i is interactive and -t is that tty again. Don’t forget to add the tool you want to launch at the end!

podman exec -it {$CONTAINER_ID} bash

Once in the interactive shell one can change the web page.

ls -al
echo '<html><body><h1>Still works!</h1></body></html>' > htdocs/index.html

In a different Terminal, try the curl again. It should reflect the new page.

curl http://localhost:8080
# <html><body><h1>Still works!</h1></body></html>

Stop, start and curl again… The changes are preserved!

Make a new image from an existing container

Let’s say you want to make a new image from this changed container. That’s what the commit command is for.

## see containers
podman ps -a
## see images
podman images 
## will provide default info (best for shared environments)
# podman commit {$CONTAINER_ID} 
podman commit {$CONTAINER_ID} {$SOME_HUMAN_READABLE_LABEL_FOR_NEW}
## look for new image
podman images 

I chose “my-httpd-template” for my new localhost/my-httpd-template now lives in my list of images, and I can make new containers from it instead of the one from the registry.

podman run -dt -p 8080:80/tcp localhost/my-httpd-template
## see it running
podman ps

Until next post

This is a handy place to stop this section of notes because we now have a our own new copy of an image that we made changes to, and can make changes to.

The next set of notes all covers how to share an image once you have it, i.e. various ways of copying it out of the VM, pushing it to a remote registry, pushing it to a local registry, etc.

This article is part of a series.