Claude-skill-registry devspace
Guide for working with DevSpace, a Kubernetes development tool that automates building, deploying, and developing applications. Use when users need to create or modify devspace.yaml configuration files, build and deploy images to Kubernetes, manage multi-environment deployments with profiles, upload files to pods, or troubleshoot DevSpace workflows. Includes patterns for CI/CD integration, image tagging strategies, and secret management.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/devspace" ~/.claude/skills/majiayu000-claude-skill-registry-devspace && rm -rf "$T"
skills/data/devspace/SKILL.mdDevSpace
Overview
DevSpace is a Kubernetes development tool that automates the complete lifecycle of building container images, deploying to Kubernetes, and developing applications. This skill provides guidance for working with DevSpace non-interactively in automation scenarios, avoiding common pitfalls and following best practices.
Core Principle
Always work through
configuration rather than applying Kubernetes manifests directly. DevSpace manages the complete lifecycle including image building, tagging, and deployment coordination.devspace.yaml
When to Use This Skill
Use this skill when:
- Creating or modifying
configuration filesdevspace.yaml - Building and deploying container images to Kubernetes via DevSpace
- Setting up multi-environment deployments with DevSpace profiles
- Uploading files or creating secrets dynamically in Kubernetes pods
- Troubleshooting DevSpace-related image tag mismatches or deployment issues
- Integrating DevSpace into CI/CD pipelines
- Converting manual
workflows to DevSpace-managed workflowskubectl
Critical Understanding
The Image Tag Problem
Problem: DevSpace builds images with dynamic, random tags (e.g.,
abc123) and automatically replaces image references in manifests during deployment. Applying manifests manually with kubectl apply bypasses this replacement, causing deployments to fail with "image not found" errors.
Solution: Always use
devspace deploy or devspace build + devspace deploy --skip-build. Never manually kubectl apply files from the k8s folder.
DevSpace v2 Architecture
DevSpace v2 uses a pipeline-based approach with three main sections:
version: v2beta1 name: my-project # Define what images to build images: backend: image: myregistry/backend dockerfile: ./Dockerfile context: ./ # Define build and deploy pipelines pipelines: build: |- build_images --all deploy: |- build_images --all create_deployments --all # Define what to deploy deployments: backend: kubectl: manifests: - k8s/
Common DevSpace Workflows
1. Build and Deploy
# Build all images and deploy devspace deploy # Deploy without rebuilding (use existing images) devspace deploy --skip-build # Force rebuild all images devspace deploy --force-build # Deploy with specific profile devspace deploy -p production
2. Build Images Only
# Build all images devspace build # Build with specific tag devspace build --tag v1.0.0 # Build and tag multiple versions devspace build --tag v1.0.0 --tag latest
3. Non-Interactive Deployment
# Specify namespace explicitly devspace deploy -n my-namespace # Specify Kubernetes context devspace deploy --kube-context=my-cluster # Override variables devspace deploy --var REGISTRY=production.io --var TAG=v1.0.0 # Wait for deployment to be ready devspace deploy --wait --timeout=300
4. Configuration Validation
# Validate and show rendered configuration devspace print # Validate with specific profile devspace print -p production # List deployments devspace list deployments # List profiles devspace list profiles
5. Cleanup
# Remove all deployments devspace purge # Remove specific deployment devspace purge --deployments=backend
Configuration Patterns
Minimal Configuration
version: v2beta1 name: simple-app images: app: image: myregistry.io/app dockerfile: ./Dockerfile context: ./ deployments: app: kubectl: manifests: - k8s/ pipelines: deploy: |- build_images --all create_deployments --all
Production-Ready Configuration
version: v2beta1 name: production-app vars: - name: REGISTRY source: env default: dev.registry.io - name: VERSION value: $(git describe --always) - name: NAMESPACE source: env default: development images: backend: image: ${REGISTRY}/backend tags: - ${VERSION} - latest rebuildStrategy: default deployments: backend: namespace: ${NAMESPACE} kubectl: manifests: - k8s/deployment.yaml - k8s/service.yaml profiles: - name: production patches: - op: replace path: vars.REGISTRY.value value: prod.registry.io - op: add path: deployments.backend.kubectl.patches value: - op: replace path: spec.replicas value: 5 pipelines: deploy: |- build_images --all create_deployments --all verify: |- kubectl wait --for=condition=available deployment/backend \ -n ${NAMESPACE} --timeout=300s
Image Tagging Strategies
Static Tags
images: backend: image: myregistry/backend tags: - latest - v1.0.0
Dynamic Tags from Git
images: backend: image: myregistry/backend tags: - $(git describe --always) - latest
Runtime Variables for Image References
Use runtime variables in inline manifests to reference built images:
deployments: backend: kubectl: inlineManifest: |- apiVersion: apps/v1 kind: Deployment metadata: name: backend spec: template: spec: containers: - name: backend image: ${runtime.images.backend.image}:${runtime.images.backend.tag}
Available runtime variables:
- Full image name with tag${runtime.images.IMAGE_NAME.image}
- Just the tag${runtime.images.IMAGE_NAME.tag}
- Just the image name (no tag)${runtime.images.IMAGE_NAME.imageName}
Variables and Configuration
Variable Types
Static Variables:
vars: - name: REGISTRY value: myregistry.io
Environment Variables:
vars: - name: CI_COMMIT_SHA source: env - name: NAMESPACE source: env default: default
Command Variables:
vars: - name: GIT_COMMIT command: git args: ["rev-parse", "HEAD"] # Shorthand - name: GIT_BRANCH value: $(git rev-parse --abbrev-ref HEAD)
AVOID in Automation - Interactive Variables:
# DON'T USE THIS - prompts user vars: - name: MYSQL_VERSION question: "Which MySQL version?" options: ["5.7", "8.0"]
Predefined Variables
DevSpace provides built-in variables:
- Current namespace${DEVSPACE_NAMESPACE}
- Current kube context${DEVSPACE_CONTEXT}
- Active profile name${DEVSPACE_PROFILE}
- Random 6-char string${DEVSPACE_RANDOM}
- Current UNIX timestamp${DEVSPACE_TIMESTAMP}
Profiles for Multi-Environment Deployments
Profiles allow different configurations for dev, staging, production:
vars: - name: ENV source: env default: development profiles: - name: staging patches: - op: replace path: images.backend.image value: staging.registry.io/backend - op: add path: deployments.backend.kubectl.patches value: - op: replace path: spec.replicas value: 2 - name: production activation: - vars: ENV: production patches: - op: replace path: images.backend.image value: prod.registry.io/backend - op: add path: deployments.backend.kubectl.patches value: - op: replace path: spec.replicas value: 5 # Use with: devspace deploy -p production # Or auto-activate: ENV=production devspace deploy
Uploading Files to Pods
DevSpace provides hooks for uploading files to containers after deployment.
Option 1: Command-based Variables (Recommended)
vars: - name: CONFIG_PATH source: command command: | if [ -f ~/.config/app/config.json ]; then echo ~/.config/app/config.json elif [ -f ./config/app.json ]; then echo ./config/app.json else echo "config-not-found" fi hooks: - upload: localPath: ${CONFIG_PATH} containerPath: /app/config/config.json container: imageSelector: myregistry/app:tag events: ["after:deploy:my-deployment"] name: "upload-config"
Option 2: Config Expressions
hooks: - upload: localPath: $!(./scripts/find-config.sh) containerPath: /app/config/config.json container: labelSelector: app: my-app events: ["after:deploy:my-deployment"] name: "upload-config"
Multiple Files
vars: - name: APP_CONFIG source: command command: ./scripts/find-config.sh app - name: DB_CONFIG source: command command: ./scripts/find-config.sh database hooks: - upload: localPath: ${APP_CONFIG} containerPath: /app/config/app.json container: imageSelector: myregistry/app events: ["after:deploy:my-app"] name: "upload-app-config" - upload: localPath: ${DB_CONFIG} containerPath: /app/config/database.json container: imageSelector: myregistry/app events: ["after:deploy:my-app"] name: "upload-db-config"
Managing Secrets
Create Kubernetes secrets from environment variables using hooks.
Basic Secret Creation
vars: - name: API_KEY source: env - name: DATABASE_PASSWORD source: env hooks: # Validate required secrets - command: | if [ -z "$API_KEY" ] || [ -z "$DATABASE_PASSWORD" ]; then echo "ERROR: API_KEY and DATABASE_PASSWORD must be set" exit 1 fi events: ["before:deploy"] name: "validate-secrets" # Create secret - command: | kubectl create secret generic app-secrets \ --from-literal=api-key="${API_KEY}" \ --from-literal=db-password="${DATABASE_PASSWORD}" \ --dry-run=client -o yaml | kubectl apply -f - echo "Application secrets created" events: ["before:deploy"] name: "create-secrets" # Use in deployment deployments: app: helm: componentChart: true values: containers: - image: myregistry/app env: - name: API_KEY valueFrom: secretKeyRef: name: app-secrets key: api-key
Dynamic Secret Detection from .env
vars: - name: SECRET_DATA source: command command: | if [ -f .env ]; then cat .env | grep -v '^#' | grep -v '^$' | \ awk -F= '{printf "--from-literal=%s=%s ", $1, $2}' fi hooks: - command: | if [ ! -z "${SECRET_DATA}" ]; then kubectl create secret generic env-secrets \ ${SECRET_DATA} \ --dry-run=client -o yaml | kubectl apply -f - fi events: ["before:deploy"] name: "create-env-secrets"
Dev Mode Initialization and Credential Mounting
DevSpace dev mode provides interactive development workflows with file sync and terminal access. However, it introduces challenges when applications need credential files mounted into directories they also write to.
The Problem
Challenge 1: Kubernetes subPath Mount Limitations
- Applications often need credential files in directories where they create other files
- Kubernetes
mounts cannot mount files into directories where apps write other filessubPath - Example: Mounting
intocredentials.json
fails if the app creates~/.app/
or other files~/.app/cache/
Challenge 2: DevSpace Terminal Mode Bypasses Entrypoints
- DevSpace dev mode with
replaces container commandsterminal.enabled: true - Standard ENTRYPOINT and CMD are not executed
- Initialization logic in entrypoints does not run
The Solution: DevSpace Hooks with once: true
DevSpace hooks with
once: true are the official pattern for initialization tasks that run once per container lifecycle.
hooks: - name: setup-credentials events: ["after:deploy"] command: | if [ -f /tmp/secrets/credentials.json ]; then ln -sf /tmp/secrets/credentials.json /home/user/.app/credentials.json echo "✓ Credentials symlinked" fi container: labelSelector: app: my-app containerName: main namespace: my-namespace once: true # Only runs when container starts, not on every dev session wait: true timeout: 60
Why This Works:
- Hooks execute in the running container (not at build time)
ensures the hook only runs when the container first startsonce: true- Runs after deployment, so the container and volumes are ready
- Does not interfere with DevSpace's terminal/entrypoint handling
- Subsequent
sessions do not re-trigger the hookdevspace dev
Complete Example: Credential Mounting Pattern
# In deployment manifest (k8s/deployment.yaml): # Mount secret to separate directory (not the app's writable directory) volumeMounts: - name: app-credentials mountPath: /tmp/secrets readOnly: true volumes: - name: app-credentials secret: secretName: my-app-creds items: - key: credentials.json path: credentials.json # In devspace.yaml: hooks: - name: setup-app-credentials events: ["after:deploy"] command: | # Create target directory if needed mkdir -p ~/.app # Symlink credentials from read-only mount ln -sf /tmp/secrets/credentials.json ~/.app/credentials.json echo "✓ Application credentials configured" container: labelSelector: app: my-app containerName: main namespace: ${DEVSPACE_NAMESPACE} once: true wait: true timeout: 60
Multi-File Credential Setup
hooks: - name: setup-application-secrets events: ["after:deploy"] command: | # Create all required directories mkdir -p ~/.app ~/.config/app # Symlink multiple credential files ln -sf /tmp/secrets/credentials.json ~/.app/credentials.json ln -sf /tmp/secrets/api-key.txt ~/.config/app/api-key.txt ln -sf /tmp/secrets/client-secret.json ~/.app/client-secret.json # Set permissions if needed chmod 600 ~/.app/credentials.json echo "✓ All application credentials configured" container: labelSelector: app: my-app once: true wait: true
Anti-Patterns to Avoid
❌ Don't use dev.patches to force entrypoints (hacky):
# AVOID THIS dev: my-app: patches: - op: replace path: spec.template.spec.containers[0].command value: ["/bin/sh", "-c", "/setup.sh && bash"]
This interferes with DevSpace's terminal handling and creates confusion.
❌ Don't mount secrets with subPath into app-writable directories:
# AVOID THIS - will fail volumeMounts: - name: app-credentials mountPath: /home/user/.app/credentials.json subPath: credentials.json # Fails if app writes to ~/.app/
❌ Don't use init containers for dev mode initialization: Init containers run before the main container starts, not when dev sessions restart. Hooks with
once: true are the correct pattern.
❌ Don't put initialization in .bashrc:
# AVOID THIS in .bashrc ln -sf /tmp/secrets/credentials.json ~/.app/credentials.json
This runs every shell session, not just on container start, and does not work for non-interactive containers.
When to Use This Pattern
Use DevSpace hooks with
once: true for:
- Mounting credential files into writable directories
- One-time setup tasks in dev mode
- Symlinking files from read-only mounts
- Database initialization scripts
- Certificate/key setup that should persist across dev sessions
Container Selection Strategies
By label selector (recommended):
container: labelSelector: app: my-app component: backend
By image selector:
container: imageSelector: myregistry.io/my-app:${runtime.images.backend.tag}
By container name:
container: containerName: main namespace: ${DEVSPACE_NAMESPACE}
Debugging Initialization Hooks
Check if hook executed:
devspace logs --follow --container my-app
Verify symlinks inside container:
devspace enter ls -la ~/.app/ cat ~/.app/credentials.json
Re-run hook manually (for testing):
devspace enter ln -sf /tmp/secrets/credentials.json ~/.app/credentials.json
CI/CD Integration
DevSpace works identically in CI/CD as it does locally:
# GitHub Actions example - name: Deploy to Kubernetes run: | devspace use namespace ${{ env.NAMESPACE }} devspace use context ${{ env.KUBE_CONTEXT }} devspace deploy --wait --timeout=300 --var VERSION=${{ github.sha }} env: REGISTRY: ghcr.io/myorg VERSION: ${{ github.sha }} NAMESPACE: production
Key flags for CI/CD:
- Skip image building--skip-build
- Skip pushing images to registry--skip-push
- Force rebuild all images--force-build
- Force redeploy all deployments--force-deploy
- Wait for deployments to be ready--wait
- Timeout for wait operations (default 120s)--timeout
Common Pitfalls and Solutions
Pitfall 1: Dynamic Image Tags Not Matching
Error:
Image "myregistry/backend:abc123" not found
Cause: Manually applying manifests that reference images with DevSpace-generated tags.
Solution: Always use
devspace deploy instead of kubectl apply.
Pitfall 2: Image Built but Not Pushed
Error: Deployment fails because image doesn't exist in registry.
Solution:
# Ensure push happens devspace build # Automatically pushes # Or explicitly devspace deploy --skip-push=false # For local clusters only devspace deploy --skip-push-local-kube=true
Pitfall 3: Changes Not Reflected After Deploy
Cause: DevSpace skipped rebuild (no detected changes) or using cached image.
Solution:
# Force rebuild and redeploy devspace deploy --force-build --force-deploy # Or delete cache rm -rf .devspace/ devspace deploy
Pitfall 4: Interactive Prompts in Automation
Cause: Using variables with
question field.
Solution: Use
source: env with defaults or provide via command line:
devspace deploy --var REGISTRY=myregistry.io --var NAMESPACE=prod
Pitfall 5: Wrong Namespace/Cluster
Solution:
# Set explicitly devspace use context production-cluster devspace use namespace production # Or specify in command devspace deploy --kube-context=production-cluster -n production
Best Practices
1. Always Read devspace.yaml First
Before making changes:
cat devspace.yaml devspace list deployments devspace list profiles
2. Validate Configuration
# Validate configuration devspace print # Validate with specific profile devspace print -p production
3. Test in Safe Environment First
# Create test namespace kubectl create namespace test-${USER} # Deploy there devspace deploy -n test-${USER} # Verify devspace analyze -n test-${USER} # Cleanup devspace purge -n test-${USER} kubectl delete namespace test-${USER}
4. Use Version Control
# Check current state git diff devspace.yaml # Create backup cp devspace.yaml devspace.yaml.backup # Make changes and validate devspace print # Commit if good git add devspace.yaml git commit -m "feat: add new service deployment"
5. Document Changes
Add comments to devspace.yaml when making changes:
images: # Added 2024-01-15: New microservice for payment processing payments: image: myregistry.io/payments tags: ["${VERSION}"]
6. Handle Errors Gracefully
if devspace deploy; then echo "Deployment successful" devspace analyze else echo "Deployment failed" kubectl get pods -n ${NAMESPACE} kubectl describe pods -n ${NAMESPACE} exit 1 fi
Verification Checklist
After any change, verify:
- YAML syntax is valid (
)devspace print - Images are defined in
sectionimages - Deployments reference correct manifests
- Variables have defaults or are provided
- No interactive prompts (no
fields)question - Namespace and context are explicit
- Image tags are managed by DevSpace
- No manual
commandskubectl apply
Quick Command Reference
# Build devspace build # Build all images devspace build --tag v1.0.0 # Build with specific tag devspace build --force-build # Force rebuild # Deploy devspace deploy # Build and deploy devspace deploy --skip-build # Deploy only devspace deploy -p production # Deploy with profile devspace deploy --wait --timeout=300 # Wait for readiness # Pipelines devspace run-pipeline build # Run custom pipeline devspace run-pipeline deploy-backend # Run named pipeline # Configuration devspace print # Show rendered config devspace print -p production # With profile devspace list deployments # List deployments devspace list profiles # List profiles # Validation devspace analyze # Check namespace health devspace analyze --patient # Wait for pods to be ready # Cleanup devspace purge # Remove deployments devspace purge --deployments=backend # Remove specific deployment # Context management devspace use context my-cluster # Set cluster devspace use namespace production # Set namespace
Resources
This skill includes additional reference documentation:
references/
- Advanced DevSpace patterns including Helm deployments, Kustomize integration, deployment patches, and complex pipeline examplesadvanced_patterns.md
- Comprehensive troubleshooting guide for common DevSpace issues with diagnosis steps and solutionstroubleshooting.md
When to read references:
- When implementing Helm or Kustomize deployments
- When creating complex multi-service pipelines
- When encountering deployment issues or errors
- When setting up advanced CI/CD workflows
Note: Start with the main SKILL.md for most DevSpace tasks. Load reference files when deeper knowledge is needed for specific advanced scenarios.