Overview
Push Docker images to configured container registries. Supports Docker Hub, private registries, and custom registry configurations with automatic tag management and authentication handling.
Endpoint
POST /api/images/push?env={environmentId}
Query Parameters
Environment ID containing the image to push. Optional for local environments.
Request Body
Image ID (SHA256 hash) to push
Current image name/tag (used for audit logging)
Registry ID where the image will be pushed. Must be a configured registry.
Custom tag for the pushed image. If not provided, uses the image’s existing tag.
Format: repository/name:tag or name:tag
Authentication
Requires images:push permission for the specified environment.
Registry Authentication
Registry credentials are retrieved from the database and sent to Docker API:
const authConfig = registry.username && registry.password
? {
username: registry.username,
password: registry.password,
serveraddress: authServerAddress
}
: {
serveraddress: authServerAddress
};
Async Response (default)
Returns job ID for progress tracking:
{
"jobId": "550e8400-e29b-41d4-a716-446655440000"
}
Sync Response (with Accept: application/json)
Returns final result immediately:
{
"status": "complete",
"message": "Image pushed to registry.example.com/app:v1.0",
"targetTag": "registry.example.com/app:v1.0"
}
Progress Events
Tagging
{
"status": "tagging",
"message": "Tagging image..."
}
Pushing
{
"status": "pushing",
"message": "Pushing to registry..."
}
Layer Progress
{
"id": "abc123",
"status": "Pushing",
"progressDetail": {
"current": 1048576,
"total": 10485760
},
"progress": "[====> ] 1MB/10MB"
}
Complete
{
"status": "complete",
"message": "Image pushed to registry.example.com/app:v1.0",
"targetTag": "registry.example.com/app:v1.0"
}
Error
{
"status": "error",
"error": "Authentication failed. Check registry credentials."
}
Error Responses
Invalid request - missing required fields{ "error": "Image ID and registry ID are required" }
Image has no tag{ "error": "Image has no tag. Please provide a tag name." }
Permission denied{ "error": "Permission denied" }
Registry not found{ "error": "Registry not found" }
Push failed - authentication or network error{
"status": "error",
"error": "TLS/HTTPS error. If your registry uses HTTP, add it to Docker's insecure-registries in /etc/docker/daemon.json"
}
Tag Management
The push endpoint automatically handles tag formatting for different registry types:
Docker Hub
Docker Hub images don’t require host prefix:
const isDockerHub = registryHost.includes('docker.io') ||
registryHost.includes('hub.docker.com') ||
registryHost.includes('registry.hub.docker.com') ||
registryHost.includes('index.docker.io');
// Docker Hub: username/image:tag
// Other registries: registry.example.com/org/image:tag
const targetTag = isDockerHub ? targetImageName : `${fullRegistry}/${targetImageName}`;
Private Registries
Private registry pushes include the full host path:
registry.company.com:5000/project/app:v1.0
Registry Prefix Removal
Existing registry prefixes are stripped before applying new target:
let baseImageName = sourceTag;
if (baseImageName.includes('/')) {
const parts = baseImageName.split('/');
// Check if first part looks like a registry (contains . or :)
if (parts[0].includes('.') || parts[0].includes(':')) {
baseImageName = parts.slice(1).join('/');
}
}
Edge Mode Support
For Hawser Edge environments:
if (edgeCheck.isEdge && edgeCheck.environmentId) {
if (!isEdgeConnected(edgeCheck.environmentId)) {
emit({ status: 'error', error: 'Edge agent not connected' });
return;
}
const authHeader = Buffer.from(JSON.stringify(authConfig)).toString('base64');
await sendEdgeStreamRequest(
edgeCheck.environmentId,
'POST',
`/images/${encodeURIComponent(targetTag)}/push`,
{ onData, onEnd, onError },
undefined,
{ 'X-Registry-Auth': authHeader }
);
}
Error Handling
The endpoint provides user-friendly error messages:
const formatError = (error: any): string => {
const errorMessage = error.message || error || '';
let userMessage = errorMessage || 'Failed to push image';
if (error.statusCode === 401 || errorMessage.includes('401')) {
userMessage = 'Authentication failed. Check registry credentials.';
} else if (error.statusCode === 404 || errorMessage.includes('404')) {
userMessage = 'Image not found';
} else if (errorMessage.includes('https') || errorMessage.includes('tls') ||
errorMessage.includes('certificate') || errorMessage.includes('x509')) {
userMessage = `TLS/HTTPS error. If your registry uses HTTP, add it to Docker's insecure-registries in /etc/docker/daemon.json`;
}
return userMessage;
};
Usage Examples
Push to Docker Hub
curl -X POST 'https://dockhand.example.com/api/images/push?env=1' \
-H 'Content-Type: application/json' \
-H 'Cookie: session=...' \
-d '{
"imageId": "sha256:abc123...",
"imageName": "myapp:latest",
"registryId": 1,
"newTag": "username/myapp:v1.0"
}'
Push to Private Registry
curl -X POST 'https://dockhand.example.com/api/images/push?env=1' \
-H 'Content-Type: application/json' \
-d '{
"imageId": "sha256:def456...",
"registryId": 2,
"newTag": "app:production"
}'
Push with Progress Tracking
const response = await fetch('/api/images/push?env=1', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
imageId: 'sha256:abc123...',
registryId: 1,
newTag: 'myapp:v2.0'
})
});
const { jobId } = await response.json();
const eventSource = new EventSource(`/api/jobs/${jobId}`);
eventSource.addEventListener('data', (e) => {
const progress = JSON.parse(e.data);
if (progress.data.status === 'complete') {
console.log('Push complete:', progress.data.targetTag);
eventSource.close();
} else if (progress.data.status === 'error') {
console.error('Push failed:', progress.data.error);
eventSource.close();
}
});
Audit Logging
Push operations are logged with full details:
await auditImage(
event,
'push',
imageId,
imageName || targetTag,
envIdNum,
{ targetTag, registry: registry.name }
);
Notes
- Images are automatically tagged before pushing
- Docker Hub uses
index.docker.io/v1/ for authentication
- Private registries must be configured with credentials
- Insecure registries require Docker daemon configuration
- Edge mode requires active Hawser agent connection
- Authentication failures provide helpful error messages
- TLS/certificate errors suggest insecure-registry configuration