Running your first container with Podman
CoreOS ships Podman, not Docker, as its default container runtime. Here's how to pull and run your first container, and how to make it survive a reboot with Quadlet.
14 February 2025 3 min read
CoreOS’s whole reason for existing is to run containers well with minimal host maintenance. The runtime it ships for that job is Podman, not Docker. If you’ve used Docker before, most of the concepts carry across directly – but there are a couple of real differences worth understanding before you start.
Checking Podman is there
Podman is included on CoreOS out of the box – there’s nothing to install. SSH in using the key you set up in your Ignition config and confirm it’s present:
podman --version
Pulling and running a simple container
Pull an image and run it much as you would with Docker:
podman pull docker.io/library/nginx:latest
podman run -d --name web -p 8080:80 docker.io/library/nginx:latest
Check it’s running and reachable:
podman ps
curl http://localhost:8080
Note the fully qualified image name – docker.io/library/nginx rather than just nginx. Podman doesn’t assume Docker Hub as an implicit default registry the way Docker does, so being explicit avoids ambiguity, especially once you’ve configured other registries.
Why Podman is architecturally different from Docker
This isn’t just a rebrand of the same tool. Docker relies on a long-running background daemon (dockerd) running as root, which every container command talks to. Podman has no daemon. Each podman run command launches the container as a direct child process of the command that started it, using the same OCI container standards under the hood.
Two practical consequences follow from that:
- There’s no single daemon process that, if it crashes, takes every container’s management interface down with it
- Podman supports genuinely rootless containers – running as an unprivileged user, with no daemon requiring root – which is a meaningfully smaller attack surface than Docker’s traditional root daemon model
Because there’s no daemon watching your containers, a container Podman started directly on the command line does not come back on its own after a reboot. That’s where systemd integration comes in.
Making it survive a reboot: Quadlet
The current recommended way to run a Podman container as a proper systemd-managed service on Fedora CoreOS is Quadlet. Rather than hand-writing a systemd unit that shells out to podman run, you write a small declarative .container file, and systemd generates the actual service unit from it automatically at boot.
Create the file at /etc/containers/systemd/web.container:
[Unit]
Description=Nginx web container
[Container]
Image=docker.io/library/nginx:latest
PublishPort=8080:80
[Install]
WantedBy=multi-user.target
Then reload systemd and start it as a normal unit – note the .service suffix Quadlet appends to the container name:
sudo systemctl daemon-reload
sudo systemctl start web.service
sudo systemctl status web.service
Because it’s a real systemd unit with WantedBy=multi-user.target, it starts automatically on every boot from here on – including after CoreOS’s own automatic OS updates and reboots, which we cover in the next post. You get systemd’s usual tools for free too: journalctl -u web.service for logs, and standard restart/dependency handling if the container exits.
For a config you’re provisioning from scratch, it’s worth writing the Quadlet file directly into your Ignition config as one of the files it drops onto the filesystem at first boot, rather than creating it by hand after SSHing in – that keeps your whole setup, container included, reproducible from one source file.