mirror of
https://github.com/BagelHole/DevOps-Security-Agent-Skills.git
synced 2026-08-22 12:49:53 +02:00
382 lines
7.6 KiB
Markdown
382 lines
7.6 KiB
Markdown
---
|
|||
|
|
name: podman
|
||
|
|
description: Manage containers using Podman, the daemonless container engine. Run rootless containers, create pods, manage images, and use Docker-compatible commands. Use when working with Podman or requiring rootless container operations.
|
||
|
|
license: MIT
|
||
|
|
metadata:
|
||
|
|
author: devops-skills
|
||
|
|
version: "1.0"
|
||
|
|
---
|
||
|
|
|
||
|
|
# Podman
|
||
|
|
|
||
|
|
Run and manage containers without a daemon using Podman's rootless container engine.
|
||
|
|
|
||
|
|
## When to Use This Skill
|
||
|
|
|
||
|
|
Use this skill when:
|
||
|
|
- Running containers without root privileges
|
||
|
|
- Managing containers on systems without Docker
|
||
|
|
- Creating pod-based container groups
|
||
|
|
- Using systemd for container management
|
||
|
|
- Working in security-conscious environments
|
||
|
|
|
||
|
|
## Prerequisites
|
||
|
|
|
||
|
|
- Podman installed (4.x+)
|
||
|
|
- For rootless: user namespaces enabled
|
||
|
|
- Basic container concepts understanding
|
||
|
|
|
||
|
|
## Key Differences from Docker
|
||
|
|
|
||
|
|
| Feature | Docker | Podman |
|
||
|
|
|---------|--------|--------|
|
||
|
|
| Architecture | Client-daemon | Daemonless |
|
||
|
|
| Root required | Default | Optional (rootless) |
|
||
|
|
| Pod support | No | Yes (Kubernetes-style) |
|
||
|
|
| Systemd integration | Limited | Native |
|
||
|
|
| Socket | docker.sock | podman.sock (optional) |
|
||
|
|
|
||
|
|
## Basic Commands
|
||
|
|
|
||
|
|
### Container Operations
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Run container (identical to Docker)
|
||
|
|
podman run -d --name webserver -p 8080:80 nginx
|
||
|
|
|
||
|
|
# List containers
|
||
|
|
podman ps -a
|
||
|
|
|
||
|
|
# Stop and remove
|
||
|
|
podman stop webserver
|
||
|
|
podman rm webserver
|
||
|
|
|
||
|
|
# Execute command
|
||
|
|
podman exec -it webserver /bin/sh
|
||
|
|
|
||
|
|
# View logs
|
||
|
|
podman logs -f webserver
|
||
|
|
```
|
||
|
|
|
||
|
|
### Image Management
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Pull image
|
||
|
|
podman pull docker.io/library/nginx:latest
|
||
|
|
|
||
|
|
# List images
|
||
|
|
podman images
|
||
|
|
|
||
|
|
# Build image
|
||
|
|
podman build -t myapp:latest .
|
||
|
|
|
||
|
|
# Push to registry
|
||
|
|
podman push myapp:latest registry.example.com/myapp:latest
|
||
|
|
|
||
|
|
# Remove image
|
||
|
|
podman rmi nginx:latest
|
||
|
|
```
|
||
|
|
|
||
|
|
## Rootless Containers
|
||
|
|
|
||
|
|
### Setup
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Check user namespace support
|
||
|
|
cat /proc/sys/user/max_user_namespaces
|
||
|
|
|
||
|
|
# Enable if needed (as root)
|
||
|
|
echo "user.max_user_namespaces=28633" | sudo tee /etc/sysctl.d/userns.conf
|
||
|
|
sudo sysctl -p /etc/sysctl.d/userns.conf
|
||
|
|
|
||
|
|
# Configure subuid/subgid for user
|
||
|
|
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
|
||
|
|
|
||
|
|
# Verify
|
||
|
|
podman unshare cat /proc/self/uid_map
|
||
|
|
```
|
||
|
|
|
||
|
|
### Running Rootless
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Run as regular user (no sudo)
|
||
|
|
podman run -d --name myapp -p 8080:80 nginx
|
||
|
|
|
||
|
|
# Check user namespace mapping
|
||
|
|
podman unshare id
|
||
|
|
|
||
|
|
# Verify non-root
|
||
|
|
podman top myapp user
|
||
|
|
```
|
||
|
|
|
||
|
|
### Port Considerations
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Rootless cannot bind to ports < 1024 by default
|
||
|
|
# Use ports >= 1024
|
||
|
|
podman run -d -p 8080:80 nginx
|
||
|
|
|
||
|
|
# Or enable unprivileged ports (as root)
|
||
|
|
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee /etc/sysctl.d/ports.conf
|
||
|
|
sudo sysctl -p /etc/sysctl.d/ports.conf
|
||
|
|
```
|
||
|
|
|
||
|
|
## Pods
|
||
|
|
|
||
|
|
### Creating Pods
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Create pod
|
||
|
|
podman pod create --name mypod -p 8080:80 -p 5432:5432
|
||
|
|
|
||
|
|
# Add containers to pod
|
||
|
|
podman run -d --pod mypod --name web nginx
|
||
|
|
podman run -d --pod mypod --name db postgres:15
|
||
|
|
|
||
|
|
# List pods
|
||
|
|
podman pod ps
|
||
|
|
|
||
|
|
# Containers share network namespace
|
||
|
|
podman exec web curl localhost:5432
|
||
|
|
```
|
||
|
|
|
||
|
|
### Pod Management
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Start/stop pod (affects all containers)
|
||
|
|
podman pod start mypod
|
||
|
|
podman pod stop mypod
|
||
|
|
|
||
|
|
# Remove pod and containers
|
||
|
|
podman pod rm -f mypod
|
||
|
|
|
||
|
|
# View pod details
|
||
|
|
podman pod inspect mypod
|
||
|
|
|
||
|
|
# Generate Kubernetes YAML from pod
|
||
|
|
podman generate kube mypod > mypod.yaml
|
||
|
|
```
|
||
|
|
|
||
|
|
## Systemd Integration
|
||
|
|
|
||
|
|
### Generate Systemd Unit
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Generate unit file for container
|
||
|
|
podman generate systemd --new --name myapp > ~/.config/systemd/user/container-myapp.service
|
||
|
|
|
||
|
|
# For pod
|
||
|
|
podman generate systemd --new --name mypod --files
|
||
|
|
|
||
|
|
# Reload systemd
|
||
|
|
systemctl --user daemon-reload
|
||
|
|
|
||
|
|
# Enable and start
|
||
|
|
systemctl --user enable --now container-myapp.service
|
||
|
|
```
|
||
|
|
|
||
|
|
### Quadlet (Podman 4.4+)
|
||
|
|
|
||
|
|
```ini
|
||
|
|
# ~/.config/containers/systemd/webapp.container
|
||
|
|
[Container]
|
||
|
|
Image=docker.io/library/nginx:latest
|
||
|
|
PublishPort=8080:80
|
||
|
|
Volume=webapp-data:/usr/share/nginx/html
|
||
|
|
|
||
|
|
[Service]
|
||
|
|
Restart=always
|
||
|
|
|
||
|
|
[Install]
|
||
|
|
WantedBy=default.target
|
||
|
|
```
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Reload to generate service
|
||
|
|
systemctl --user daemon-reload
|
||
|
|
|
||
|
|
# Start the service
|
||
|
|
systemctl --user start webapp
|
||
|
|
```
|
||
|
|
|
||
|
|
## Compose Compatibility
|
||
|
|
|
||
|
|
### Using Podman Compose
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Install podman-compose
|
||
|
|
pip install podman-compose
|
||
|
|
|
||
|
|
# Run compose file
|
||
|
|
podman-compose up -d
|
||
|
|
|
||
|
|
# Or use Docker Compose with Podman socket
|
||
|
|
systemctl --user enable --now podman.socket
|
||
|
|
export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock
|
||
|
|
docker-compose up -d
|
||
|
|
```
|
||
|
|
|
||
|
|
### Native Podman Kube
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Play Kubernetes YAML
|
||
|
|
podman kube play deployment.yaml
|
||
|
|
|
||
|
|
# Stop and remove
|
||
|
|
podman kube down deployment.yaml
|
||
|
|
```
|
||
|
|
|
||
|
|
## Networking
|
||
|
|
|
||
|
|
### Network Management
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Create network
|
||
|
|
podman network create mynetwork
|
||
|
|
|
||
|
|
# Run on network
|
||
|
|
podman run -d --network mynetwork --name app myapp
|
||
|
|
|
||
|
|
# Connect container to network
|
||
|
|
podman network connect mynetwork existing-container
|
||
|
|
|
||
|
|
# List networks
|
||
|
|
podman network ls
|
||
|
|
|
||
|
|
# Inspect network
|
||
|
|
podman network inspect mynetwork
|
||
|
|
```
|
||
|
|
|
||
|
|
### DNS Resolution
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Containers on same network can resolve by name
|
||
|
|
podman run -d --network mynetwork --name db postgres:15
|
||
|
|
podman run -d --network mynetwork --name app \
|
||
|
|
-e DATABASE_HOST=db myapp
|
||
|
|
```
|
||
|
|
|
||
|
|
## Storage
|
||
|
|
|
||
|
|
### Volume Management
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Create volume
|
||
|
|
podman volume create mydata
|
||
|
|
|
||
|
|
# Use volume
|
||
|
|
podman run -d -v mydata:/data myapp
|
||
|
|
|
||
|
|
# List volumes
|
||
|
|
podman volume ls
|
||
|
|
|
||
|
|
# Inspect volume
|
||
|
|
podman volume inspect mydata
|
||
|
|
|
||
|
|
# Rootless volumes location
|
||
|
|
ls ~/.local/share/containers/storage/volumes/
|
||
|
|
```
|
||
|
|
|
||
|
|
### Bind Mounts
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Bind mount with SELinux label
|
||
|
|
podman run -v ./data:/app/data:Z myapp
|
||
|
|
|
||
|
|
# Z = private label (single container)
|
||
|
|
# z = shared label (multiple containers)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Registry Configuration
|
||
|
|
|
||
|
|
### Configure Registries
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Edit registries.conf
|
||
|
|
# ~/.config/containers/registries.conf
|
||
|
|
```
|
||
|
|
|
||
|
|
```toml
|
||
|
|
unqualified-search-registries = ["docker.io", "quay.io"]
|
||
|
|
|
||
|
|
[[registry]]
|
||
|
|
prefix = "docker.io"
|
||
|
|
location = "docker.io"
|
||
|
|
|
||
|
|
[[registry.mirror]]
|
||
|
|
location = "mirror.gcr.io"
|
||
|
|
```
|
||
|
|
|
||
|
|
### Authentication
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Login to registry
|
||
|
|
podman login docker.io
|
||
|
|
|
||
|
|
# Login to private registry
|
||
|
|
podman login registry.example.com
|
||
|
|
|
||
|
|
# Credentials stored in
|
||
|
|
# ~/.config/containers/auth.json
|
||
|
|
```
|
||
|
|
|
||
|
|
## Building Images
|
||
|
|
|
||
|
|
### Buildah Integration
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Podman uses Buildah for builds
|
||
|
|
podman build -t myapp:latest .
|
||
|
|
|
||
|
|
# Build with specific format
|
||
|
|
podman build --format docker -t myapp .
|
||
|
|
|
||
|
|
# Multi-stage build
|
||
|
|
podman build --target production -t myapp:prod .
|
||
|
|
```
|
||
|
|
|
||
|
|
### Buildah Commands
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Create container from scratch
|
||
|
|
buildah from scratch
|
||
|
|
buildah copy working-container ./app /app
|
||
|
|
buildah config --entrypoint '["/app/main"]' working-container
|
||
|
|
buildah commit working-container myapp:minimal
|
||
|
|
```
|
||
|
|
|
||
|
|
## Common Issues
|
||
|
|
|
||
|
|
### Issue: Permission Denied
|
||
|
|
**Problem**: Cannot access files in mounted volumes
|
||
|
|
**Solution**: Use `:Z` or `:z` suffix for SELinux, or check ownership
|
||
|
|
|
||
|
|
### Issue: Cannot Connect to Container
|
||
|
|
**Problem**: Port not accessible in rootless mode
|
||
|
|
**Solution**: Use ports >= 1024 or configure unprivileged port start
|
||
|
|
|
||
|
|
### Issue: Slow Image Pulls
|
||
|
|
**Problem**: Images download slowly
|
||
|
|
**Solution**: Configure registry mirrors in registries.conf
|
||
|
|
|
||
|
|
### Issue: Systemd Service Fails
|
||
|
|
**Problem**: Container doesn't start via systemd
|
||
|
|
**Solution**: Enable lingering: `loginctl enable-linger $USER`
|
||
|
|
|
||
|
|
## Best Practices
|
||
|
|
|
||
|
|
- Use rootless mode for enhanced security
|
||
|
|
- Leverage pods for related containers
|
||
|
|
- Generate systemd units for production
|
||
|
|
- Use Quadlet for declarative container services
|
||
|
|
- Configure SELinux labels for bind mounts
|
||
|
|
- Enable user lingering for persistent services
|
||
|
|
- Use podman auto-update for automatic updates
|
||
|
|
- Alias `docker` to `podman` for compatibility
|
||
|
|
|
||
|
|
## Related Skills
|
||
|
|
|
||
|
|
- [docker-management](../docker-management/) - Docker fundamentals
|
||
|
|
- [kubernetes-ops](../../orchestration/kubernetes-ops/) - K8s orchestration
|
||
|
|
- [container-hardening](../../../security/hardening/container-hardening/) - Security
|