Build on Podman

What is Podman?

To quote from the official documentation:

Podman is a daemonless, open source, Linux native tool designed to make it easy to find, run, build, share and deploy applications using Open Containers Initiative (OCI) Containers and Container Images.

It can be used as a standalone daemonless CLI with sub-commands and flags almost identical the standard docker CLI. You can even alias docker=podman and everything should work as expected.

Beside running as a standalone daemonless CLI, podman can also serve as a docker API daemon using podman system service sub-command. You just need to set the DOCKER_HOST environment and most applications will pick it up (pack is one of them).

While podman is native to Linux you still can enjoy it on macOS using virtual machine. There is sub-command podman machine facilitating VM creation making it really easy.

Setup

Minimal required versions:


Install

sudo dnf -y install podman

Service

Expose the service using systemd:

systemctl enable --user podman.socket
systemctl start --user podman.socket

Connection

export DOCKER_HOST="unix://$(podman info -f "{{.Host.RemoteSocket.Path}}")"

Tip: put the command into your shell init file (e.g ~/.bashrc).

Install

WARNING: These commands will UPGRADE existing packages.

. /etc/os-release
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
curl -L "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key" | sudo apt-key add -
sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get -y install podman

Service

Expose the service using systemd:

systemctl enable --user podman.socket
systemctl start --user podman.socket

Connection

export DOCKER_HOST="unix://$(podman info -f "{{.Host.RemoteSocket.Path}}")"

Tip: put the command into your shell init file (e.g ~/.bashrc).

Install

brew install podman

Virtual Machine

Init
podman machine init --cpus=2 --disk-size=30 --memory=8192

Where:

  • --cpus is the number of CPUs we’ll allocate to the VM.
  • --disk-size is the amount of disk space we’ll give the VM. (GBs)
  • --memory is the amount of memory we’ll allocate to the VM. (MBs)
Start
podman machine start

Connection

  1. Add the SSH key for the podman VM to your keychain:
    ssh-add -k "$HOME/.ssh/podman-machine-default"
    
  2. Change default connection to use root:
    podman system connection default podman-machine-default-root
    

    Note: root connection prevents needing to pass --docker-host=inherit on every pack build.
    For more information, see issue buildpacks/pack#1338.

  3. Configure DOCKER_HOST with the connection information:
    export DOCKER_HOST="$(podman system connection ls --format="{{.URI}}" | grep root)"
    

    Tip: put the commands into your shell init file (e.g ~/.zshrc).

Usage

Build

Source

git clone https://github.com/buildpacks/samples

pack build

pack build sample-app -p samples/apps/ruby-bundler/ -B cnbs/sample-builder:jammy

Where:

  • sample-app is the image name of the image to be created.
  • -p is the path to the application source.
  • -B is the builder to use.

NOTE: If using a socket connection, for example on Linux, you’ll need to pass an additional flag in order to provide the proper socket location to the lifecycle: --docker-host=inherit

In the future, this may be automatically detected.

Results

podman images

Known Issues & Limitations

  • On macOS bind mounts do not work since the VM cannot access host file system.

  • With more time consuming builds and --trust-builder=true following error may occur:

    ERROR: failed to image: error during connect: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.40/info": EOF
    

    There is a workaround for this, increase timeout of podman service:

    cat <<EOF > /etc/systemd/user/podman.service
    [Unit]
    Description=Podman API Service
    Requires=podman.socket
    After=podman.socket
    Documentation=man:podman-system-service(1)
    StartLimitIntervalSec=0
    
    [Service]
    Type=exec
    KillMode=process
    Environment=LOGGING="--log-level=info"
    ExecStart=/usr/bin/podman $LOGGING system service --time=1800
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    systemctl --user daemon-reload
    systemctl restart --user podman.socket
    

    On macOS you need to run this in the VM (use podman machine ssh).