mirror of
https://github.com/BagelHole/DevOps-Security-Agent-Skills.git
synced 2026-08-22 12:49:53 +02:00
.
This commit is contained in:
@@ -0,0 +1,411 @@
|
||||
---
|
||||
name: container-registries
|
||||
description: Manage container registries including ECR, ACR, GCR, and Docker Hub. Push and pull images, configure authentication, set up repository policies, and implement image lifecycle management. Use when working with container image storage and distribution.
|
||||
license: MIT
|
||||
metadata:
|
||||
author: devops-skills
|
||||
version: "1.0"
|
||||
---
|
||||
|
||||
# Container Registries
|
||||
|
||||
Store, manage, and distribute container images across cloud and self-hosted registries.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use this skill when:
|
||||
- Pushing and pulling container images
|
||||
- Configuring registry authentication
|
||||
- Setting up image retention policies
|
||||
- Managing private container registries
|
||||
- Implementing image scanning and security
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker or Podman installed
|
||||
- Cloud CLI tools (AWS CLI, az, gcloud) for respective registries
|
||||
- Appropriate IAM permissions
|
||||
|
||||
## Docker Hub
|
||||
|
||||
### Authentication
|
||||
|
||||
```bash
|
||||
# Login
|
||||
docker login
|
||||
|
||||
# Login with token
|
||||
echo "$DOCKER_TOKEN" | docker login -u username --password-stdin
|
||||
```
|
||||
|
||||
### Push/Pull Images
|
||||
|
||||
```bash
|
||||
# Tag image
|
||||
docker tag myapp:latest username/myapp:latest
|
||||
|
||||
# Push
|
||||
docker push username/myapp:latest
|
||||
|
||||
# Pull
|
||||
docker pull username/myapp:latest
|
||||
```
|
||||
|
||||
### Automated Builds
|
||||
|
||||
Configure in Docker Hub UI:
|
||||
1. Connect GitHub/Bitbucket repository
|
||||
2. Set build rules (branch → tag mapping)
|
||||
3. Configure build context and Dockerfile path
|
||||
|
||||
## Amazon ECR
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
# Create repository
|
||||
aws ecr create-repository \
|
||||
--repository-name myapp \
|
||||
--image-scanning-configuration scanOnPush=true \
|
||||
--encryption-configuration encryptionType=AES256
|
||||
|
||||
# Get registry URI
|
||||
REGISTRY=$(aws ecr describe-repositories \
|
||||
--repository-names myapp \
|
||||
--query 'repositories[0].repositoryUri' \
|
||||
--output text | cut -d'/' -f1)
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
```bash
|
||||
# Login (Docker)
|
||||
aws ecr get-login-password --region us-east-1 | \
|
||||
docker login --username AWS --password-stdin $REGISTRY
|
||||
|
||||
# Login with credential helper
|
||||
# Add to ~/.docker/config.json:
|
||||
{
|
||||
"credHelpers": {
|
||||
"123456789.dkr.ecr.us-east-1.amazonaws.com": "ecr-login"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Push/Pull
|
||||
|
||||
```bash
|
||||
# Tag and push
|
||||
docker tag myapp:latest $REGISTRY/myapp:latest
|
||||
docker push $REGISTRY/myapp:latest
|
||||
|
||||
# Pull
|
||||
docker pull $REGISTRY/myapp:latest
|
||||
```
|
||||
|
||||
### Lifecycle Policy
|
||||
|
||||
```bash
|
||||
# Create lifecycle policy
|
||||
aws ecr put-lifecycle-policy \
|
||||
--repository-name myapp \
|
||||
--lifecycle-policy-text '{
|
||||
"rules": [
|
||||
{
|
||||
"rulePriority": 1,
|
||||
"description": "Keep last 10 images",
|
||||
"selection": {
|
||||
"tagStatus": "any",
|
||||
"countType": "imageCountMoreThan",
|
||||
"countNumber": 10
|
||||
},
|
||||
"action": {
|
||||
"type": "expire"
|
||||
}
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
### Repository Policy
|
||||
|
||||
```bash
|
||||
# Allow cross-account access
|
||||
aws ecr set-repository-policy \
|
||||
--repository-name myapp \
|
||||
--policy-text '{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "CrossAccountPull",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::OTHER_ACCOUNT:root"
|
||||
},
|
||||
"Action": [
|
||||
"ecr:GetDownloadUrlForLayer",
|
||||
"ecr:BatchGetImage"
|
||||
]
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
## Azure Container Registry (ACR)
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
# Create registry
|
||||
az acr create \
|
||||
--resource-group mygroup \
|
||||
--name myregistry \
|
||||
--sku Standard \
|
||||
--admin-enabled false
|
||||
|
||||
# Get login server
|
||||
az acr show --name myregistry --query loginServer -o tsv
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
```bash
|
||||
# Login with Azure CLI
|
||||
az acr login --name myregistry
|
||||
|
||||
# Login with service principal
|
||||
docker login myregistry.azurecr.io \
|
||||
-u $SP_APP_ID \
|
||||
-p $SP_PASSWORD
|
||||
|
||||
# Get access token
|
||||
az acr login --name myregistry --expose-token
|
||||
```
|
||||
|
||||
### Push/Pull
|
||||
|
||||
```bash
|
||||
# Tag and push
|
||||
docker tag myapp:latest myregistry.azurecr.io/myapp:latest
|
||||
docker push myregistry.azurecr.io/myapp:latest
|
||||
|
||||
# ACR Build (build in cloud)
|
||||
az acr build \
|
||||
--registry myregistry \
|
||||
--image myapp:latest \
|
||||
--file Dockerfile .
|
||||
```
|
||||
|
||||
### Retention Policy
|
||||
|
||||
```bash
|
||||
# Enable retention policy
|
||||
az acr config retention update \
|
||||
--registry myregistry \
|
||||
--status enabled \
|
||||
--days 30 \
|
||||
--type UntaggedManifests
|
||||
```
|
||||
|
||||
### Geo-Replication
|
||||
|
||||
```bash
|
||||
# Enable replication
|
||||
az acr replication create \
|
||||
--registry myregistry \
|
||||
--location westeurope
|
||||
|
||||
# List replications
|
||||
az acr replication list --registry myregistry
|
||||
```
|
||||
|
||||
## Google Container Registry (GCR) / Artifact Registry
|
||||
|
||||
### Setup (Artifact Registry)
|
||||
|
||||
```bash
|
||||
# Create repository
|
||||
gcloud artifacts repositories create myrepo \
|
||||
--repository-format=docker \
|
||||
--location=us-central1 \
|
||||
--description="Docker repository"
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
```bash
|
||||
# Configure Docker auth
|
||||
gcloud auth configure-docker us-central1-docker.pkg.dev
|
||||
|
||||
# Or use credential helper
|
||||
gcloud auth print-access-token | \
|
||||
docker login -u oauth2accesstoken --password-stdin \
|
||||
https://us-central1-docker.pkg.dev
|
||||
```
|
||||
|
||||
### Push/Pull
|
||||
|
||||
```bash
|
||||
# Tag for Artifact Registry
|
||||
docker tag myapp:latest \
|
||||
us-central1-docker.pkg.dev/PROJECT_ID/myrepo/myapp:latest
|
||||
|
||||
# Push
|
||||
docker push us-central1-docker.pkg.dev/PROJECT_ID/myrepo/myapp:latest
|
||||
|
||||
# Pull
|
||||
docker pull us-central1-docker.pkg.dev/PROJECT_ID/myrepo/myapp:latest
|
||||
```
|
||||
|
||||
### Cleanup Policy
|
||||
|
||||
```bash
|
||||
# Create cleanup policy
|
||||
gcloud artifacts repositories set-cleanup-policies myrepo \
|
||||
--location=us-central1 \
|
||||
--policy=policy.json
|
||||
|
||||
# policy.json
|
||||
{
|
||||
"name": "delete-old",
|
||||
"action": {"type": "Delete"},
|
||||
"condition": {
|
||||
"olderThan": "30d",
|
||||
"tagState": "untagged"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## GitHub Container Registry (GHCR)
|
||||
|
||||
### Authentication
|
||||
|
||||
```bash
|
||||
# Login with PAT
|
||||
echo "$GITHUB_TOKEN" | docker login ghcr.io -u USERNAME --password-stdin
|
||||
```
|
||||
|
||||
### Push/Pull
|
||||
|
||||
```bash
|
||||
# Tag
|
||||
docker tag myapp:latest ghcr.io/OWNER/myapp:latest
|
||||
|
||||
# Push
|
||||
docker push ghcr.io/OWNER/myapp:latest
|
||||
|
||||
# Pull
|
||||
docker pull ghcr.io/OWNER/myapp:latest
|
||||
```
|
||||
|
||||
### Visibility Settings
|
||||
|
||||
Configure in GitHub:
|
||||
1. Go to package settings
|
||||
2. Change visibility (public/private)
|
||||
3. Manage access for teams/users
|
||||
|
||||
## Self-Hosted Registry
|
||||
|
||||
### Deploy with Docker
|
||||
|
||||
```bash
|
||||
# Run registry
|
||||
docker run -d -p 5000:5000 \
|
||||
--name registry \
|
||||
-v registry-data:/var/lib/registry \
|
||||
registry:2
|
||||
|
||||
# Configure TLS
|
||||
docker run -d -p 443:5000 \
|
||||
--name registry \
|
||||
-v /certs:/certs \
|
||||
-v registry-data:/var/lib/registry \
|
||||
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
|
||||
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
|
||||
registry:2
|
||||
```
|
||||
|
||||
### Harbor Registry
|
||||
|
||||
```bash
|
||||
# Download Harbor
|
||||
wget https://github.com/goharbor/harbor/releases/download/v2.9.0/harbor-online-installer-v2.9.0.tgz
|
||||
tar xzvf harbor-online-installer-v2.9.0.tgz
|
||||
|
||||
# Configure harbor.yml
|
||||
# Set hostname, https certificate, admin password
|
||||
|
||||
# Install
|
||||
./install.sh --with-trivy --with-chartmuseum
|
||||
```
|
||||
|
||||
## Image Security
|
||||
|
||||
### Vulnerability Scanning
|
||||
|
||||
```bash
|
||||
# ECR - Enable scan on push
|
||||
aws ecr put-image-scanning-configuration \
|
||||
--repository-name myapp \
|
||||
--image-scanning-configuration scanOnPush=true
|
||||
|
||||
# Get scan results
|
||||
aws ecr describe-image-scan-findings \
|
||||
--repository-name myapp \
|
||||
--image-id imageTag=latest
|
||||
|
||||
# ACR - Scan with Defender
|
||||
az acr task create \
|
||||
--registry myregistry \
|
||||
--name scan-images \
|
||||
--cmd "mcr.microsoft.com/azure-cli az acr run-scan"
|
||||
```
|
||||
|
||||
### Image Signing
|
||||
|
||||
```bash
|
||||
# Enable content trust
|
||||
export DOCKER_CONTENT_TRUST=1
|
||||
|
||||
# Sign image on push
|
||||
docker push myregistry/myapp:latest
|
||||
|
||||
# Verify signature
|
||||
docker trust inspect myregistry/myapp:latest
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Issue: Authentication Expired
|
||||
**Problem**: Push/pull fails with auth error
|
||||
**Solution**: Re-run login command, check credential helper
|
||||
|
||||
### Issue: Image Not Found
|
||||
**Problem**: Pull fails with manifest unknown
|
||||
**Solution**: Verify tag exists, check registry URL
|
||||
|
||||
### Issue: Push Permission Denied
|
||||
**Problem**: Cannot push to repository
|
||||
**Solution**: Check IAM permissions, verify repository exists
|
||||
|
||||
### Issue: Rate Limiting (Docker Hub)
|
||||
**Problem**: Too many requests error
|
||||
**Solution**: Authenticate for higher limits, use pull-through cache
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Enable vulnerability scanning on all repositories
|
||||
- Implement lifecycle policies to manage storage costs
|
||||
- Use immutable tags for production images
|
||||
- Configure cross-region replication for availability
|
||||
- Use service accounts/principals for CI/CD authentication
|
||||
- Enable audit logging for compliance
|
||||
- Implement image signing for supply chain security
|
||||
- Use pull-through cache to avoid rate limits
|
||||
|
||||
## Related Skills
|
||||
|
||||
- [docker-management](../docker-management/) - Building images
|
||||
- [container-scanning](../../../security/scanning/container-scanning/) - Security scanning
|
||||
- [aws-iam](../../../infrastructure/cloud-aws/aws-iam/) - AWS permissions
|
||||
@@ -0,0 +1,458 @@
|
||||
---
|
||||
name: docker-compose
|
||||
description: Define and run multi-container Docker applications using Docker Compose. Create compose files, manage service dependencies, configure networks and volumes, and orchestrate local development environments. Use when setting up multi-service applications or development environments.
|
||||
license: MIT
|
||||
metadata:
|
||||
author: devops-skills
|
||||
version: "1.0"
|
||||
---
|
||||
|
||||
# Docker Compose
|
||||
|
||||
Orchestrate multi-container applications with declarative YAML configuration.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use this skill when:
|
||||
- Running multi-container applications locally
|
||||
- Setting up development environments
|
||||
- Defining service dependencies and networking
|
||||
- Managing application stacks with multiple services
|
||||
- Creating reproducible development setups
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Engine with Compose plugin (v2)
|
||||
- Basic Docker knowledge
|
||||
- YAML syntax understanding
|
||||
|
||||
## Basic Configuration
|
||||
|
||||
### Simple Application Stack
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- DATABASE_URL=postgres://postgres:secret@db:5432/myapp
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
|
||||
db:
|
||||
image: postgres:15-alpine
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: secret
|
||||
POSTGRES_DB: myapp
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
```
|
||||
|
||||
## Service Configuration
|
||||
|
||||
### Build Options
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: ./app
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
NODE_VERSION: "20"
|
||||
target: development
|
||||
cache_from:
|
||||
- myapp:cache
|
||||
image: myapp:dev
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- API_KEY=${API_KEY} # From shell or .env file
|
||||
env_file:
|
||||
- .env
|
||||
- .env.local
|
||||
```
|
||||
|
||||
### Port Mapping
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
ports:
|
||||
- "3000:3000" # HOST:CONTAINER
|
||||
- "127.0.0.1:9229:9229" # Bind to localhost only
|
||||
- "8080-8090:8080-8090" # Port range
|
||||
expose:
|
||||
- "3000" # Internal only (no host binding)
|
||||
```
|
||||
|
||||
### Volume Mounts
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
volumes:
|
||||
# Named volume
|
||||
- app-data:/app/data
|
||||
# Bind mount
|
||||
- ./src:/app/src
|
||||
# Read-only bind mount
|
||||
- ./config:/app/config:ro
|
||||
# Anonymous volume (for node_modules)
|
||||
- /app/node_modules
|
||||
|
||||
volumes:
|
||||
app-data:
|
||||
driver: local
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
|
||||
db:
|
||||
image: postgres:15
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
```
|
||||
|
||||
## Networking
|
||||
|
||||
### Custom Networks
|
||||
|
||||
```yaml
|
||||
services:
|
||||
frontend:
|
||||
networks:
|
||||
- frontend-net
|
||||
|
||||
backend:
|
||||
networks:
|
||||
- frontend-net
|
||||
- backend-net
|
||||
|
||||
db:
|
||||
networks:
|
||||
- backend-net
|
||||
|
||||
networks:
|
||||
frontend-net:
|
||||
driver: bridge
|
||||
backend-net:
|
||||
driver: bridge
|
||||
internal: true # No external access
|
||||
```
|
||||
|
||||
### Network Aliases
|
||||
|
||||
```yaml
|
||||
services:
|
||||
db:
|
||||
networks:
|
||||
backend:
|
||||
aliases:
|
||||
- database
|
||||
- postgres
|
||||
|
||||
networks:
|
||||
backend:
|
||||
```
|
||||
|
||||
## Resource Limits
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
memory: 1G
|
||||
reservations:
|
||||
cpus: '0.5'
|
||||
memory: 256M
|
||||
```
|
||||
|
||||
## Multiple Compose Files
|
||||
|
||||
### Override Files
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml (base)
|
||||
services:
|
||||
web:
|
||||
image: myapp:latest
|
||||
ports:
|
||||
- "3000:3000"
|
||||
|
||||
# docker-compose.override.yml (development - auto-loaded)
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
volumes:
|
||||
- ./src:/app/src
|
||||
environment:
|
||||
- DEBUG=true
|
||||
|
||||
# docker-compose.prod.yml (production)
|
||||
services:
|
||||
web:
|
||||
deploy:
|
||||
replicas: 3
|
||||
environment:
|
||||
- DEBUG=false
|
||||
```
|
||||
|
||||
### Using Multiple Files
|
||||
|
||||
```bash
|
||||
# Development (uses override automatically)
|
||||
docker compose up
|
||||
|
||||
# Production
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
|
||||
|
||||
# Merge and view final config
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml config
|
||||
```
|
||||
|
||||
## Profiles
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
image: myapp
|
||||
|
||||
db:
|
||||
image: postgres:15
|
||||
|
||||
debug:
|
||||
image: busybox
|
||||
profiles:
|
||||
- debug
|
||||
|
||||
monitoring:
|
||||
image: prometheus
|
||||
profiles:
|
||||
- monitoring
|
||||
```
|
||||
|
||||
```bash
|
||||
# Run without profiles (web, db only)
|
||||
docker compose up
|
||||
|
||||
# Run with debug profile
|
||||
docker compose --profile debug up
|
||||
|
||||
# Run with multiple profiles
|
||||
docker compose --profile debug --profile monitoring up
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
### Lifecycle
|
||||
|
||||
```bash
|
||||
# Start services
|
||||
docker compose up -d
|
||||
|
||||
# Start specific service
|
||||
docker compose up -d web
|
||||
|
||||
# Stop services
|
||||
docker compose stop
|
||||
|
||||
# Stop and remove containers
|
||||
docker compose down
|
||||
|
||||
# Stop and remove everything including volumes
|
||||
docker compose down -v --rmi all
|
||||
|
||||
# Restart services
|
||||
docker compose restart web
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
```bash
|
||||
# Build images
|
||||
docker compose build
|
||||
|
||||
# Build without cache
|
||||
docker compose build --no-cache
|
||||
|
||||
# Build and start
|
||||
docker compose up --build
|
||||
|
||||
# Pull latest images
|
||||
docker compose pull
|
||||
```
|
||||
|
||||
### Monitoring
|
||||
|
||||
```bash
|
||||
# View logs
|
||||
docker compose logs -f
|
||||
|
||||
# View specific service logs
|
||||
docker compose logs -f web
|
||||
|
||||
# View running services
|
||||
docker compose ps
|
||||
|
||||
# View resource usage
|
||||
docker compose top
|
||||
```
|
||||
|
||||
### Execution
|
||||
|
||||
```bash
|
||||
# Run command in new container
|
||||
docker compose run --rm web npm test
|
||||
|
||||
# Execute in running container
|
||||
docker compose exec web /bin/sh
|
||||
|
||||
# Scale service
|
||||
docker compose up -d --scale worker=3
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Watch Mode (Compose v2.22+)
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
develop:
|
||||
watch:
|
||||
- action: sync
|
||||
path: ./src
|
||||
target: /app/src
|
||||
- action: rebuild
|
||||
path: ./package.json
|
||||
```
|
||||
|
||||
```bash
|
||||
docker compose watch
|
||||
```
|
||||
|
||||
### Hot Reload Setup
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
target: development
|
||||
volumes:
|
||||
- ./src:/app/src
|
||||
- /app/node_modules
|
||||
environment:
|
||||
- CHOKIDAR_USEPOLLING=true
|
||||
command: npm run dev
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Database Initialization
|
||||
|
||||
```yaml
|
||||
services:
|
||||
db:
|
||||
image: postgres:15
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
- ./init-scripts:/docker-entrypoint-initdb.d:ro
|
||||
environment:
|
||||
POSTGRES_DB: myapp
|
||||
```
|
||||
|
||||
### Reverse Proxy
|
||||
|
||||
```yaml
|
||||
services:
|
||||
proxy:
|
||||
image: traefik:v3.0
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- ./traefik.yml:/etc/traefik/traefik.yml:ro
|
||||
|
||||
web:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.web.rule=Host(`app.localhost`)"
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Issue: Container Cannot Resolve Service Name
|
||||
**Problem**: Service can't connect to another service by name
|
||||
**Solution**: Ensure services are on the same network, check depends_on
|
||||
|
||||
### Issue: Volume Permissions
|
||||
**Problem**: Container can't write to mounted volume
|
||||
**Solution**: Match container user UID with host, or use named volumes
|
||||
|
||||
### Issue: Port Already in Use
|
||||
**Problem**: Error binding to port
|
||||
**Solution**: Change host port or stop conflicting service
|
||||
|
||||
### Issue: Changes Not Reflected
|
||||
**Problem**: Code changes don't appear in container
|
||||
**Solution**: Check volume mounts, rebuild if Dockerfile changed
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Use named volumes for persistent data
|
||||
- Define healthchecks for database dependencies
|
||||
- Use profiles to separate optional services
|
||||
- Keep secrets in .env files (not committed)
|
||||
- Use override files for environment-specific config
|
||||
- Pin image versions for reproducibility
|
||||
- Use networks to isolate service groups
|
||||
- Leverage watch mode for development
|
||||
|
||||
## Related Skills
|
||||
|
||||
- [docker-management](../docker-management/) - Docker fundamentals
|
||||
- [kubernetes-ops](../../orchestration/kubernetes-ops/) - Production orchestration
|
||||
- [reverse-proxy](../../../infrastructure/networking/reverse-proxy/) - Production routing
|
||||
@@ -0,0 +1,124 @@
|
||||
# Docker Compose Patterns
|
||||
|
||||
## Basic Structure
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
ports:
|
||||
- "8080:80"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
depends_on:
|
||||
- db
|
||||
networks:
|
||||
- frontend
|
||||
- backend
|
||||
|
||||
db:
|
||||
image: postgres:15
|
||||
volumes:
|
||||
- db_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: myapp
|
||||
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
|
||||
secrets:
|
||||
- db_password
|
||||
networks:
|
||||
- backend
|
||||
|
||||
volumes:
|
||||
db_data:
|
||||
|
||||
networks:
|
||||
frontend:
|
||||
backend:
|
||||
|
||||
secrets:
|
||||
db_password:
|
||||
file: ./secrets/db_password.txt
|
||||
```
|
||||
|
||||
## Health Checks
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
```
|
||||
|
||||
## Resource Limits
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
memory: 512M
|
||||
reservations:
|
||||
cpus: '0.25'
|
||||
memory: 256M
|
||||
```
|
||||
|
||||
## Multiple Compose Files
|
||||
|
||||
```bash
|
||||
# Base + overrides
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
|
||||
|
||||
# Or use COMPOSE_FILE
|
||||
export COMPOSE_FILE=docker-compose.yml:docker-compose.prod.yml
|
||||
docker compose up
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```yaml
|
||||
# .env file
|
||||
services:
|
||||
app:
|
||||
image: myapp:${VERSION:-latest}
|
||||
environment:
|
||||
- DATABASE_URL=${DATABASE_URL}
|
||||
env_file:
|
||||
- .env
|
||||
- .env.local
|
||||
```
|
||||
|
||||
## Service Profiles
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
profiles: [] # Always starts
|
||||
|
||||
debug:
|
||||
profiles: [debug]
|
||||
# Only starts with --profile debug
|
||||
```
|
||||
|
||||
## Extension Fields
|
||||
|
||||
```yaml
|
||||
x-common: &common
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
|
||||
services:
|
||||
app:
|
||||
<<: *common
|
||||
image: myapp
|
||||
```
|
||||
@@ -0,0 +1,402 @@
|
||||
---
|
||||
name: docker-management
|
||||
description: Build, optimize, and troubleshoot Docker containers and images. Create efficient Dockerfiles, manage container lifecycle, configure networking and volumes, and debug container issues. Use when working with Docker, containerization, or container troubleshooting.
|
||||
license: MIT
|
||||
metadata:
|
||||
author: devops-skills
|
||||
version: "1.0"
|
||||
---
|
||||
|
||||
# Docker Management
|
||||
|
||||
Build, run, and manage Docker containers for application deployment and development.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use this skill when:
|
||||
- Creating and optimizing Dockerfiles
|
||||
- Building and tagging Docker images
|
||||
- Running and managing containers
|
||||
- Debugging container issues
|
||||
- Configuring Docker networking and volumes
|
||||
- Implementing container security best practices
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Engine installed (20.10+)
|
||||
- Basic command line knowledge
|
||||
- Understanding of application deployment
|
||||
|
||||
## Dockerfile Best Practices
|
||||
|
||||
### Multi-Stage Build
|
||||
|
||||
```dockerfile
|
||||
# Build stage
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci --only=production
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
# Production stage
|
||||
FROM node:20-alpine AS production
|
||||
WORKDIR /app
|
||||
RUN addgroup -g 1001 -S nodejs && \
|
||||
adduser -S nodejs -u 1001
|
||||
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
|
||||
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
|
||||
USER nodejs
|
||||
EXPOSE 3000
|
||||
CMD ["node", "dist/index.js"]
|
||||
```
|
||||
|
||||
### Layer Optimization
|
||||
|
||||
```dockerfile
|
||||
FROM python:3.12-slim
|
||||
|
||||
# Install dependencies first (cached unless requirements change)
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy application code (changes frequently)
|
||||
COPY . .
|
||||
|
||||
CMD ["python", "app.py"]
|
||||
```
|
||||
|
||||
### Security Hardening
|
||||
|
||||
```dockerfile
|
||||
FROM node:20-alpine
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup -g 1001 appgroup && \
|
||||
adduser -u 1001 -G appgroup -D appuser
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy with proper ownership
|
||||
COPY --chown=appuser:appgroup . .
|
||||
|
||||
# Drop privileges
|
||||
USER appuser
|
||||
|
||||
# Use exec form for proper signal handling
|
||||
CMD ["node", "server.js"]
|
||||
```
|
||||
|
||||
## Building Images
|
||||
|
||||
### Basic Build
|
||||
|
||||
```bash
|
||||
# Build with tag
|
||||
docker build -t myapp:1.0 .
|
||||
|
||||
# Build with build args
|
||||
docker build --build-arg NODE_ENV=production -t myapp:prod .
|
||||
|
||||
# Build for specific platform
|
||||
docker build --platform linux/amd64 -t myapp:amd64 .
|
||||
|
||||
# Build with no cache
|
||||
docker build --no-cache -t myapp:fresh .
|
||||
```
|
||||
|
||||
### Multi-Platform Builds
|
||||
|
||||
```bash
|
||||
# Create builder
|
||||
docker buildx create --name multiplatform --use
|
||||
|
||||
# Build for multiple architectures
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
-t myregistry/myapp:latest \
|
||||
--push .
|
||||
```
|
||||
|
||||
## Running Containers
|
||||
|
||||
### Basic Operations
|
||||
|
||||
```bash
|
||||
# Run container
|
||||
docker run -d --name myapp -p 8080:3000 myapp:latest
|
||||
|
||||
# Run with environment variables
|
||||
docker run -d \
|
||||
-e DATABASE_URL=postgres://localhost/db \
|
||||
-e NODE_ENV=production \
|
||||
myapp:latest
|
||||
|
||||
# Run with resource limits
|
||||
docker run -d \
|
||||
--memory="512m" \
|
||||
--cpus="1.0" \
|
||||
myapp:latest
|
||||
|
||||
# Run with restart policy
|
||||
docker run -d --restart=unless-stopped myapp:latest
|
||||
```
|
||||
|
||||
### Volume Management
|
||||
|
||||
```bash
|
||||
# Named volume
|
||||
docker volume create mydata
|
||||
docker run -v mydata:/app/data myapp:latest
|
||||
|
||||
# Bind mount
|
||||
docker run -v $(pwd)/config:/app/config:ro myapp:latest
|
||||
|
||||
# tmpfs mount (memory)
|
||||
docker run --tmpfs /tmp:rw,noexec,nosuid myapp:latest
|
||||
```
|
||||
|
||||
### Networking
|
||||
|
||||
```bash
|
||||
# Create network
|
||||
docker network create mynetwork
|
||||
|
||||
# Run on network
|
||||
docker run -d --network mynetwork --name api myapp:latest
|
||||
|
||||
# Connect existing container
|
||||
docker network connect mynetwork existing-container
|
||||
|
||||
# Expose specific ports
|
||||
docker run -d -p 127.0.0.1:8080:3000 myapp:latest
|
||||
```
|
||||
|
||||
## Container Lifecycle
|
||||
|
||||
### Management Commands
|
||||
|
||||
```bash
|
||||
# List containers
|
||||
docker ps -a
|
||||
|
||||
# Stop container
|
||||
docker stop myapp
|
||||
|
||||
# Remove container
|
||||
docker rm myapp
|
||||
|
||||
# Force remove running container
|
||||
docker rm -f myapp
|
||||
|
||||
# Prune stopped containers
|
||||
docker container prune -f
|
||||
```
|
||||
|
||||
### Logs and Monitoring
|
||||
|
||||
```bash
|
||||
# View logs
|
||||
docker logs myapp
|
||||
|
||||
# Follow logs
|
||||
docker logs -f --tail 100 myapp
|
||||
|
||||
# View resource usage
|
||||
docker stats myapp
|
||||
|
||||
# Inspect container
|
||||
docker inspect myapp
|
||||
```
|
||||
|
||||
## Debugging Containers
|
||||
|
||||
### Interactive Access
|
||||
|
||||
```bash
|
||||
# Execute command in running container
|
||||
docker exec -it myapp /bin/sh
|
||||
|
||||
# Run container with shell
|
||||
docker run -it --rm myapp:latest /bin/sh
|
||||
|
||||
# Debug failed container
|
||||
docker run -it --entrypoint /bin/sh myapp:latest
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
```bash
|
||||
# Check container logs for errors
|
||||
docker logs myapp 2>&1 | grep -i error
|
||||
|
||||
# Inspect container state
|
||||
docker inspect --format='{{.State.Status}}' myapp
|
||||
|
||||
# Check container processes
|
||||
docker top myapp
|
||||
|
||||
# View container filesystem changes
|
||||
docker diff myapp
|
||||
|
||||
# Export container filesystem
|
||||
docker export myapp > myapp-fs.tar
|
||||
```
|
||||
|
||||
### Health Checks
|
||||
|
||||
```dockerfile
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost:3000/health || exit 1
|
||||
```
|
||||
|
||||
```bash
|
||||
# Check health status
|
||||
docker inspect --format='{{.State.Health.Status}}' myapp
|
||||
```
|
||||
|
||||
## Image Management
|
||||
|
||||
### Tagging and Pushing
|
||||
|
||||
```bash
|
||||
# Tag image
|
||||
docker tag myapp:latest myregistry.com/myapp:v1.0
|
||||
|
||||
# Push to registry
|
||||
docker push myregistry.com/myapp:v1.0
|
||||
|
||||
# Pull image
|
||||
docker pull myregistry.com/myapp:v1.0
|
||||
```
|
||||
|
||||
### Cleanup
|
||||
|
||||
```bash
|
||||
# Remove unused images
|
||||
docker image prune -a
|
||||
|
||||
# Remove all unused resources
|
||||
docker system prune -a --volumes
|
||||
|
||||
# Remove specific image
|
||||
docker rmi myapp:old
|
||||
|
||||
# List image sizes
|
||||
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
|
||||
```
|
||||
|
||||
### Image Analysis
|
||||
|
||||
```bash
|
||||
# View image history
|
||||
docker history myapp:latest
|
||||
|
||||
# Inspect image layers
|
||||
docker inspect myapp:latest
|
||||
|
||||
# Check image vulnerabilities (with Docker Scout)
|
||||
docker scout cves myapp:latest
|
||||
```
|
||||
|
||||
## Docker Compose Integration
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
volumes:
|
||||
- app-data:/app/data
|
||||
depends_on:
|
||||
- db
|
||||
restart: unless-stopped
|
||||
|
||||
db:
|
||||
image: postgres:15-alpine
|
||||
environment:
|
||||
POSTGRES_PASSWORD: secret
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
|
||||
volumes:
|
||||
app-data:
|
||||
db-data:
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### Image Security
|
||||
|
||||
```dockerfile
|
||||
# Use specific version tags
|
||||
FROM node:20.10-alpine3.18
|
||||
|
||||
# Don't run as root
|
||||
USER nobody
|
||||
|
||||
# Remove unnecessary packages
|
||||
RUN apk del --purge build-dependencies
|
||||
|
||||
# Use COPY instead of ADD
|
||||
COPY . .
|
||||
```
|
||||
|
||||
### Runtime Security
|
||||
|
||||
```bash
|
||||
# Run with security options
|
||||
docker run -d \
|
||||
--security-opt=no-new-privileges \
|
||||
--cap-drop=ALL \
|
||||
--cap-add=NET_BIND_SERVICE \
|
||||
--read-only \
|
||||
myapp:latest
|
||||
|
||||
# Use user namespace remapping
|
||||
# Add to /etc/docker/daemon.json: {"userns-remap": "default"}
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Issue: Container Exits Immediately
|
||||
**Problem**: Container starts and stops instantly
|
||||
**Solution**: Check if CMD/ENTRYPOINT runs foreground process, use `docker logs` to see errors
|
||||
|
||||
### Issue: Cannot Connect to Container
|
||||
**Problem**: Port not accessible
|
||||
**Solution**: Verify port mapping (-p), check container is running, verify firewall rules
|
||||
|
||||
### Issue: Out of Disk Space
|
||||
**Problem**: Docker using too much disk
|
||||
**Solution**: Run `docker system prune -a --volumes`, check for large unused images
|
||||
|
||||
### Issue: Build Cache Not Working
|
||||
**Problem**: Every build downloads dependencies
|
||||
**Solution**: Order Dockerfile instructions from least to most frequently changing
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Use multi-stage builds to minimize image size
|
||||
- Never store secrets in images - use runtime injection
|
||||
- Pin base image versions for reproducibility
|
||||
- Implement health checks for production containers
|
||||
- Use .dockerignore to exclude unnecessary files
|
||||
- Run containers as non-root users
|
||||
- Scan images for vulnerabilities regularly
|
||||
- Use Docker BuildKit for faster builds
|
||||
|
||||
## Related Skills
|
||||
|
||||
- [docker-compose](../docker-compose/) - Multi-container applications
|
||||
- [container-scanning](../../../security/scanning/container-scanning/) - Security scanning
|
||||
- [container-hardening](../../../security/hardening/container-hardening/) - Security hardening
|
||||
@@ -0,0 +1,111 @@
|
||||
# Docker Command Reference
|
||||
|
||||
## Container Lifecycle
|
||||
|
||||
```bash
|
||||
# Run container
|
||||
docker run -d --name myapp -p 8080:80 nginx
|
||||
docker run -it --rm ubuntu bash
|
||||
|
||||
# Start/Stop
|
||||
docker start myapp
|
||||
docker stop myapp
|
||||
docker restart myapp
|
||||
|
||||
# Remove
|
||||
docker rm myapp
|
||||
docker rm -f myapp # Force
|
||||
|
||||
# Logs
|
||||
docker logs myapp
|
||||
docker logs -f myapp # Follow
|
||||
docker logs --tail 100 myapp
|
||||
```
|
||||
|
||||
## Images
|
||||
|
||||
```bash
|
||||
# List/Pull/Build
|
||||
docker images
|
||||
docker pull nginx:latest
|
||||
docker build -t myapp:1.0 .
|
||||
docker build -t myapp:1.0 -f Dockerfile.prod .
|
||||
|
||||
# Tag/Push
|
||||
docker tag myapp:1.0 registry.example.com/myapp:1.0
|
||||
docker push registry.example.com/myapp:1.0
|
||||
|
||||
# Remove
|
||||
docker rmi myapp:1.0
|
||||
docker image prune -a # Remove unused
|
||||
```
|
||||
|
||||
## Inspection
|
||||
|
||||
```bash
|
||||
# Container info
|
||||
docker ps
|
||||
docker ps -a
|
||||
docker inspect myapp
|
||||
docker stats
|
||||
docker top myapp
|
||||
|
||||
# Exec into container
|
||||
docker exec -it myapp bash
|
||||
docker exec myapp ls -la /app
|
||||
```
|
||||
|
||||
## Networks
|
||||
|
||||
```bash
|
||||
# List/Create
|
||||
docker network ls
|
||||
docker network create mynet
|
||||
|
||||
# Connect container
|
||||
docker network connect mynet myapp
|
||||
docker run --network mynet nginx
|
||||
```
|
||||
|
||||
## Volumes
|
||||
|
||||
```bash
|
||||
# List/Create
|
||||
docker volume ls
|
||||
docker volume create mydata
|
||||
|
||||
# Mount
|
||||
docker run -v mydata:/data nginx
|
||||
docker run -v $(pwd):/app nginx
|
||||
docker run --mount type=bind,source=$(pwd),target=/app nginx
|
||||
```
|
||||
|
||||
## Cleanup
|
||||
|
||||
```bash
|
||||
# Remove stopped containers
|
||||
docker container prune
|
||||
|
||||
# Remove unused images
|
||||
docker image prune -a
|
||||
|
||||
# Remove everything unused
|
||||
docker system prune -a --volumes
|
||||
|
||||
# Disk usage
|
||||
docker system df
|
||||
```
|
||||
|
||||
## Multi-stage Build
|
||||
|
||||
```dockerfile
|
||||
FROM node:20 AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginx:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
```
|
||||
@@ -0,0 +1,381 @@
|
||||
---
|
||||
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
|
||||
Reference in New Issue
Block a user