hasura-docker-cli
Hasura Docker CLI Skill
This skill guides you through using Hasura CLI in a self-hosted Docker Compose environment where the Hasura CLI runs inside a container.
When This Skill Activates
Claude automatically uses this skill when you:
- Need to run Hasura CLI commands in self-hosted Docker environment
- Want to access Hasura console for schema changes
- Are managing database migrations via Hasura CLI
- Need to apply or rollback migrations
- Want to export or apply Hasura metadata
- Are troubleshooting Hasura configuration issues
Self-Hosted Docker Architecture
In a self-hosted setup, the Hasura CLI runs inside a Docker container rather than on your host machine.
Self-Hosted Docker Stack:
┌──────────────────────────────────────────────────┐
│ console service (hasura/graphql-engine) │
│ • Runs hasura-cli console command │
│ • Port 9695: Hasura Console UI │
│ • Has hasura-cli installed │
│ • Working dir: /app (mounted nhost/ directory) │
└──────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ graphql service (hasura/graphql-engine) │
│ • Main Hasura GraphQL Engine │
│ • Port 8080: GraphQL API │
└──────────────────────────────────────────────────┘
CRITICAL: Use Docker Exec for CLI Commands
❌ TRADITIONAL HASURA CLI DOES NOT WORK DIRECTLY:
# ❌ These fail because CLI is inside container
hasura-cli migrate status
hasura-cli metadata export
✅ INSTEAD, USE DOCKER EXEC:
# ✅ Correct way to access Hasura CLI in Docker
docker exec {console-container-name} hasura-cli [command]
# Example:
docker exec backend-console-1 hasura-cli version
docker exec backend-console-1 hasura-cli migrate status
Finding Your Console Container Name
# List all containers to find the console
docker ps | grep console
# Common naming patterns:
# - backend-console-1
# - nhost-console-1
# - hasura-console-1
# - {project}-console-1
Hasura Console Access
Method 1: Web Browser (Recommended)
The Hasura Console is typically already running when your Docker stack is up:
# Console URL (configure in docker-compose.yaml)
http://localhost:9695
# Or via environment variable:
https://${CONSOLE_URL}
Docker Compose Configuration:
services:
console:
image: hasura/graphql-engine:{version}
entrypoint: ["hasura-cli"]
command: ["console", "--no-browser", "--endpoint=http://graphql:8080"]
ports:
- "9695:9695"
volumes:
- ./nhost:/app # Mount nhost directory
working_dir: /app
This means:
- ✅ Console is always running when Docker stack is up
- ✅ Automatically tracks schema changes as migrations
- ✅ Accessible via browser at port 9695
Method 2: Direct CLI Access
# Access the console container shell
docker exec -it {console-container-name} bash
# Inside container, run hasura-cli commands directly
hasura-cli migrate status
hasura-cli metadata export
Common Hasura CLI Commands
All commands must be prefixed with docker exec {container-name}:
Migration Management
# Set your container name as environment variable for convenience
export CONSOLE_CONTAINER={your-console-container-name}
export HASURA_ADMIN_SECRET={your-admin-secret}
# Check migration status
docker exec $CONSOLE_CONTAINER hasura-cli migrate status \
--database-name default \
--endpoint http://graphql:8080 \
--admin-secret $HASURA_ADMIN_SECRET
# Apply pending migrations
docker exec $CONSOLE_CONTAINER hasura-cli migrate apply \
--database-name default \
--endpoint http://graphql:8080 \
--admin-secret $HASURA_ADMIN_SECRET
# Create new migration
docker exec $CONSOLE_CONTAINER hasura-cli migrate create "add_users_table" \
--database-name default \
--endpoint http://graphql:8080 \
--admin-secret $HASURA_ADMIN_SECRET
# Rollback last migration
docker exec $CONSOLE_CONTAINER hasura-cli migrate apply \
--down 1 \
--database-name default \
--endpoint http://graphql:8080 \
--admin-secret $HASURA_ADMIN_SECRET
# Rollback to specific version
docker exec $CONSOLE_CONTAINER hasura-cli migrate apply \
--version {timestamp} \
--database-name default \
--endpoint http://graphql:8080 \
--admin-secret $HASURA_ADMIN_SECRET
Metadata Management
# Export metadata
docker exec $CONSOLE_CONTAINER hasura-cli metadata export \
--endpoint http://graphql:8080 \
--admin-secret $HASURA_ADMIN_SECRET
# Apply metadata
docker exec $CONSOLE_CONTAINER hasura-cli metadata apply \
--endpoint http://graphql:8080 \
--admin-secret $HASURA_ADMIN_SECRET
# Reload metadata (refresh GraphQL schema)
docker exec $CONSOLE_CONTAINER hasura-cli metadata reload \
--endpoint http://graphql:8080 \
--admin-secret $HASURA_ADMIN_SECRET
# Check metadata inconsistencies
docker exec $CONSOLE_CONTAINER hasura-cli metadata inconsistency list \
--endpoint http://graphql:8080 \
--admin-secret $HASURA_ADMIN_SECRET
Seed Data Management
# Apply seed data
docker exec $CONSOLE_CONTAINER hasura-cli seed apply \
--database-name default \
--endpoint http://graphql:8080 \
--admin-secret $HASURA_ADMIN_SECRET
# Apply specific seed file
docker exec $CONSOLE_CONTAINER hasura-cli seed apply \
--file seeds/default/1234_initial_data.sql \
--database-name default \
--endpoint http://graphql:8080 \
--admin-secret $HASURA_ADMIN_SECRET
Environment Variables
The Hasura CLI typically needs these environment variables:
# Inside the console container (configured in docker-compose.yaml)
HASURA_GRAPHQL_ADMIN_SECRET=${GRAPHQL_ADMIN_SECRET}
HASURA_GRAPHQL_DATABASE_URL=postgres://${PGUSER}:${PGPASSWORD}@${PGHOST}:${PGPORT}/${PGDATABASE}
Working Directory
The console container should mount your project directory:
# In docker-compose.yaml
volumes:
- ./nhost:/app
working_dir: /app
This means the CLI can find:
/app/config.yaml- Hasura config/app/migrations/- Migration files/app/metadata/- Metadata files/app/seeds/- Seed files
Simplified Helper Aliases (Optional)
Create shell aliases for convenience:
# Add to ~/.bashrc or ~/.zshrc
export CONSOLE_CONTAINER={your-container-name}
export HASURA_ADMIN_SECRET=${GRAPHQL_ADMIN_SECRET}
alias hasura='docker exec $CONSOLE_CONTAINER hasura-cli'
# Then use like:
hasura migrate status --database-name default
hasura metadata export
Complete Migration Workflow
Scenario: Add a new database table
# 1. Open Hasura Console in browser
open http://localhost:9695
# 2. Make schema changes via UI
# - Go to DATA tab
# - Click "Create Table"
# - Define columns, constraints, relationships
# - Save
# 3. Console automatically creates migration files in:
# nhost/migrations/default/{timestamp}_{operation}/
# ├── up.sql (forward migration)
# └── down.sql (rollback migration)
# 4. Check migration status
docker exec $CONSOLE_CONTAINER hasura-cli migrate status \
--database-name default \
--endpoint http://graphql:8080
# 5. If needed, manually apply migrations
docker exec $CONSOLE_CONTAINER hasura-cli migrate apply \
--database-name default \
--endpoint http://graphql:8080
# 6. Export metadata to sync permissions
docker exec $CONSOLE_CONTAINER hasura-cli metadata export \
--endpoint http://graphql:8080
# 7. Reload Hasura metadata
docker exec $CONSOLE_CONTAINER hasura-cli metadata reload \
--endpoint http://graphql:8080
# 8. Commit migration files
git add nhost/migrations/
git add nhost/metadata/
git commit -m "feat(db): add users table"
Troubleshooting
Issue: Cannot connect to Hasura
Symptoms:
docker execcommands fail- "No such container" error
Solutions:
# 1. Check if console container is running
docker ps | grep console
# 2. If not running, start Docker stack
docker compose up -d
# 3. Wait for services to be healthy
docker compose ps
# 4. Check console logs
docker logs {console-container-name}
Issue: Admin secret authentication failed
Symptoms:
- "admin secret not provided" error
- "access denied" messages
Solutions:
# 1. Check admin secret in .env file
grep HASURA_ADMIN_SECRET .env
# 2. Pass admin secret explicitly
docker exec $CONSOLE_CONTAINER hasura-cli migrate status \
--admin-secret "your-actual-secret-here" \
--database-name default
# 3. Or set environment variable
export HASURA_GRAPHQL_ADMIN_SECRET=$(grep HASURA_ADMIN_SECRET .env | cut -d '=' -f2)
Issue: Migration files not found
Symptoms:
- "no migrations found" error
- Migration commands don't see files
Solutions:
# 1. Verify migration files exist
ls -la nhost/migrations/default/
# 2. Check docker volume mount
docker inspect {console-container-name} | grep -A 10 Mounts
# 3. Verify working directory in container
docker exec $CONSOLE_CONTAINER pwd
# Should output: /app
# 4. List files in container
docker exec $CONSOLE_CONTAINER ls -la /app/migrations/default/
Issue: Console not accessible in browser
Symptoms:
- Cannot access http://localhost:9695
- Console URL returns 404 or connection refused
Solutions:
# 1. Check if console service is running
docker ps | grep console
# 2. Check console service health
docker compose ps console
# 3. Check console logs for errors
docker logs {console-container-name} -f
# 4. Verify port mapping
docker port {console-container-name}
# 5. Try accessing via environment URL
echo "https://${CONSOLE_URL}"
Key Differences from Managed Services
| Feature | Managed (Nhost Cloud/Hasura Cloud) | Self-Hosted Docker |
|---|---|---|
| Console access | nhost dev hasura |
Browser: http://localhost:9695 |
| CLI commands | hasura-cli [cmd] |
docker exec {container} hasura-cli |
| Migration apply | Auto-applied | Manual via CLI or auto on startup |
| Console startup | On-demand | Always running with Docker stack |
| Endpoint | Managed by service | http://graphql:8080 (internal) |
| Admin secret | Auto-configured | From .env file |
| Working directory | Auto-detected | /app in container |
Best Practices
- Use Console UI for schema changes - Automatically creates migration files
- Commit migration files immediately - Track schema changes in version control
- Test migrations in development first - Before applying to production
- Always export metadata after schema changes - Keep metadata in sync
- Use explicit database-name flag -
--database-name defaultfor clarity - Keep admin secret secure - Never commit to version control
- Back up database before rollbacks - Prevent data loss
Quick Reference
| Task | Command |
|---|---|
| Check CLI version | docker exec $CONSOLE_CONTAINER hasura-cli version |
| Migration status | docker exec $CONSOLE_CONTAINER hasura-cli migrate status --database-name default |
| Apply migrations | docker exec $CONSOLE_CONTAINER hasura-cli migrate apply --database-name default |
| Export metadata | docker exec $CONSOLE_CONTAINER hasura-cli metadata export |
| Reload metadata | docker exec $CONSOLE_CONTAINER hasura-cli metadata reload |
| Access console | Open browser to http://localhost:9695 or https://${CONSOLE_URL} |
Remember: In self-hosted Docker environments, the Hasura CLI runs inside a container. Always use docker exec {container-name} hasura-cli to run CLI commands, and access the console via web browser.