Skip to content
SHC Docs

shc job

Jobs in SHC execute commands at specific points during stack lifecycle operations or on-demand. The shc job commands let you list, run, and monitor jobs.

Jobs execute commands with full access to stack mounts and networking. They are used when operations need to interact with running services or access live data.

ContextDescriptionUse Case
serviceExecute in an existing running serviceCHECKPOINT on running DB
containerSpin up ephemeral container with stack accessMigration scripts, data jobs
httpMake HTTP request to a serviceHealth checks, API calls
AspectJobsConverters
When runsWhile stack is runningAfter snapshot, stack resumed
NetworkFull stack network accessnetwork_mode: none (isolated)
MountsLive volumes (read/write)Snapshot (read-only) + output dir
PurposeInteract with servicesTransform data into backup format
Used byHooks, restore, integrationsBackups only

List jobs defined for a stack:

Terminal window
# List all jobs for a stack (positional stack name)
shc job myapp
# List jobs with details
shc job myapp --verbose
# Filter by hook type
shc job myapp --hook post_install
Terminal window
$ shc job postgres
Jobs for postgres:
Name Context Hook Description
────────────────────────────────────────────────────────
flush_checkpoint service pre_backup Flush DB checkpoint
create_database service integration Create user database
migrate container post_install Run database migrations
health_check http - Check service health

Run a job manually:

Terminal window
# Run a specific job
shc job run --stack myapp --job migrate
# Run with environment variables
shc job run --stack myapp --job migrate --env FORCE=true
# Run with timeout override
shc job run --stack myapp --job long_task --timeout 600
# Dry run (show what would execute)
shc job run --stack myapp --job migrate --dry-run
Terminal window
$ shc job run --stack postgres --job flush_checkpoint
Running job: flush_checkpoint
Context: service (postgres)
Command: psql -c "CHECKPOINT"
Output:
CHECKPOINT
Job completed successfully (0.3s)

Show status of running or recent jobs:

Terminal window
# Show recent job runs
shc job status --stack myapp
# Show specific job run
shc job status --stack myapp --job migrate
# Show detailed output
shc job status --stack myapp --job migrate --verbose
Terminal window
$ shc job status --stack myapp
Recent jobs for myapp:
Job Started Duration Status
────────────────────────────────────────────────
migrate 2025-01-15 12:30:00 2.3s success
migrate 2025-01-14 10:15:00 2.1s success
seed 2025-01-14 10:15:05 0.8s success

Jobs are defined in *.job.yaml files within the app directory:

Runs command inside an existing running container:

flush_checkpoint.job.yaml
name: flush_checkpoint
context: service
service: postgres
command: psql -c "CHECKPOINT"
timeout: 60

Properties:

PropertyTypeDescription
servicestringService name from compose (required)
commandstringCommand to execute (required)
userstringRun as specific user
working_dirstringWorking directory inside container

Spins up an ephemeral container with stack network access:

migrate.job.yaml
name: migrate
context: container
image: myapp:latest
command: python manage.py migrate --noinput
volumes:
- app_data:/app/data
environment:
DATABASE_URL: "{{ integrations.postgres.socket.url }}"
timeout: 300

Properties:

PropertyTypeDescription
imagestringDocker image to use (required)
commandstringCommand to execute (required)
volumeslist[string]Volume mounts
environmentdictEnvironment variables
networkslist[string]Networks to attach (defaults to stack networks)
userstringRun as specific user
working_dirstringWorking directory
labelsdictContainer labels

Makes HTTP request to a service (no container created):

health_check.job.yaml
name: health_check
context: http
url: http://web:8080/health
method: GET
timeout: 30
notify_slack.job.yaml
name: notify_slack
context: http
url: "{{ vars.slack_webhook }}"
method: POST
headers:
Content-Type: application/json
body:
text: "Deployment of {{ stack }} complete"
retry: 3

Properties:

PropertyTypeDefaultDescription
urlstringURL to request (required)
methodstringGETHTTP method
headersdictRequest headers
bodystring/dict/listRequest body (JSON)
retryinteger0Retry attempts

All job contexts share these properties:

PropertyTypeDefaultDescription
namestringJob name (required)
contextstringservice, container, http
timeoutinteger300Timeout in seconds
retryinteger0Number of retries (with exponential backoff)

Jobs are commonly referenced in lifecycle hooks:

app.yaml
hooks:
post_install:
- migrate
- seed_data
post_upgrade:
- migrate
pre_backup:
- flush_checkpoint
post_restore:
- rebuild_indexes
HookWhenStack StateUse Case
pre_installBefore deploymentNot runningValidation
post_installAfter containers healthyRunningMigrations, initial setup
pre_upgradeBefore upgrade startsRunningPre-flight checks
post_upgradeAfter upgrade completesRunningSchema migrations
pre_uninstallBefore containers stopRunningGraceful shutdown
post_uninstallAfter containers removedNot runningExternal cleanup
pre_backupBefore snapshotRunning (paused)Quiesce writes
post_backupAfter backup completesRunningResume operations
pre_restoreBefore restore startsStoppedValidate backup
post_restoreAfter restore completesRunningRebuild indexes
migrate.job.yaml
name: migrate
context: service
service: web
command: python manage.py migrate --noinput
app.yaml
hooks:
post_install:
- migrate
post_upgrade:
- migrate
checkpoint.job.yaml
name: checkpoint
context: service
service: postgres
command: psql -c "CHECKPOINT"
app.yaml
hooks:
pre_backup:
- checkpoint
notify.job.yaml
name: notify
context: http
url: "{{ vars.webhook_url }}"
method: POST
headers:
Content-Type: application/json
body:
event: "deployment_complete"
stack: "{{ stack }}"
environment: "{{ environment }}"
retry: 3
seed.job.yaml
name: seed
context: container
image: myapp:latest
command: python manage.py seed_data
volumes:
- seed_data:/app/seeds:ro
environment:
DATABASE_URL: "{{ integrations.postgres.socket.url }}"

If a job fails, SHC logs a warning and continues to the next job. Use retry for jobs with transient failures:

name: notify_webhook
context: http
url: "{{ vars.webhook_url }}"
retry: 3 # Retry up to 3 times with exponential backoff

For critical jobs that must succeed, the operation will fail if the job fails (e.g., pre_install hooks failing will abort installation).