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.
- https://www.redhat.com/en/topics/containers/what-is-podman
- https://docs.podman.io/en/v5.2.4/Introduction.html
- QUICK & EASY START HERE -> podman.io get started
- Podman Tutorial Zero to Hero | Full 1 Hour Course
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
- https://docs.podman.io/en/latest/markdown/podman-machine-init.1.html
- https://docs.podman.io/en/latest/markdown/podman-machine-start.1.html
If for any reason you want to nuke it and start again:
podman machine stop
podman machine rm
podman machine init
podman machine start
- https://docs.podman.io/en/latest/markdown/podman-machine-stop.1.html
- https://docs.podman.io/en/latest/markdown/podman-machine-rm.1.html
You can find out more information about your set up by running info and version
podman info
podman version
Tell it what registries you prefer it to search
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:
- stars (int - number of stars the image has)
- is-automated (boolean - true | false) - is the image automated or not
- is-official (boolean - true | false) - is the image official or not
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.