Files
ansible-podman/README.md
Daniel Akulenok 17fea0e02b podman
2026-01-10 23:21:34 +01:00

369 lines
8.4 KiB
Markdown

# Podman Role
**Bootstrap containerized applications with Podman in minutes.**
## 🚀 Quick Start
### 1. Basic Setup
```yaml
- hosts: servers
roles:
- podman
```
### 2. Run Your First Container
```yaml
- hosts: servers
roles:
- role: podman
vars:
podman_containers:
- name: nginx
image: nginx:latest
ports:
- "80:80"
```
### 3. Common Patterns
**Web application with database:**
```yaml
podman_containers:
- name: webapp
image: myapp:latest
ports:
- "8080:8080"
env:
DATABASE_URL: "postgresql://postgres@db:5432/app"
- name: database
image: postgres:15
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)
---
## 🔧 Configuration Guide
### Management Modes (Quadlet vs Systemd)
This role automatically selects the best management engine based on your operating system version:
- **Quadlet** (Default for Debian 13+): Uses Podman's native systemd generator via `.container` files. This is the modern, preferred method.
- **Systemd** (Default for Debian < 13): Uses legacy `podman generate systemd` to create service units.
The determination is controlled by the logic in `defaults/main.yml`:
```yaml
# Auto-detected. True for Debian 13+, False otherwise.
podman_use_quadlet: "{{ ... }}"
# Sets default state to 'quadlet' or 'started'/'present' accordingly
podman_mode: ...
```
**Recommendation:** Do **not** set `state` explicitly in your variables (e.g., `podman_containers`) unless you have a specific reason. The role's defaults will ensure the correct state is applied for your OS version.
Users can still manually control defaults if needed:
```yaml
# Force Quadlet usage on older systems (if supported)
podman_use_quadlet: true
# Or customize default options
podman_container_defaults:
quadlet_options:
- "AutoUpdate=registry"
- |
[Install]
WantedBy=default.target
```
If you prefer the standard imperative approach (similar to `docker run`) regardless of OS, you can override the defaults or set `state: started` on individual items.
### Resource Definition
The variables `podman_containers`, `podman_networks`, `podman_volumes`, and `podman_pods` accept standard parameters from the [containers.podman](https://docs.ansible.com/ansible/latest/collections/containers/podman/index.html) collection.
#### Containers
```yaml
podman_containers:
- name: nginx
image: nginx:latest
ports: ["80:80"]
volumes:
- "html_vol:/usr/share/nginx/html"
- "./local_conf:/etc/nginx/conf.d:ro"
env:
NGINX_HOST: example.com
# Quadlet-specific options can be added as a list
quadlet_options:
- "AutoUpdate=registry"
```
#### Networks
```yaml
podman_networks:
- name: app_net
subnet: "10.0.0.0/24"
gateway: "10.0.0.1"
dns: ["8.8.8.8"]
```
#### Volumes
```yaml
# Toggle automatic creation of host directories for bind mounts
podman_create_volumes: true
podman_volumes:
- name: db_data
# state defaults to 'quadlet'
```
#### Pods
```yaml
podman_pods:
- name: app_pod
ports: ["8080:80"]
share: "net,ipc"
```
### Advanced Configuration
#### Registry & Security Policy
```yaml
# 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
```yaml
# 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
```yaml
# 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
```yaml
podman_configure_storage: true
podman_storage_driver: overlay
podman_storage_graphroot: /var/lib/containers/storage
podman_storage_runroot: /run/containers/storage
```
#### API & Socket Services
```yaml
podman_enable_socket: true # Enable Podman socket
podman_enable_api_service: true # Enable REST API
```
---
## 🏷️ Available Tags
Run specific parts of the role:
```bash
# 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
```yaml
- 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
ports:
- "8080:80"
volumes:
- "./web:/usr/share/nginx/html"
```
### Production Environment
```yaml
- 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
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
```yaml
- 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
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
networks:
- app-network
volumes:
- "redis-data:/data"
# Application
- name: app
image: myapp:latest
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>