Initial commit
This commit is contained in:
268
skills/docker/references/compose.md
Normal file
268
skills/docker/references/compose.md
Normal file
@@ -0,0 +1,268 @@
|
||||
# Docker Compose Reference
|
||||
|
||||
## File Structure
|
||||
|
||||
```yaml
|
||||
name: project-name # Optional, defaults to directory name
|
||||
|
||||
services:
|
||||
service-name:
|
||||
# Image or build
|
||||
image: image:tag
|
||||
build:
|
||||
context: ./path
|
||||
dockerfile: Dockerfile
|
||||
|
||||
# Networking
|
||||
ports:
|
||||
- "host:container"
|
||||
networks:
|
||||
- network-name
|
||||
|
||||
# Storage
|
||||
volumes:
|
||||
- named-volume:/path
|
||||
- ./host-path:/container-path
|
||||
|
||||
# Environment
|
||||
environment:
|
||||
KEY: value
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
# Dependencies
|
||||
depends_on:
|
||||
- other-service
|
||||
|
||||
# Lifecycle
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
# Resources
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
memory: 512M
|
||||
reservations:
|
||||
memory: 256M
|
||||
|
||||
networks:
|
||||
network-name:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
named-volume:
|
||||
```
|
||||
|
||||
## Service Options
|
||||
|
||||
### Image vs Build
|
||||
|
||||
```yaml
|
||||
# Use existing image
|
||||
image: nginx:1.25-alpine
|
||||
|
||||
# Build from Dockerfile
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
BUILD_ARG: value
|
||||
```
|
||||
|
||||
### Port Mapping
|
||||
|
||||
```yaml
|
||||
ports:
|
||||
- "80:80" # host:container
|
||||
- "443:443"
|
||||
- "127.0.0.1:8080:80" # localhost only
|
||||
- "8080-8090:8080-8090" # range
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```yaml
|
||||
# Inline
|
||||
environment:
|
||||
DATABASE_URL: postgres://db:5432/app
|
||||
DEBUG: "false"
|
||||
|
||||
# From file
|
||||
env_file:
|
||||
- .env
|
||||
- .env.local
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
```yaml
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
|
||||
# With conditions (compose v2.1+)
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
```
|
||||
|
||||
### Restart Policies
|
||||
|
||||
| Policy | Behavior |
|
||||
|--------|----------|
|
||||
| no | Never restart (default) |
|
||||
| always | Always restart |
|
||||
| unless-stopped | Restart unless manually stopped |
|
||||
| on-failure | Restart only on error exit |
|
||||
|
||||
### Health Checks
|
||||
|
||||
```yaml
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/health"]
|
||||
interval: 30s # Time between checks
|
||||
timeout: 10s # Check timeout
|
||||
retries: 3 # Failures before unhealthy
|
||||
start_period: 40s # Grace period on startup
|
||||
```
|
||||
|
||||
### Resource Limits
|
||||
|
||||
```yaml
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
memory: 1G
|
||||
reservations:
|
||||
cpus: '0.5'
|
||||
memory: 256M
|
||||
```
|
||||
|
||||
## Network Configuration
|
||||
|
||||
### Custom Network
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
frontend:
|
||||
driver: bridge
|
||||
backend:
|
||||
driver: bridge
|
||||
internal: true # No external access
|
||||
```
|
||||
|
||||
### External Network
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
existing-network:
|
||||
external: true
|
||||
```
|
||||
|
||||
### Macvlan Network
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
lan:
|
||||
driver: macvlan
|
||||
driver_opts:
|
||||
parent: eth0
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 192.168.1.0/24
|
||||
gateway: 192.168.1.1
|
||||
```
|
||||
|
||||
## Volume Configuration
|
||||
|
||||
### Named Volume
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
data:
|
||||
driver: local
|
||||
|
||||
services:
|
||||
db:
|
||||
volumes:
|
||||
- data:/var/lib/mysql
|
||||
```
|
||||
|
||||
### Bind Mount
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
volumes:
|
||||
- ./config:/etc/app/config:ro
|
||||
- ./data:/app/data
|
||||
```
|
||||
|
||||
### tmpfs Mount
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
tmpfs:
|
||||
- /tmp
|
||||
- /run
|
||||
```
|
||||
|
||||
## Multi-Environment Setup
|
||||
|
||||
### Using .env Files
|
||||
|
||||
```bash
|
||||
# .env
|
||||
COMPOSE_PROJECT_NAME=myapp
|
||||
IMAGE_TAG=latest
|
||||
```
|
||||
|
||||
```yaml
|
||||
# docker-compose.yaml
|
||||
services:
|
||||
app:
|
||||
image: myapp:${IMAGE_TAG}
|
||||
```
|
||||
|
||||
### Override Files
|
||||
|
||||
```bash
|
||||
# Base config
|
||||
docker-compose.yaml
|
||||
|
||||
# Development overrides
|
||||
docker-compose.override.yaml # Auto-loaded
|
||||
|
||||
# Production
|
||||
docker compose -f docker-compose.yaml -f docker-compose.prod.yaml up
|
||||
```
|
||||
|
||||
## Useful Commands
|
||||
|
||||
```bash
|
||||
# Start with rebuild
|
||||
docker compose up -d --build
|
||||
|
||||
# Scale service
|
||||
docker compose up -d --scale web=3
|
||||
|
||||
# View config after variable substitution
|
||||
docker compose config
|
||||
|
||||
# Execute command in service
|
||||
docker compose exec web sh
|
||||
|
||||
# View service logs
|
||||
docker compose logs -f web
|
||||
|
||||
# Restart single service
|
||||
docker compose restart web
|
||||
```
|
||||
243
skills/docker/references/dockerfile.md
Normal file
243
skills/docker/references/dockerfile.md
Normal file
@@ -0,0 +1,243 @@
|
||||
# Dockerfile Reference
|
||||
|
||||
## Basic Structure
|
||||
|
||||
```dockerfile
|
||||
# Base image
|
||||
FROM ubuntu:22.04
|
||||
|
||||
# Metadata
|
||||
LABEL maintainer="team@example.com"
|
||||
LABEL version="1.0"
|
||||
|
||||
# Environment
|
||||
ENV APP_HOME=/app
|
||||
WORKDIR $APP_HOME
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
package1 \
|
||||
package2 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy files
|
||||
COPY requirements.txt .
|
||||
RUN pip install -r requirements.txt
|
||||
COPY . .
|
||||
|
||||
# Non-root user
|
||||
RUN useradd -r -s /bin/false appuser
|
||||
USER appuser
|
||||
|
||||
# Expose port
|
||||
EXPOSE 8080
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=3s \
|
||||
CMD curl -f http://localhost:8080/health || exit 1
|
||||
|
||||
# Entry point
|
||||
ENTRYPOINT ["python"]
|
||||
CMD ["app.py"]
|
||||
```
|
||||
|
||||
## Multi-Stage Builds
|
||||
|
||||
Reduce final image size by separating build and runtime:
|
||||
|
||||
```dockerfile
|
||||
# Build stage
|
||||
FROM golang:1.21 AS builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN go build -o myapp
|
||||
|
||||
# Runtime stage
|
||||
FROM alpine:3.18
|
||||
COPY --from=builder /app/myapp /usr/local/bin/
|
||||
CMD ["myapp"]
|
||||
```
|
||||
|
||||
## Common Base Images
|
||||
|
||||
| Image | Size | Use Case |
|
||||
|-------|------|----------|
|
||||
| alpine | ~5MB | Minimal, production |
|
||||
| debian:slim | ~80MB | Compatibility |
|
||||
| ubuntu | ~75MB | Development |
|
||||
| distroless | ~20MB | Security-focused |
|
||||
| scratch | 0MB | Static binaries only |
|
||||
|
||||
## Instructions Reference
|
||||
|
||||
### FROM
|
||||
|
||||
```dockerfile
|
||||
FROM image:tag
|
||||
FROM image:tag AS builder
|
||||
FROM --platform=linux/amd64 image:tag
|
||||
```
|
||||
|
||||
### RUN
|
||||
|
||||
```dockerfile
|
||||
# Shell form
|
||||
RUN apt-get update && apt-get install -y package
|
||||
|
||||
# Exec form
|
||||
RUN ["executable", "param1", "param2"]
|
||||
```
|
||||
|
||||
### COPY vs ADD
|
||||
|
||||
```dockerfile
|
||||
# COPY - preferred for local files
|
||||
COPY ./src /app/src
|
||||
COPY --chown=user:group files /app/
|
||||
|
||||
# ADD - can extract tars, fetch URLs (use sparingly)
|
||||
ADD archive.tar.gz /app/
|
||||
```
|
||||
|
||||
### ENV vs ARG
|
||||
|
||||
```dockerfile
|
||||
# ARG - build-time only
|
||||
ARG VERSION=1.0
|
||||
|
||||
# ENV - persists in image
|
||||
ENV APP_VERSION=$VERSION
|
||||
```
|
||||
|
||||
### EXPOSE
|
||||
|
||||
```dockerfile
|
||||
EXPOSE 8080
|
||||
EXPOSE 443/tcp
|
||||
EXPOSE 53/udp
|
||||
```
|
||||
|
||||
Documentation only - doesn't publish ports.
|
||||
|
||||
### ENTRYPOINT vs CMD
|
||||
|
||||
```dockerfile
|
||||
# ENTRYPOINT - main executable
|
||||
ENTRYPOINT ["python"]
|
||||
|
||||
# CMD - default arguments (can be overridden)
|
||||
CMD ["app.py"]
|
||||
|
||||
# Combined: python app.py
|
||||
# Override: docker run image other.py -> python other.py
|
||||
```
|
||||
|
||||
### USER
|
||||
|
||||
```dockerfile
|
||||
RUN useradd -r -s /bin/false appuser
|
||||
USER appuser
|
||||
```
|
||||
|
||||
### HEALTHCHECK
|
||||
|
||||
```dockerfile
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost/health || exit 1
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Layer Caching
|
||||
|
||||
Order from least to most frequently changed:
|
||||
|
||||
```dockerfile
|
||||
# Rarely changes - cached
|
||||
FROM node:18-alpine
|
||||
WORKDIR /app
|
||||
|
||||
# Changes when deps change
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
|
||||
# Changes frequently - rebuild each time
|
||||
COPY . .
|
||||
```
|
||||
|
||||
### Reduce Layers
|
||||
|
||||
Combine RUN commands:
|
||||
|
||||
```dockerfile
|
||||
# Bad - 3 layers
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y package
|
||||
RUN rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Good - 1 layer
|
||||
RUN apt-get update && \
|
||||
apt-get install -y package && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
```dockerfile
|
||||
# Use specific tags
|
||||
FROM node:18.17.0-alpine # Not :latest
|
||||
|
||||
# Non-root user
|
||||
USER nobody
|
||||
|
||||
# Read-only filesystem
|
||||
# (Set at runtime with --read-only)
|
||||
|
||||
# No secrets in image
|
||||
# (Use build args or runtime secrets)
|
||||
```
|
||||
|
||||
### .dockerignore
|
||||
|
||||
```
|
||||
.git
|
||||
.gitignore
|
||||
node_modules
|
||||
*.log
|
||||
.env
|
||||
Dockerfile
|
||||
docker-compose.yaml
|
||||
README.md
|
||||
```
|
||||
|
||||
## Build Commands
|
||||
|
||||
```bash
|
||||
# Basic build
|
||||
docker build -t myimage:tag .
|
||||
|
||||
# With build args
|
||||
docker build --build-arg VERSION=1.0 -t myimage .
|
||||
|
||||
# No cache
|
||||
docker build --no-cache -t myimage .
|
||||
|
||||
# Specific Dockerfile
|
||||
docker build -f Dockerfile.prod -t myimage .
|
||||
|
||||
# Multi-platform
|
||||
docker buildx build --platform linux/amd64,linux/arm64 -t myimage .
|
||||
```
|
||||
|
||||
## Debugging Builds
|
||||
|
||||
```bash
|
||||
# Build with progress output
|
||||
docker build --progress=plain -t myimage .
|
||||
|
||||
# Inspect layers
|
||||
docker history myimage
|
||||
|
||||
# Check image size
|
||||
docker images myimage
|
||||
```
|
||||
229
skills/docker/references/networking.md
Normal file
229
skills/docker/references/networking.md
Normal file
@@ -0,0 +1,229 @@
|
||||
# Docker Networking Reference
|
||||
|
||||
## Network Drivers
|
||||
|
||||
### Bridge (Default)
|
||||
|
||||
Isolated container network with port mapping.
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
app-network:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
- Containers get private IPs (172.17.0.0/16 default)
|
||||
- Port mapping exposes services (`-p 80:80`)
|
||||
- DNS resolution between containers by name
|
||||
- Default for single-host deployments
|
||||
|
||||
### Host
|
||||
|
||||
Container shares host network stack.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
network_mode: host
|
||||
```
|
||||
|
||||
- No network isolation
|
||||
- No port mapping needed (container uses host ports)
|
||||
- Best performance (no NAT overhead)
|
||||
- Use for: Network tools, performance-critical apps
|
||||
|
||||
### Macvlan
|
||||
|
||||
Container gets own MAC address on physical network.
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
lan:
|
||||
driver: macvlan
|
||||
driver_opts:
|
||||
parent: eth0
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 192.168.1.0/24
|
||||
gateway: 192.168.1.1
|
||||
ip_range: 192.168.1.128/25
|
||||
```
|
||||
|
||||
- Container appears as physical device on LAN
|
||||
- Direct network access, no port mapping
|
||||
- Use for: Services needing LAN presence (DNS, DHCP)
|
||||
- Requires promiscuous mode on parent interface
|
||||
|
||||
### IPvlan
|
||||
|
||||
Like macvlan but shares host MAC address.
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
lan:
|
||||
driver: ipvlan
|
||||
driver_opts:
|
||||
parent: eth0
|
||||
ipvlan_mode: l2 # or l3
|
||||
```
|
||||
|
||||
- L2 mode: Same subnet as host
|
||||
- L3 mode: Different subnet, requires routing
|
||||
- Use when: Macvlan blocked by switch, cloud environments
|
||||
|
||||
### None
|
||||
|
||||
No networking.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
isolated:
|
||||
network_mode: none
|
||||
```
|
||||
|
||||
## Port Mapping
|
||||
|
||||
```yaml
|
||||
ports:
|
||||
# Simple mapping
|
||||
- "80:80"
|
||||
|
||||
# Different host port
|
||||
- "8080:80"
|
||||
|
||||
# Localhost only
|
||||
- "127.0.0.1:8080:80"
|
||||
|
||||
# UDP
|
||||
- "53:53/udp"
|
||||
|
||||
# Range
|
||||
- "8080-8090:8080-8090"
|
||||
|
||||
# Random host port
|
||||
- "80"
|
||||
```
|
||||
|
||||
## DNS and Service Discovery
|
||||
|
||||
### Automatic DNS
|
||||
|
||||
Containers on same network resolve each other by service name:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
networks:
|
||||
- app
|
||||
db:
|
||||
networks:
|
||||
- app
|
||||
```
|
||||
|
||||
`web` can reach `db` at hostname `db`.
|
||||
|
||||
### Aliases
|
||||
|
||||
```yaml
|
||||
services:
|
||||
db:
|
||||
networks:
|
||||
app:
|
||||
aliases:
|
||||
- database
|
||||
- mysql
|
||||
```
|
||||
|
||||
### Custom DNS
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
dns:
|
||||
- 8.8.8.8
|
||||
- 8.8.4.4
|
||||
dns_search:
|
||||
- example.com
|
||||
```
|
||||
|
||||
## Network Isolation
|
||||
|
||||
### Internal Networks
|
||||
|
||||
No external connectivity:
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
backend:
|
||||
internal: true
|
||||
```
|
||||
|
||||
### Multiple Networks
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
networks:
|
||||
- frontend
|
||||
- backend
|
||||
|
||||
db:
|
||||
networks:
|
||||
- backend # Not on frontend
|
||||
|
||||
networks:
|
||||
frontend:
|
||||
backend:
|
||||
internal: true
|
||||
```
|
||||
|
||||
## Static IPs
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
networks:
|
||||
app-network:
|
||||
ipv4_address: 172.20.0.10
|
||||
|
||||
networks:
|
||||
app-network:
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.20.0.0/24
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Inspect Network
|
||||
|
||||
```bash
|
||||
docker network ls
|
||||
docker network inspect <network>
|
||||
```
|
||||
|
||||
### Container Network Info
|
||||
|
||||
```bash
|
||||
docker inspect <container> --format '{{json .NetworkSettings.Networks}}'
|
||||
```
|
||||
|
||||
### Test Connectivity
|
||||
|
||||
```bash
|
||||
# From inside container
|
||||
docker exec <container> ping <target>
|
||||
docker exec <container> curl <url>
|
||||
|
||||
# Check DNS
|
||||
docker exec <container> nslookup <hostname>
|
||||
```
|
||||
|
||||
### Common Issues
|
||||
|
||||
| Problem | Check |
|
||||
|---------|-------|
|
||||
| Can't reach container | Port mapping, firewall, network attachment |
|
||||
| DNS not working | Same network, container running |
|
||||
| Slow network | Network mode, MTU settings |
|
||||
| Port already in use | `lsof -i :<port>`, change mapping |
|
||||
227
skills/docker/references/proxmox/hosting.md
Normal file
227
skills/docker/references/proxmox/hosting.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# Docker on Proxmox VMs
|
||||
|
||||
Best practices for running Docker workloads on Proxmox VE.
|
||||
|
||||
## Template Selection
|
||||
|
||||
Use Docker-ready templates (102+) which have Docker pre-installed:
|
||||
|
||||
| Template ID | Name | Docker? |
|
||||
|-------------|------|---------|
|
||||
| 100 | tmpl-ubuntu-2404-base | No |
|
||||
| 101 | tmpl-ubuntu-2404-standard | No |
|
||||
| 102 | tmpl-ubuntu-2404-docker | Yes |
|
||||
| 103 | tmpl-ubuntu-2404-github-runner | Yes |
|
||||
| 104 | tmpl-ubuntu-2404-pihole | Yes |
|
||||
|
||||
**DO NOT** install Docker via cloud-init on templates 102+.
|
||||
|
||||
## VM vs LXC for Docker
|
||||
|
||||
| Factor | VM (QEMU) | LXC Unprivileged | LXC Privileged |
|
||||
|--------|-----------|------------------|----------------|
|
||||
| Docker support | Full | Limited | Works but risky |
|
||||
| Isolation | Complete | Shared kernel | Shared kernel |
|
||||
| Overhead | Higher | Lower | Lower |
|
||||
| Nested containers | Works | Requires config | Works |
|
||||
| GPU passthrough | Yes | Limited | Limited |
|
||||
| Security | Best | Good | Avoid |
|
||||
|
||||
**Recommendation:** Use VMs for Docker workloads. LXC adds complexity for marginal resource savings.
|
||||
|
||||
## VM Sizing for Docker
|
||||
|
||||
### Minimum for Docker host
|
||||
|
||||
```
|
||||
CPU: 2 cores
|
||||
RAM: 4 GB (2 GB for OS, 2 GB for containers)
|
||||
Disk: 50 GB (20 GB OS, 30 GB images/volumes)
|
||||
```
|
||||
|
||||
### Per-container overhead
|
||||
|
||||
```
|
||||
Base: ~10 MB RAM per container
|
||||
Image layers: Shared between containers
|
||||
Volumes: Depends on data
|
||||
```
|
||||
|
||||
### Sizing formula
|
||||
|
||||
```
|
||||
Total RAM = 2 GB (OS) + sum(container memory limits) + 20% buffer
|
||||
Total Disk = 20 GB (OS) + images + volumes + 20% buffer
|
||||
```
|
||||
|
||||
## Storage Backend Selection
|
||||
|
||||
| Proxmox Storage | Docker Use Case | Performance |
|
||||
|-----------------|-----------------|-------------|
|
||||
| local-lvm | General workloads | Good |
|
||||
| ZFS | Database containers | Better (snapshots) |
|
||||
| Ceph | HA workloads | Good (distributed) |
|
||||
| NFS | Shared config/data | Moderate |
|
||||
|
||||
### Volume mapping to Proxmox storage
|
||||
|
||||
```yaml
|
||||
# docker-compose.yaml
|
||||
volumes:
|
||||
db_data:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
device: /mnt/storage/mysql # Map to Proxmox storage mount
|
||||
o: bind
|
||||
```
|
||||
|
||||
## Network Considerations
|
||||
|
||||
### Bridge mode (default)
|
||||
|
||||
Container gets private IP, NAT to VM IP. Good for most workloads.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
ports:
|
||||
- "80:80" # VM_IP:80 -> container:80
|
||||
```
|
||||
|
||||
### Host mode
|
||||
|
||||
Container shares VM network stack. Use for network tools or performance.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
pihole:
|
||||
network_mode: host # Container uses VM's IPs directly
|
||||
```
|
||||
|
||||
### Macvlan (direct LAN access)
|
||||
|
||||
Container gets own IP on Proxmox bridge.
|
||||
|
||||
```bash
|
||||
# On Docker host (VM)
|
||||
docker network create -d macvlan \
|
||||
--subnet=192.168.1.0/24 \
|
||||
--gateway=192.168.1.1 \
|
||||
-o parent=eth0 \
|
||||
lan
|
||||
```
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
networks:
|
||||
lan:
|
||||
ipv4_address: 192.168.1.50
|
||||
|
||||
networks:
|
||||
lan:
|
||||
external: true
|
||||
```
|
||||
|
||||
**Note:** Requires Proxmox bridge without VLAN tagging on that interface, or pass-through the VLAN-tagged interface to VM.
|
||||
|
||||
## Resource Limits
|
||||
|
||||
Always set limits to prevent container runaway affecting VM:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
memory: 2G
|
||||
reservations:
|
||||
cpus: '0.5'
|
||||
memory: 512M
|
||||
```
|
||||
|
||||
## GPU Passthrough
|
||||
|
||||
For containers needing GPU (AI/ML, transcoding):
|
||||
|
||||
1. **Proxmox:** Pass GPU to VM
|
||||
```
|
||||
hostpci0: 0000:01:00.0,pcie=1
|
||||
```
|
||||
|
||||
2. **VM:** Install NVIDIA drivers + nvidia-container-toolkit
|
||||
|
||||
3. **Compose:**
|
||||
```yaml
|
||||
services:
|
||||
plex:
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: 1
|
||||
capabilities: [gpu]
|
||||
```
|
||||
|
||||
## Backup Considerations
|
||||
|
||||
### What to backup
|
||||
|
||||
| Data | Method | Location |
|
||||
|------|--------|----------|
|
||||
| VM disk | Proxmox vzdump | Includes everything |
|
||||
| Docker volumes | docker run --volumes-from | Application-level |
|
||||
| Compose files | Git | Version control |
|
||||
|
||||
### Proxmox backup includes Docker
|
||||
|
||||
When backing up the VM with vzdump, all Docker data (images, volumes, containers) is included.
|
||||
|
||||
```bash
|
||||
vzdump <vmid> --mode snapshot --storage backup
|
||||
```
|
||||
|
||||
### Application-consistent backups
|
||||
|
||||
For databases, use pre/post scripts:
|
||||
|
||||
```bash
|
||||
# Pre-backup: flush and lock
|
||||
docker exec mysql mysql -e "FLUSH TABLES WITH READ LOCK;"
|
||||
|
||||
# vzdump runs...
|
||||
|
||||
# Post-backup: unlock
|
||||
docker exec mysql mysql -e "UNLOCK TABLES;"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Container can't reach internet
|
||||
|
||||
1. Check VM can reach internet: `ping 8.8.8.8`
|
||||
2. Check Docker DNS: `docker run --rm alpine nslookup google.com`
|
||||
3. Check iptables forwarding: `sysctl net.ipv4.ip_forward`
|
||||
|
||||
### Port not accessible from LAN
|
||||
|
||||
1. Check Proxmox firewall allows port
|
||||
2. Check VM firewall (ufw/iptables)
|
||||
3. Check container is bound to 0.0.0.0 not 127.0.0.1
|
||||
|
||||
### Disk space issues
|
||||
|
||||
```bash
|
||||
# Check Docker disk usage
|
||||
docker system df
|
||||
|
||||
# Clean up
|
||||
docker system prune -a --volumes # WARNING: removes all unused data
|
||||
|
||||
# Check VM disk
|
||||
df -h
|
||||
```
|
||||
140
skills/docker/references/proxmox/lxc-vs-docker.md
Normal file
140
skills/docker/references/proxmox/lxc-vs-docker.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# LXC vs Docker Containers
|
||||
|
||||
Understanding when to use Proxmox LXC containers vs Docker containers.
|
||||
|
||||
## Fundamental Differences
|
||||
|
||||
| Aspect | LXC (Proxmox) | Docker |
|
||||
|--------|---------------|--------|
|
||||
| Abstraction | System container (full OS) | Application container |
|
||||
| Init system | systemd, runit, etc. | Single process (PID 1) |
|
||||
| Management | Proxmox (pct) | Docker daemon |
|
||||
| Persistence | Stateful by default | Ephemeral by default |
|
||||
| Updates | apt/yum inside container | Replace container |
|
||||
| Networking | Proxmox managed | Docker managed |
|
||||
|
||||
## When to Use LXC
|
||||
|
||||
- **Long-running services** with traditional management (systemd, cron)
|
||||
- **Multi-process applications** that expect init system
|
||||
- **Legacy apps** not designed for containers
|
||||
- **Dev/test environments** mimicking full VMs
|
||||
- **Resource efficiency** when full VM isolation not needed
|
||||
- **Direct Proxmox management** (backup, snapshots, migration)
|
||||
|
||||
```bash
|
||||
# Create LXC
|
||||
pct create 200 local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst \
|
||||
--hostname mycontainer \
|
||||
--storage local-lvm \
|
||||
--rootfs local-lvm:8 \
|
||||
--cores 2 \
|
||||
--memory 2048 \
|
||||
--net0 name=eth0,bridge=vmbr0,ip=dhcp
|
||||
```
|
||||
|
||||
## When to Use Docker
|
||||
|
||||
- **Microservices** with single responsibility
|
||||
- **CI/CD pipelines** with reproducible builds
|
||||
- **Rapid deployment** and scaling
|
||||
- **Application isolation** within a host
|
||||
- **Compose stacks** with multi-container apps
|
||||
- **Ecosystem tooling** (registries, orchestration)
|
||||
|
||||
```yaml
|
||||
# docker-compose.yaml
|
||||
services:
|
||||
app:
|
||||
image: myapp:1.0
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
## Decision Matrix
|
||||
|
||||
| Scenario | Recommendation | Rationale |
|
||||
|----------|---------------|-----------|
|
||||
| Pi-hole | Docker on VM | Easy updates, compose ecosystem |
|
||||
| Database server | LXC or VM | Stateful, traditional management |
|
||||
| Web app microservice | Docker | Ephemeral, scalable |
|
||||
| Development environment | LXC | Full OS, multiple services |
|
||||
| CI runner | Docker on VM | Isolation, reproducibility |
|
||||
| Network appliance | LXC | Direct network access, systemd |
|
||||
| Home automation | Docker on VM | Compose stacks, easy backup |
|
||||
|
||||
## Hybrid Approach
|
||||
|
||||
Common pattern: **VM runs Docker**, managed by Proxmox.
|
||||
|
||||
```
|
||||
Proxmox Node
|
||||
├── VM: docker-host-1 (template 102)
|
||||
│ ├── Container: nginx
|
||||
│ ├── Container: app
|
||||
│ └── Container: redis
|
||||
├── VM: docker-host-2 (template 102)
|
||||
│ ├── Container: postgres
|
||||
│ └── Container: backup
|
||||
└── LXC: pihole (direct network)
|
||||
```
|
||||
|
||||
Benefits:
|
||||
- Proxmox handles VM-level backup/migration
|
||||
- Docker handles application deployment
|
||||
- Clear separation of concerns
|
||||
|
||||
## Docker in LXC (Not Recommended)
|
||||
|
||||
Running Docker inside LXC is possible but adds complexity:
|
||||
|
||||
### Requirements
|
||||
|
||||
1. Privileged container OR nested containers enabled
|
||||
2. AppArmor profile modifications
|
||||
3. Keyctl feature enabled
|
||||
|
||||
```bash
|
||||
# LXC config (Proxmox)
|
||||
lxc.apparmor.profile: unconfined
|
||||
lxc.cgroup.devices.allow: a
|
||||
lxc.cap.drop:
|
||||
features: keyctl=1,nesting=1
|
||||
```
|
||||
|
||||
### Issues
|
||||
|
||||
- Security: Reduced isolation
|
||||
- Compatibility: Some Docker features broken
|
||||
- Debugging: Two container layers
|
||||
- Backup: More complex
|
||||
|
||||
**Recommendation:** Use VM with Docker instead.
|
||||
|
||||
## Resource Comparison
|
||||
|
||||
For equivalent workload:
|
||||
|
||||
| Resource | VM + Docker | LXC | Docker in LXC |
|
||||
|----------|-------------|-----|---------------|
|
||||
| RAM overhead | ~500 MB | ~50 MB | ~100 MB |
|
||||
| Disk overhead | ~5 GB | ~500 MB | ~1 GB |
|
||||
| Boot time | 30-60s | 2-5s | 5-10s |
|
||||
| Isolation | Full | Shared kernel | Shared kernel |
|
||||
| Complexity | Low | Low | High |
|
||||
|
||||
## Migration Paths
|
||||
|
||||
### LXC to Docker
|
||||
|
||||
1. Export application config from LXC
|
||||
2. Create Dockerfile/compose
|
||||
3. Build image
|
||||
4. Deploy to Docker host
|
||||
5. Migrate data volumes
|
||||
|
||||
### Docker to LXC
|
||||
|
||||
1. Install service directly in LXC (apt/yum)
|
||||
2. Configure with systemd
|
||||
3. Migrate data
|
||||
4. Update Proxmox firewall rules
|
||||
212
skills/docker/references/troubleshooting.md
Normal file
212
skills/docker/references/troubleshooting.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# Docker Troubleshooting Reference
|
||||
|
||||
## Common Errors
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| Container exits immediately | Bad entrypoint, missing deps | Check logs, verify CMD |
|
||||
| Port already in use | Conflict with host/other container | `lsof -i :<port>`, change mapping |
|
||||
| Volume permission denied | UID mismatch | Check ownership, use named volumes |
|
||||
| Network not found | Network removed/not created | `docker network create` |
|
||||
| Image pull failed | Registry/auth/name issue | Check registry, credentials, name |
|
||||
| OOM killed | Exceeded memory limit | Increase limit or optimize app |
|
||||
| DNS resolution failed | Network config issue | Check DNS settings, network mode |
|
||||
| Health check failing | App not responding | Check command, increase timeout |
|
||||
|
||||
## Diagnostic Commands
|
||||
|
||||
### Container Status
|
||||
|
||||
```bash
|
||||
# List all containers (including stopped)
|
||||
docker ps -a
|
||||
|
||||
# Check exit code
|
||||
docker inspect <container> --format '{{.State.ExitCode}}'
|
||||
|
||||
# Check restart count
|
||||
docker inspect <container> --format '{{.RestartCount}}'
|
||||
```
|
||||
|
||||
### Logs
|
||||
|
||||
```bash
|
||||
# View logs
|
||||
docker logs <container>
|
||||
|
||||
# Follow logs
|
||||
docker logs -f <container>
|
||||
|
||||
# Last N lines
|
||||
docker logs --tail 100 <container>
|
||||
|
||||
# With timestamps
|
||||
docker logs -t <container>
|
||||
|
||||
# Since time
|
||||
docker logs --since 10m <container>
|
||||
```
|
||||
|
||||
### Resource Usage
|
||||
|
||||
```bash
|
||||
# Real-time stats
|
||||
docker stats
|
||||
|
||||
# Single container
|
||||
docker stats <container>
|
||||
|
||||
# Disk usage
|
||||
docker system df
|
||||
docker system df -v # Verbose
|
||||
```
|
||||
|
||||
### Container Details
|
||||
|
||||
```bash
|
||||
# Full inspection
|
||||
docker inspect <container>
|
||||
|
||||
# Specific fields
|
||||
docker inspect <container> --format '{{.State.Status}}'
|
||||
docker inspect <container> --format '{{json .NetworkSettings.Networks}}'
|
||||
docker inspect <container> --format '{{.Mounts}}'
|
||||
```
|
||||
|
||||
### Process and Network
|
||||
|
||||
```bash
|
||||
# Running processes
|
||||
docker top <container>
|
||||
|
||||
# Execute command
|
||||
docker exec <container> ps aux
|
||||
docker exec <container> netstat -tlnp
|
||||
|
||||
# Network connectivity
|
||||
docker exec <container> ping <host>
|
||||
docker exec <container> curl <url>
|
||||
docker exec <container> nslookup <hostname>
|
||||
```
|
||||
|
||||
## Troubleshooting Workflows
|
||||
|
||||
### Container Won't Start
|
||||
|
||||
1. Check logs: `docker logs <container>`
|
||||
2. Check exit code: `docker inspect <container> --format '{{.State.ExitCode}}'`
|
||||
3. Run interactively: `docker run -it <image> sh`
|
||||
4. Check entrypoint/cmd: `docker inspect <image> --format '{{.Config.Cmd}}'`
|
||||
|
||||
### Container Keeps Restarting
|
||||
|
||||
1. Check logs for errors
|
||||
2. Verify health check if configured
|
||||
3. Check resource limits (OOM)
|
||||
4. Test entrypoint manually
|
||||
|
||||
### Network Issues
|
||||
|
||||
1. Verify network exists: `docker network ls`
|
||||
2. Check container attached: `docker inspect <container> --format '{{.NetworkSettings.Networks}}'`
|
||||
3. Test DNS: `docker exec <container> nslookup <service>`
|
||||
4. Check port mapping: `docker port <container>`
|
||||
|
||||
### Volume Issues
|
||||
|
||||
1. Check mount: `docker inspect <container> --format '{{.Mounts}}'`
|
||||
2. Verify permissions inside: `docker exec <container> ls -la /path`
|
||||
3. Check host path exists (bind mounts)
|
||||
4. Try named volume instead
|
||||
|
||||
### Performance Issues
|
||||
|
||||
1. Check resource usage: `docker stats`
|
||||
2. Review limits: `docker inspect <container> --format '{{.HostConfig.Memory}}'`
|
||||
3. Check for resource contention
|
||||
4. Profile application inside container
|
||||
|
||||
## Cleanup
|
||||
|
||||
```bash
|
||||
# Remove stopped containers
|
||||
docker container prune
|
||||
|
||||
# Remove unused images
|
||||
docker image prune
|
||||
|
||||
# Remove unused volumes
|
||||
docker volume prune
|
||||
|
||||
# Remove unused networks
|
||||
docker network prune
|
||||
|
||||
# Remove everything unused
|
||||
docker system prune -a --volumes
|
||||
```
|
||||
|
||||
## Debugging Compose
|
||||
|
||||
```bash
|
||||
# Validate compose file
|
||||
docker compose config
|
||||
|
||||
# See what would run
|
||||
docker compose config --services
|
||||
|
||||
# Check why service isn't starting
|
||||
docker compose logs <service>
|
||||
|
||||
# Force recreate
|
||||
docker compose up -d --force-recreate
|
||||
|
||||
# Rebuild images
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
## Common Compose Issues
|
||||
|
||||
| Problem | Check |
|
||||
|---------|-------|
|
||||
| Service not starting | `docker compose logs <service>` |
|
||||
| depends_on not working | Service starts but app not ready (use healthcheck) |
|
||||
| Volume not persisting | Check volume name, not recreated |
|
||||
| Env vars not loading | Check .env file location, syntax |
|
||||
| Network errors | Check network names, external networks |
|
||||
|
||||
## Health Check Debugging
|
||||
|
||||
```bash
|
||||
# Check health status
|
||||
docker inspect <container> --format '{{.State.Health.Status}}'
|
||||
|
||||
# View health log
|
||||
docker inspect <container> --format '{{json .State.Health}}' | jq
|
||||
|
||||
# Test health command manually
|
||||
docker exec <container> <health-command>
|
||||
```
|
||||
|
||||
## Emergency Recovery
|
||||
|
||||
### Force Stop
|
||||
|
||||
```bash
|
||||
docker kill <container>
|
||||
```
|
||||
|
||||
### Remove Stuck Container
|
||||
|
||||
```bash
|
||||
docker rm -f <container>
|
||||
```
|
||||
|
||||
### Reset Docker
|
||||
|
||||
```bash
|
||||
# Restart Docker daemon
|
||||
sudo systemctl restart docker
|
||||
|
||||
# Or on macOS
|
||||
# Restart Docker Desktop
|
||||
```
|
||||
230
skills/docker/references/volumes.md
Normal file
230
skills/docker/references/volumes.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# Docker Volumes Reference
|
||||
|
||||
## Volume Types
|
||||
|
||||
### Named Volumes (Recommended)
|
||||
|
||||
Managed by Docker, stored in `/var/lib/docker/volumes/`.
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
db-data:
|
||||
|
||||
services:
|
||||
db:
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
```
|
||||
|
||||
Benefits:
|
||||
- Portable across hosts
|
||||
- Backup-friendly
|
||||
- No permission issues
|
||||
- Can use volume drivers (NFS, etc.)
|
||||
|
||||
### Bind Mounts
|
||||
|
||||
Direct host path mapping.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
volumes:
|
||||
- ./config:/etc/app/config:ro
|
||||
- /host/data:/container/data
|
||||
```
|
||||
|
||||
Benefits:
|
||||
- Direct file access from host
|
||||
- Development workflow (live reload)
|
||||
- Access to host files
|
||||
|
||||
Drawbacks:
|
||||
- Host-dependent paths
|
||||
- Permission issues possible
|
||||
- Less portable
|
||||
|
||||
### tmpfs Mounts
|
||||
|
||||
In-memory storage (Linux only).
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
tmpfs:
|
||||
- /tmp
|
||||
- /run:size=100m
|
||||
```
|
||||
|
||||
Benefits:
|
||||
- Fast (RAM-based)
|
||||
- Secure (not persisted)
|
||||
- Good for secrets, cache
|
||||
|
||||
## Volume Options
|
||||
|
||||
### Read-Only
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./config:/etc/app/config:ro
|
||||
```
|
||||
|
||||
### Bind Propagation
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./data
|
||||
target: /data
|
||||
bind:
|
||||
propagation: rslave
|
||||
```
|
||||
|
||||
### Volume Driver Options
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
nfs-data:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: nfs
|
||||
o: addr=192.168.1.100,rw
|
||||
device: ":/export/data"
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Database Data
|
||||
|
||||
```yaml
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_PASSWORD: secret
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
```
|
||||
|
||||
### Configuration Files
|
||||
|
||||
```yaml
|
||||
services:
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./html:/usr/share/nginx/html:ro
|
||||
```
|
||||
|
||||
### Shared Data Between Services
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
volumes:
|
||||
- shared:/data
|
||||
|
||||
worker:
|
||||
volumes:
|
||||
- shared:/data
|
||||
|
||||
volumes:
|
||||
shared:
|
||||
```
|
||||
|
||||
### Log Persistence
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
volumes:
|
||||
- logs:/var/log/app
|
||||
|
||||
volumes:
|
||||
logs:
|
||||
```
|
||||
|
||||
## Backup and Restore
|
||||
|
||||
### Backup Named Volume
|
||||
|
||||
```bash
|
||||
# Create backup
|
||||
docker run --rm \
|
||||
-v myvolume:/source:ro \
|
||||
-v $(pwd):/backup \
|
||||
alpine tar czf /backup/myvolume.tar.gz -C /source .
|
||||
|
||||
# Restore backup
|
||||
docker run --rm \
|
||||
-v myvolume:/target \
|
||||
-v $(pwd):/backup \
|
||||
alpine tar xzf /backup/myvolume.tar.gz -C /target
|
||||
```
|
||||
|
||||
### Copy Files from Volume
|
||||
|
||||
```bash
|
||||
docker cp <container>:/path/to/file ./local-file
|
||||
```
|
||||
|
||||
## Volume Management
|
||||
|
||||
```bash
|
||||
# List volumes
|
||||
docker volume ls
|
||||
|
||||
# Inspect volume
|
||||
docker volume inspect <volume>
|
||||
|
||||
# Remove unused volumes
|
||||
docker volume prune
|
||||
|
||||
# Remove specific volume
|
||||
docker volume rm <volume>
|
||||
|
||||
# Create volume manually
|
||||
docker volume create --name myvolume
|
||||
```
|
||||
|
||||
## Permissions
|
||||
|
||||
### Common Permission Issues
|
||||
|
||||
```bash
|
||||
# Check container user
|
||||
docker exec <container> id
|
||||
|
||||
# Check volume permissions
|
||||
docker exec <container> ls -la /data
|
||||
```
|
||||
|
||||
### Solutions
|
||||
|
||||
```yaml
|
||||
# Run as specific user
|
||||
services:
|
||||
app:
|
||||
user: "1000:1000"
|
||||
volumes:
|
||||
- ./data:/data
|
||||
```
|
||||
|
||||
Or fix host permissions:
|
||||
```bash
|
||||
chown -R 1000:1000 ./data
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use named volumes for data** - More portable than bind mounts
|
||||
2. **Read-only when possible** - Use `:ro` for config files
|
||||
3. **Separate concerns** - Different volumes for data, config, logs
|
||||
4. **Backup strategy** - Plan for volume backup/restore
|
||||
5. **Don't store in image** - Data should be in volumes, not image layers
|
||||
6. **Use .dockerignore** - Exclude data directories from build context
|
||||
Reference in New Issue
Block a user