Your CI/CD pipeline needs to deploy containers to a remote Docker host. You don't want to write another 200-line bash script with SSH key management, error handling, and cleanup. This Action does it in 15 lines of YAML — with input validation, shell injection protection, and automatic SSH key cleanup.
- Security Enhanced: Input validation, path traversal protection, and safe command execution
- Multiple Deployment Modes: Support for both Docker Compose and Docker Swarm
- Registry Integration: Automatic login to private registries
- File Management: Automatic cleanup of old deployment files
- Error Handling: Comprehensive error handling and logging
- Non-Interactive: Fully automated without interactive prompts
- Testing: Built-in test suite for validation
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to Docker host
uses: sulthonzh/dotforge@v0.10.0
with:
remote_docker_host: ${{ secrets.REMOTE_HOST }}
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}
ssh_public_key: ${{ secrets.SSH_PUBLIC_KEY }}
deployment_mode: docker-compose
copy_stack_file: true
deploy_path: /root/my-app
stack_file_name: docker-compose.yml
keep_files: 5
args: -d productionname: Deploy to Swarm
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to Docker Swarm
uses: sulthonzh/dotforge@v0.10.0
with:
remote_docker_host: ${{ secrets.REMOTE_HOST }}
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}
ssh_public_key: ${{ secrets.SSH_PUBLIC_KEY }}
deployment_mode: docker-swarm
copy_stack_file: true
deploy_path: /root/my-swarm
stack_file_name: docker-stack.yml
keep_files: 10
args: my-app-stackname: Deploy with Private Registry
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to private registry
uses: sulthonzh/dotforge@v0.10.0
with:
remote_docker_host: ${{ secrets.REMOTE_HOST }}
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}
ssh_public_key: ${{ secrets.SSH_PUBLIC_KEY }}
deployment_mode: docker-compose
docker_registry_username: ${{ secrets.REGISTRY_USERNAME }}
docker_registry_password: ${{ secrets.REGISTRY_PASSWORD }}
docker_registry_uri: https://registry.example.com
args: -d production| Input | Description | Default |
|---|---|---|
remote_docker_host |
Remote Docker host (user@host) | Required |
ssh_public_key |
SSH public key | Required |
ssh_private_key |
SSH private key | Required |
args |
Deployment command args | Required |
| Input | Description | Default |
|---|---|---|
remote_docker_port |
Remote SSH port | 22 |
deployment_mode |
docker-compose or docker-swarm |
docker-compose |
copy_stack_file |
Copy stack file to remote server | false |
deploy_path |
Deployment path on remote server | ~/docker-deployment |
stack_file_name |
Stack file name | docker-compose.yml |
keep_files |
Number of files to keep | 4 |
docker_prune |
Run docker system prune | false |
pre_deployment_command_args |
Pre-deployment commands (docker-compose mode only) | |
pull_images_first |
Pull images before deploying (docker-compose mode only, silently skipped for docker-swarm) | false |
docker_registry_username |
Registry username | |
docker_registry_password |
Registry password | |
docker_registry_uri |
Registry URI | https://registry.hub.docker.com |
- Shell Injection Protection: Blocks shell metacharacters (
;,|,&, etc.) - Path Traversal Protection: Blocks
../sequences in file paths - Numeric Validation: Ensures port and file count inputs are valid numbers
- Strict Host Key Checking: Disables for automation (controlled environment)
- Key Management: Secure handling of SSH keys with proper permissions
- Connection Cleanup: Automatic cleanup of SSH connections and contexts
- Non-root User: Runs as non-root user for reduced attack surface
- Secure Password Handling: Uses temporary files for registry passwords
- Context Management: Proper cleanup of Docker contexts
The action includes comprehensive error handling for:
- SSH connection failures
- Docker context creation failures
- Registry authentication failures
- File transfer operations
- Deployment command execution
All errors are logged with clear messages, and the action exits with appropriate error codes.
The action includes a comprehensive test suite that validates:
- Action.yml syntax and structure
- Docker image build process
- Shell script syntax
- Input validation functions
- Environment variable handling
- Security checks
Tests run automatically on push and pull requests.
- Use SSH Keys: Always use SSH keys instead of passwords
- Restrict Host Access: Only allow trusted hosts in your SSH configuration
- Use Private Registries: Store registry credentials as secrets
- Limit Permissions: Use the least privilege necessary for deployment
- Use Copy Stack File: Set
copy_stack_file: truefor better performance - Pull Images First: Use
pull_images_first: trueto reduce deployment time (runs after pre-deployment validation, before deployment) - Manage File Count: Adjust
keep_filesbased on your storage needs
- Enable Logging: Use debug logging for troubleshooting
- Check Status: Monitor deployment status through GitHub Actions logs
- Review Prune Operations: Use
docker_prunecarefully in production
-
SSH Connection Failed
- Verify SSH keys are correctly formatted
- Check host connectivity and port access
- Ensure user has proper permissions
-
Docker Context Creation Failed
- Verify Docker is installed on the remote host
- Check SSH connectivity to Docker daemon
- Ensure user is in the docker group
-
Registry Authentication Failed
- Verify registry credentials
- Check registry URL and connectivity
- Ensure registry allows access from your IP
-
Deployment Failed
- Check stack file syntax
- Verify image availability
- Review deployment logs on the remote host
When copy_stack_file is false (default), the action passes --log-level debug to Docker Compose automatically. To get additional diagnostic output, enable GitHub Actions step debug logging by setting the ACTIONS_STEP_DEBUG secret to true in your repository.
| Feature | This Action | ssh-deploy | appleboy/ssh-action | Manual SSH Script |
|---|---|---|---|---|
| Docker Compose support | ✅ | ❌ | ❌ | DIY |
| Docker Swarm support | ✅ | ❌ | ❌ | DIY |
| Shell injection validation | ✅ | ❌ | ❌ | Maybe |
| Path traversal protection | ✅ | ❌ | ❌ | Maybe |
| Automatic key cleanup | ✅ | ❌ | ❌ | No |
| Private registry login | ✅ | ❌ | ❌ | DIY |
| Stack file management | ✅ | ✅ | ❌ | DIY |
| Non-root execution | ✅ | ❌ | ❌ | Maybe |
| Docker prune | ✅ | ❌ | ❌ | DIY |
This project is licensed under the MIT License. See the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
- Enhanced security with input validation
- Added comprehensive test suite
- Improved error handling
- Updated Docker Compose to v2.40.3
- Added non-root user support
- Fixed interactive prompt issue
- Initial release with basic Docker deployment functionality