This guide provides technical details about how authentication works in the Claude Agent SDK Docker containers.
For setup instructions, see the README Quick Start.
- Long-lived OAuth Tokens (
sk-ant-oat01-*) 1-year expiration - Interactive Browser Authentication - Session-based OAuth. Requires
docker execinto container to perform manual CLI auth flow. Persists across container restarts, but shorter period to expiration - Anthropic API Keys (
sk-ant-api03-*) - Should work by default. Direct API access (not tested as of July 2025)⚠️ If set, likely overrides Pro/Max usage and uses API credits first
When a container starts, the entrypoint script (docker-entrypoint.sh) performs the following:
- Checks for OAuth Token: If
CLAUDE_CODE_OAUTH_TOKENis set, it automatically configures authentication - Creates Credential Files:
~/.claude/.credentials.json- Contains the authentication token~/.claude.json- Contains session configuration and user metadata
- Preserves Existing Sessions: If
.claude.jsonalready exists (from a previous session), it's preserved
The containers use Docker volumes to persist authentication data for all 3 methods:
volumes:
- claude-auth:/home/claude/.claude # Persists CLI authenticationThis ensures that:
- Manual authentication sessions persist across container restarts
- You don't need to re-authenticate after stopping/starting containers
- Multiple containers can share the same authentication volume
The authentication system creates two key files:
-
~/.claude/.credentials.json- Stores the actual authentication token:{ "claudeAiOauth": { "accessToken": "sk-ant-oat01-...", "refreshToken": "sk-ant-oat01-...", "expiresAt": "2099-12-31T23:59:59.999Z", "scopes": ["read", "write"], "subscriptionType": "pro" } } -
~/.claude.json- Stores session configuration and metadata:{ "oauthAccount": { "accountUuid": "...", "emailAddress": "docker@claude-sdk.local", "organizationName": "Claude SDK Docker" }, "hasCompletedOnboarding": true, "projects": { "/app": { "allowedTools": [], "hasTrustDialogAccepted": true } } }
- Check token format: Ensure your token starts with
sk-ant-oat01- - Verify environment variable: Run
docker-compose configto check if the token is being passed - Check container logs:
Look for "OAuth authentication setup complete"
docker-compose logs typescript
-
Verify volume mount: Check that the
claude-authvolume is properly mounted:docker volume ls | grep claude-auth -
Check file permissions: The claude user should own the auth files:
docker-compose exec typescript ls -la ~/.claude/
If the CLI hangs during interactive auth:
- Make sure you're running with TTY:
docker-compose exec -it typescript bash - Complete the browser flow on your local machine
- The CLI should automatically detect when authentication is complete
By default, containers share the same authentication volume, allowing you to authenticate once and use the same credentials across TypeScript and Python containers:
volumes:
claude-auth: # Shared volume for all containersFor increased security or when using different Claude accounts/methods per container, you can create separate volumes in compose.yaml:
services:
typescript:
image: ghcr.io/[org]/claude-agent-sdk:typescript
environment:
- CLAUDE_CODE_OAUTH_TOKEN=${OAUTH_TOKEN_1}
volumes:
- claude-auth-dev:/home/claude/.claude
python:
image: ghcr.io/[org]/claude-agent-sdk:typescript
environment:
- CLAUDE_CODE_OAUTH_TOKEN=${OAUTH_TOKEN_2}
volumes:
- claude-auth-prod:/home/claude/.claude
volumes:
claude-auth-dev:
claude-auth-prod:You can also mix authentication methods across containers:
services:
# OAuth token for development
dev:
image: ghcr.io/[org]/claude-agent-sdk:typescript
environment:
- CLAUDE_CODE_OAUTH_TOKEN=${OAUTH_TOKEN}
volumes:
- claude-auth-dev:/home/claude/.claude
# API key for testing
test:
image: ghcr.io/[org]/claude-agent-sdk:typescript
environment:
- ANTHROPIC_API_KEY=${API_KEY}
volumes:
- claude-auth-test:/home/claude/.claude
# Interactive auth
experiment:
image: ghcr.io/[org]/claude-agent-sdk:typescript
volumes:
- claude-auth-exp:/home/claude/.claude
# No token - use 'docker exec' to authenticate interactively
volumes:
claude-auth-dev:
claude-auth-test:
claude-auth-exp:This approach provides:
- Security isolation: Each container has its own credentials
- Account separation: Use different Claude accounts per environment
- Method flexibility: Mix OAuth, API keys, and interactive auth as needed
- Easy rotation: Update individual tokens without affecting other containers
- Use secrets in production: For production deployments, use proper secret management
- Never commit tokens:
.envfiles are gitignored, but consider using environment variables as in 1 ☝️ to avoid accidental token exposure - Rotate tokens: Generate new tokens periodically for security