Daniel Akulenok 1fb1c85b5d podman
2025-09-12 12:44:58 +02:00
2025-09-09 12:35:00 +02:00
2025-09-12 12:44:58 +02:00
2025-09-09 12:35:00 +02:00
2025-09-05 22:49:16 +02:00
2025-09-12 12:44:58 +02:00
2025-09-12 12:44:58 +02:00
2025-09-05 22:49:16 +02:00
2025-09-12 11:12:57 +02:00

Podman Role

Bootstrap containerized applications with Podman in minutes.

🚀 Quick Start

1. Basic Setup

- hosts: servers
  roles:
    - podman

2. Run Your First Container

- hosts: servers
  roles:
    - role: podman
      vars:
        podman_containers:
          - name: nginx
            image: nginx:latest
            state: started
            ports:
              - "80:80"

3. Common Patterns

Web application with database:

podman_containers:
  - name: webapp
    image: myapp:latest
    state: started
    ports:
      - "8080:8080"
    env:
      DATABASE_URL: "postgresql://postgres@db:5432/app"
    
  - name: database
    image: postgres:15
    state: started
    volumes:
      - "db-data:/var/lib/postgresql/data"
    env:
      POSTGRES_DB: app
      POSTGRES_PASSWORD: secret

podman_volumes:
  - name: db-data

That's it! Podman will be installed, configured, and your containers will be running with systemd services automatically created.


📋 Requirements

  • Ansible: 2.11+
  • Target OS: Ubuntu 20.04+, Debian 11+
  • Collection: containers.podman (auto-installed)

🔧 Complete Feature Reference

Container Management

podman_containers:
  - name: my-app
    image: nginx:latest
    state: started           # started|stopped|present|absent
    ports:
      - "8080:80"
      - "443:443"
    volumes:
      - "/host/path:/container/path"
      - "volume-name:/data"
    env:
      ENV_VAR: value
    networks:
      - app-network
    restart_policy: always   # no|always|on-failure|unless-stopped
    user: "1000:1000"
    labels:
      app: web
      environment: prod
    memory: "1g"
    cpu_shares: 1024
    device:
      - "/dev/sda:/dev/xvda:rwm"
    security_opt:
      - "seccomp=unconfined"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
    # Systemd service generation (optional)
    generate_systemd:
      path: "/etc/systemd/system"
      restart_policy: always
      after: ["network.target"]
      wants: ["network-online.target"]

Network Management

podman_networks:
  - name: app-network
    state: present
    driver: bridge           # bridge|macvlan|ipvlan
    subnet: "172.20.0.0/16"
    gateway: "172.20.0.1"
    internal: false          # true for isolated networks
    dns:
      - "8.8.8.8"
      - "1.1.1.1"
    options:
      mtu: 1500
      vlan: 100
    
  # Advanced networking
  - name: macvlan-net
    driver: macvlan
    macvlan: "eth0"          # Parent interface
    subnet: "192.168.1.0/24"
    
  - name: ipv6-net
    driver: bridge
    subnet: "fd00::/64"
    ipv6: true

Volume Management

podman_volumes:
  - name: app-data
    state: present
    driver: local            # local|tmpfs
    labels:
      backup: daily
      environment: prod
    options:
      - "device=/dev/sdb1"
      - "type=ext4"
      - "o=rw"
      
  - name: tmpfs-volume
    driver: tmpfs
    options:
      - "tmpfs-size=100m"
      - "tmpfs-mode=1777"

Pod Management

podman_pods:
  - name: webapp-pod
    state: started
    ports:
      - "8080:80"
    networks:
      - frontend
    hostname: webapp
    dns:
      - "8.8.8.8"
    labels:
      app: webapp
    volumes:
      - "webapp-data:/data"
    memory: "2g"
    cpu_shares: 1024
    share: "net,ipc"         # Shared namespaces
    infra: true              # Use infra container
    infra_image: "registry.k8s.io/pause:3.9"

Advanced Configuration

Registry & Security Policy

# Basic registry setup (development)
podman_policy_default_type: "insecureAcceptAnything"
podman_policy_reject_unknown_registries: false

