Skip to content

Instantly share code, notes, and snippets.

@jesperronn
Last active February 4, 2026 08:12
Show Gist options
  • Select an option

  • Save jesperronn/6612a7604cb3a76bf696fc1338aa1161 to your computer and use it in GitHub Desktop.

Select an option

Save jesperronn/6612a7604cb3a76bf696fc1338aa1161 to your computer and use it in GitHub Desktop.
Guide for running Docker Compose on Rootless Podman -- February 2026 edition

The Ultimate Guide: Rootless Podman & Docker Compose on macOS

Knowledge Cut-Off: February 2024
Last Updated: February 2026


Table of Contents

  1. Introduction
  2. System-Level Setup & Persistence
  3. Permissions & Identity Mapping (The "keep-id" Interaction)
  4. Security Trade-offs (SELinux)
  5. Universal Compose Strategy (Base vs. Template)
  6. Networking & DNS Nuances
  7. Troubleshooting

1. Introduction

Running Docker Compose via Rootless Podman on macOS involves a nested architecture: your macOS host runs a Fedora-based Linux VM (the Podman Machine), which executes containers within a user namespace. This guide provides a production-grade workflow that ensures Podman functionality while maintaining Docker compatibility for your team.


2. System-Level Setup & Persistence

A. The Socket Bridge

Most Compose tools look for /var/run/docker.sock. Use the built-in helper to symlink the macOS system path to your user-level Podman machine socket:

sudo podman-mac-helper install

B. Persistent Privileged Ports (80/443)

By default, the Podman VM blocks non-root users from binding to ports below 1024. To make this change survive both VM restarts and machine stops, write the configuration to the VM's persistent sysctl directory:

podman machine ssh "sudo bash -c 'echo \"net.ipv4.ip_unprivileged_port_start=80\" > /etc/sysctl.d/99-podman.conf' && sudo sysctl -p /etc/sysctl.d/99-podman.conf"

3. Permissions & Identity Mapping

The "keep-id" vs "user: 0:0" Interaction

This combination is the standard for rootless success:

  • userns_mode: "keep-id": Maps your Mac UID (e.g., 501) to that same UID inside the container.
  • user: "0:0": Forces the process to run as "root" inside the container namespace.
  • The Result: The process has internal root privileges (to bind ports or modify internal config) but writes files to your Mac as your actual user (UID 501).

4. Security Trade-offs (SELinux)

The "label=disable" Flag

  • Why: Required for Traefik to write to the socket in rootless mode.
  • Impact: Disables SELinux Mandatory Access Control for that specific container.
  • Alternative: Use a custom SELinux policy if you require high-security isolation, though this is significantly more complex to maintain across Podman VM updates.

5. Universal Compose Strategy

Keep your primary configuration clean. Use an override file for Podman-specific "breaking" changes.

docker-compose.yml (Base - Universal)

services:
  traefik:
    image: traefik:v3.0
    ports:
      - "80:80"
      - "443:443"
    cap_add:
      - NET_BIND_SERVICE
    dns:
      - 8.8.8.8
      - 1.1.1.1
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data:/data:Z

docker-compose-override-podman-template.yml

# =========================================================================
# PODMAN ROOTLESS OVERRIDE TEMPLATE
# INSTRUCTIONS: Rename this file to 'docker-compose.override.yml' to 
# activate Podman-specific settings. Ensure 'docker-compose.override.yml' 
# is added to your .gitignore to avoid breaking Docker-based environments.
# =========================================================================

services:
  traefik:
    userns_mode: "keep-id"
    security_opt:
      - "label=disable"
    user: "0:0"

6. Networking & DNS

  • Internal Resolution: Use the service name defined in Compose.
  • Host Access: To reach services running natively on your Mac (e.g., a local DB), use the address host.containers.internal.
  • DNS Configuration: Podman networking sometimes fails to inherit Mac DNS settings. Always define dns at the service level in the base file if resolution fails.

7. Troubleshooting

Permission Issues with Mounted Volumes

If you encounter "Permission Denied" on a folder (common when NOT using keep-id), run this from your macOS terminal to align host UIDs with the Podman user namespace:

podman unshare chown -R $(id -u):$(id -g) ./data

Verification Checklist

  1. ls -l /var/run/docker.sock points to your user's socket path.
  2. podman machine inspect confirms the machine is "running".
  3. Your .gitignore contains docker-compose.override.yml.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment