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.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add aibot88/sec_skill_store --skill devspace --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Devspace?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/aibot88-devspace)More formats (shields.io, HTML) on the badges page.
---
name: devspace
description: 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.
---
# DevSpace
## 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 `devspace.yaml` configuration rather than applying Kubernetes manifests directly.** DevSpace manages the complete lifecycle including image building, tagging, and deployment coordination.
## When to Use This Skill
Use this skill when:
- Creating or modifying `devspace.yaml` configuration files
- 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 `kubectl` workflows to DevSpace-managed workflows
## 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:
```yaml
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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# Remove all deployments
devspace purge
# Remove specific deployment
devspace purge --deployments=backend
```
## Configuration Patterns
### Minimal Configuration
```yaml
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
```yaml
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
```yaml
images:
backend:
image: myregistry/backend
tags:
- latest
- v1.0.0
```
### Dynamic Tags from Git
```yaml
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:
```yaml
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:
- `${runtime.images.IMAGE_NAME.image}` - Full image name with tag
- `${runtime.images.IMAGE_NAME.tag}` - Just the tag
- `${runtime.images.IMAGE_NAME.imageName}` - Just the image name (no tag)
## Variables and Configuration
### Variable Types
**Static Variables:**
```yaml
vars:
- name: REGISTRY
value: myregistry.io
```
**Environment Variables:**
```yaml
vars:
- name: CI_COMMIT_SHA
source: env
- name: NAMESPACE
source: env
default: default
```
**Command Variables:**
```yaml
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:**
```yaml
# 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:
- `${DEVSPACE_NAMESPACE}` - Current namespace
- `${DEVSPACE_CONTEXT}` - Current kube context
- `${DEVSPACE_PROFILE}` - Active profile name
- `${DEVSPACE_RANDOM}` - Random 6-char string
- `${DEVSPACE_TIMESTAMP}` - Current UNIX timestamp
## Profiles for Multi-Environment Deployments
Profiles allow different configurations for dev, staging, production:
```yaml
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)
```yaml
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
```yaml
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
```yaml
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
```yaml
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
```yaml
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 `subPath` mounts cannot mount files into directories where apps write other files
- Example: Mounting `credentials.json` into `~/.app/` fails if the app creates `~/.app/cache/` or other files
**Challenge 2: DevSpace Terminal Mode Bypasses Entrypoints**
- DevSpace dev mode with `terminal.enabled: true` replaces container commands
- 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.
```yaml
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)
- `once: true` ensures the hook only runs when the container first starts
- Runs after deployment, so the container and volumes are ready
- Does not interfere with DevSpace's terminal/entrypoint handling
- Subsequent `devspace dev` sessions do not re-trigger the hook
### Complete Example: Credential Mounting Pattern
```yaml
# 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
```yaml
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):**
```yaml
# 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:**
```yaml
# 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:**
```bash
# 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):**
```yaml
container:
labelSelector:
app: my-app
component: backend
```
**By image selector:**
```yaml
container:
imageSelector: myregistry.io/my-app:${runtime.images.backend.tag}
```
**By container name:**
```yaml
container:
containerName: main
namespace: ${DEVSPACE_NAMESPACE}
```
### Debugging Initialization Hooks
**Check if hook executed:**
```bash
devspace logs --follow --container my-app
```
**Verify symlinks inside container:**
```bash
devspace enter
ls -la ~/.app/
cat ~/.app/credentials.json
```
**Re-run hook manually (for testing):**
```bash
devspace enter
ln -sf /tmp/secrets/credentials.json ~/.app/credentials.json
```
## CI/CD Integration
DevSpace works identically in CI/CD as it does locally:
```yaml
# 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-build` - Skip image building
- `--skip-push` - Skip pushing images to registry
- `--force-build` - Force rebuild all images
- `--force-deploy` - Force redeploy all deployments
- `--wait` - Wait for deployments to be ready
- `--timeout` - Timeout for wait operations (default 120s)
## 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:**
```bash
# 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:**
```bash
# 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:
```bash
devspace deploy --var REGISTRY=myregistry.io --var NAMESPACE=prod
```
### Pitfall 5: Wrong Namespace/Cluster
**Solution:**
```bash
# 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:
```bash
cat devspace.yaml
devspace list deployments
devspace list profiles
```
### 2. Validate Configuration
```bash
# Validate configuration
devspace print
# Validate with specific profile
devspace print -p production
```
### 3. Test in Safe Environment First
```bash
# 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
```bash
# 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:
```yaml
images:
# Added 2024-01-15: New microservice for payment processing
payments:
image: myregistry.io/payments
tags: ["${VERSION}"]
```
### 6. Handle Errors Gracefully
```bash
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 `images` section
- [ ] Deployments reference correct manifests
- [ ] Variables have defaults or are provided
- [ ] No interactive prompts (no `question` fields)
- [ ] Namespace and context are explicit
- [ ] Image tags are managed by DevSpace
- [ ] No manual `kubectl apply` commands
## Quick Command Reference
```bash
# 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_patterns.md` - Advanced DevSpace patterns including Helm deployments, Kustomize integration, deployment patches, and complex pipeline examples
- `troubleshooting.md` - Comprehensive troubleshooting guide for common DevSpace issues with diagnosis steps and solutions
**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.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!