# Production security (with signatures)
podman_policy_default_type: "reject"
podman_policy_reject_unknown_registries: true
podman_policy_trusted_registries:
  - registry: "docker.io"
    type: "insecureAcceptAnything"
    unqualified_search: true
    
  - registry: "internal.company.com"
    type: "signedBy"
    keyPath: "/etc/pki/containers/company.gpg"
    insecure: false
    mirror:
      - location: "backup.company.com"

Systemd Service Generation

# Global systemd settings
podman_generate_systemd: true
podman_systemd_options:
  restart_policy: always
  stop_timeout: 120
  after: ["network.target"]
  wants: ["network-online.target"]
  container_prefix: "container-"
  pod_prefix: "pod-"

Resource Cleanup

# Auto-cleanup unused resources
podman_prune_enabled: true
podman_prune_options:
  container: true    # Remove stopped containers
  image: true        # Remove unused images
  network: true      # Remove unused networks
  volume: true       # Remove unused volumes
  system: true       # Full system cleanup

Storage Configuration

podman_configure_storage: true
podman_storage_driver: overlay
podman_storage_graphroot: /var/lib/containers/storage
podman_storage_runroot: /run/containers/storage

API & Socket Services

podman_enable_socket: true      # Enable Podman socket
podman_enable_api_service: true # Enable REST API

🏷️ Available Tags

Run specific parts of the role:

# Install only
ansible-playbook -t podman-install playbook.yml

# Configure only  
ansible-playbook -t podman-configure playbook.yml

# Manage containers only
ansible-playbook -t podman-containers playbook.yml

# Manage networks only
ansible-playbook -t podman-networks playbook.yml

Available tags:

  • podman - Run everything
  • podman-install - Package installation
  • podman-configure - Configuration files
  • podman-services - System services
  • podman-networks - Network management
  • podman-volumes - Volume management
  • podman-pods - Pod management
  • podman-containers - Container management
  • podman-systemd - Systemd service generation
  • podman-prune - Resource cleanup

📚 Example Playbooks

Development Environment

- hosts: dev-servers
  roles:
    - role: podman
      vars:
        # Permissive for development
        podman_policy_default_type: "insecureAcceptAnything"
        podman_enable_socket: true
        
        podman_containers:
          - name: dev-web
            image: nginx:latest
            state: started
            ports:
              - "8080:80"
            volumes:
              - "./web:/usr/share/nginx/html"

Production Environment

- hosts: prod-servers
  roles:
    - role: podman
      vars:
        # Strict security for production
        podman_policy_default_type: "reject"
        podman_policy_reject_unknown_registries: true
        podman_policy_trusted_registries:
          - registry: "registry.company.com"
            type: "signedBy"
            keyPath: "/etc/pki/containers/prod.gpg"
            
        podman_containers:
          - name: prod-app
            image: registry.company.com/app:v1.2.3
            state: started
            restart_policy: always
            memory: "2g"
            cpu_shares: 2048
            healthcheck:
              test: ["CMD", "curl", "-f", "http://localhost/health"]
              interval: 30s
              timeout: 10s
              retries: 3

Multi-Service Application

- hosts: app-servers
  roles:
    - role: podman
      vars:
        podman_networks:
          - name: app-network
            subnet: "172.20.0.0/16"
            
        podman_volumes:
          - name: postgres-data
          - name: redis-data
          - name: app-uploads
            
        podman_containers:
          # Database
          - name: postgres
            image: postgres:15
            state: started
            networks:
              - app-network
            volumes:
              - "postgres-data:/var/lib/postgresql/data"
            env:
              POSTGRES_DB: myapp
              POSTGRES_PASSWORD: "{{ vault_db_password }}"
              
          # Cache
          - name: redis
            image: redis:7-alpine
            state: started
            networks:
              - app-network
            volumes:
              - "redis-data:/data"
              
          # Application
          - name: app
            image: myapp:latest
            state: started
            networks:
              - app-network
            ports:
              - "80:8080"
            volumes:
              - "app-uploads:/app/uploads"
            env:
              DATABASE_URL: "postgresql://postgres:{{ vault_db_password }}@postgres:5432/myapp"
              REDIS_URL: "redis://redis:6379"
            depends_on:
              - postgres
              - redis

📄 License

MIT

👤 Author

Daniel Akulenok podman@valid.dk

Description
No description provided
Readme 85 KiB
Languages
Jinja 100%