Commit 418e37887be1
Changed files (3)
dots
.config
claude
skills
Docker
dots/.config/claude/skills/Docker/tools/DetectRuntime.sh
@@ -3,61 +3,140 @@
# shellcheck shell=bash
# DetectRuntime.sh - Detect Docker or Podman runtime and return information
-# Usage: DetectRuntime.sh [--json]
+# Usage: DetectRuntime.sh [--runtime docker|podman] [--json]
set -euo pipefail
+show_usage() {
+ cat <<EOF
+Usage: DetectRuntime.sh [OPTIONS]
+
+Detect container runtime (Docker or Podman) and return information.
+
+OPTIONS:
+ --runtime RUNTIME Force specific runtime (docker|podman)
+ --json Output in JSON format
+ -h, --help Show this help message
+
+EXAMPLES:
+ DetectRuntime.sh # Auto-detect available runtime
+ DetectRuntime.sh --runtime docker # Force Docker runtime
+ DetectRuntime.sh --json # Output as JSON
+EOF
+}
+
detect_runtime() {
+ local force_runtime=""
+ local output_json=false
+
+ # Parse arguments
+ while [[ $# -gt 0 ]]; do
+ case $1 in
+ --runtime)
+ force_runtime="$2"
+ shift 2
+ ;;
+ --json)
+ output_json=true
+ shift
+ ;;
+ -h|--help)
+ show_usage
+ exit 0
+ ;;
+ *)
+ echo "ERROR: Unknown option: $1" >&2
+ show_usage >&2
+ exit 1
+ ;;
+ esac
+ done
+
local runtime=""
local compose=""
local version=""
local rootless="false"
local socket=""
- # Check for Podman first (preference for rootless)
- if command -v podman &>/dev/null; then
- runtime="podman"
- version=$(podman --version | awk '{print $3}')
-
- # Check if running rootless
- if podman info --format '{{.Host.Security.Rootless}}' 2>/dev/null | grep -q "true"; then
- rootless="true"
- socket="unix://$XDG_RUNTIME_DIR/podman/podman.sock"
- else
- rootless="false"
- socket="unix:///run/podman/podman.sock"
- fi
-
- # Check for podman-compose
- if command -v podman-compose &>/dev/null; then
- compose="podman-compose"
- elif command -v docker-compose &>/dev/null; then
- compose="docker-compose"
- else
- compose="none"
- fi
- # Fall back to Docker
- elif command -v docker &>/dev/null; then
- runtime="docker"
- version=$(docker --version | awk '{print $3}' | tr -d ',')
- rootless="false"
- socket="unix:///var/run/docker.sock"
-
- # Check for docker-compose
- if docker compose version &>/dev/null; then
- compose="docker-compose-plugin"
- elif command -v docker-compose &>/dev/null; then
- compose="docker-compose"
- else
- compose="none"
- fi
- else
- echo "ERROR: Neither Docker nor Podman found in PATH" >&2
- exit 1
+ # If specific runtime requested, check only that one
+ if [[ -n "$force_runtime" ]]; then
+ case "$force_runtime" in
+ podman)
+ if ! command -v podman &>/dev/null; then
+ echo "ERROR: Podman requested but not found in PATH" >&2
+ exit 1
+ fi
+ runtime="podman"
+ ;;
+ docker)
+ if ! command -v docker &>/dev/null; then
+ echo "ERROR: Docker requested but not found in PATH" >&2
+ exit 1
+ fi
+ runtime="docker"
+ ;;
+ *)
+ echo "ERROR: Invalid runtime '$force_runtime'. Must be 'docker' or 'podman'" >&2
+ exit 1
+ ;;
+ esac
fi
+ # Auto-detect if no runtime forced
+ if [[ -z "$runtime" ]]; then
+ # Check for Podman first (preference for rootless)
+ if command -v podman &>/dev/null; then
+ runtime="podman"
+ # Fall back to Docker
+ elif command -v docker &>/dev/null; then
+ runtime="docker"
+ else
+ echo "ERROR: Neither Docker nor Podman found in PATH" >&2
+ exit 1
+ fi
+ fi
+
+ # Get runtime-specific information
+ case "$runtime" in
+ podman)
+ version=$(podman --version | awk '{print $3}')
+
+ # Check if running rootless
+ if podman info --format '{{.Host.Security.Rootless}}' 2>/dev/null | grep -q "true"; then
+ rootless="true"
+ socket="unix://$XDG_RUNTIME_DIR/podman/podman.sock"
+ else
+ rootless="false"
+ socket="unix:///run/podman/podman.sock"
+ fi
+
+ # Check for podman-compose
+ if command -v podman-compose &>/dev/null; then
+ compose="podman-compose"
+ elif command -v docker-compose &>/dev/null; then
+ compose="docker-compose"
+ else
+ compose="none"
+ fi
+ ;;
+ docker)
+ version=$(docker --version | awk '{print $3}' | tr -d ',')
+ rootless="false"
+ socket="unix:///var/run/docker.sock"
+
+ # Check for docker-compose
+ if docker compose version &>/dev/null 2>&1; then
+ compose="docker-compose-plugin"
+ elif command -v docker-compose &>/dev/null; then
+ compose="docker-compose"
+ else
+ compose="none"
+ fi
+ ;;
+ esac
+
# Output format
- if [[ "${1:-}" == "--json" ]]; then
+ if [[ "$output_json" == true ]]; then
jq -n \
--arg runtime "$runtime" \
--arg version "$version" \
dots/.config/claude/skills/Docker/workflows/BuildImage.md
@@ -5,7 +5,9 @@ Build container images with best practices for Docker or Podman.
## Process
1. **Detect Runtime**
- - Run `DetectRuntime.sh` to determine Docker/Podman
+ - Parse user prompt for explicit runtime mention ("use Docker", "with Podman")
+ - If explicit runtime mentioned: Use `DetectRuntime.sh --runtime <docker|podman>`
+ - If auto-detect: Run `DetectRuntime.sh` (prefers Podman, falls back to Docker)
- Identify available build tools (buildx, buildah)
2. **Analyze Context**
dots/.config/claude/skills/Docker/SKILL.md
@@ -51,6 +51,27 @@ This skill works seamlessly with both runtimes:
The skill automatically detects which runtime is available and adjusts commands accordingly.
+## Runtime Selection
+
+By default, the skill auto-detects available runtimes (prefers Podman for rootless). You can explicitly choose a runtime in your prompts:
+
+**Explicit mentions** (natural language):
+- "**Use Docker to** build this image"
+- "Build this image **with Podman**"
+- "**Using Docker**, start the container"
+- "**With Podman**, create a volume"
+
+When you mention a specific runtime, the skill will use that runtime exclusively for the operation.
+
+**Auto-detection behavior**:
+1. Checks for Podman first (rootless preference)
+2. Falls back to Docker if Podman not found
+3. Errors if neither is available
+
+**When both are installed**: You have both runtimes available, so you can choose based on your needs:
+- **Podman**: Rootless, daemonless, pods support
+- **Docker**: Mature ecosystem, wider adoption, better tooling
+
## Examples
**Example 1: Build a container image**
@@ -87,6 +108,19 @@ User: "Build this image for both AMD64 and ARM64"
→ Pushes to registry with manifest
```
+**Example 5: Explicit runtime selection**
+```
+User: "Use Docker to build this image"
+→ Invokes BuildImage workflow
+→ Forces Docker runtime (--runtime docker)
+→ Uses Docker-specific features if needed
+
+User: "With Podman, start a rootless container"
+→ Invokes ManageContainers workflow
+→ Forces Podman runtime (--runtime podman)
+→ Uses Podman rootless mode
+```
+
## Best Practices
### Dockerfile