What's Actually Happening
Docker push to Harbor container registry fails. Images cannot be uploaded to the registry.
The Error You'll See
```bash $ docker push harbor.example.com/myproject/myimage:latest
unauthorized: authentication required ```
Denied error:
```bash $ docker push harbor.example.com/myproject/myimage:v1
denied: requested access to the resource is denied ```
Blob upload error:
```bash $ docker push harbor.example.com/library/app:latest
blob upload unknown ```
Storage error:
```bash $ docker push harbor.example.com/project/image:tag
Error writing blob: disk quota exceeded ```
Why This Happens
- 1.Not authenticated - Docker not logged in to Harbor
- 2.Insufficient permissions - User lacks push permission
- 3.Project not found - Target project does not exist
- 4.Storage quota exceeded - Project storage limit reached
- 5.Tag immutability - Cannot overwrite immutable tag
- 6.Network issues - Connection to Harbor failed
Step 1: Check Docker Authentication
```bash # Check current Docker auth: cat ~/.docker/config.json
# Login to Harbor: docker login harbor.example.com
# Enter username and password: # Username: admin # Password: ** # Login Succeeded
# Login with token: echo "token" | docker login harbor.example.com -u user --password-stdin
# Check login status: docker login harbor.example.com --username test --password-stdin <<< "password"
# Logout and login again: docker logout harbor.example.com docker login harbor.example.com
# Check Harbor credentials: # Harbor UI -> User Profile -> CLI Secret ```
Step 2: Check Project Permissions
```bash # Check if project exists: curl -u user:password https://harbor.example.com/api/v2.0/projects
# Check project details: curl -u user:password https://harbor.example.com/api/v2.0/projects/myproject
# Check user permissions: # Harbor UI -> Projects -> myproject -> Members
# Required role for push: # - Developer: can push images # - Admin: full access
# Add user to project: # Harbor UI -> Projects -> myproject -> Members -> Add Member
# Check via API: curl -u user:password https://harbor.example.com/api/v2.0/projects/myproject/members
# Create project if missing: curl -u admin:password -X POST \ https://harbor.example.com/api/v2.0/projects \ -H "Content-Type: application/json" \ -d '{"project_name":"myproject","public":false}' ```
Step 3: Check Image Tag Format
```bash # Correct tag format: # harbor.example.com/project/image:tag
# Tag image correctly: docker tag myimage:latest harbor.example.com/myproject/myimage:latest
# Check tagged image: docker images | grep harbor
# Wrong format examples: # harbor.example.com/myimage:tag # Missing project # myproject/myimage:tag # Missing registry
# Tag with full path: docker tag myimage:v1 harbor.example.com/library/myimage:v1
# Verify tag: docker inspect harbor.example.com/myproject/myimage:v1 | jq .[0].RepoTags ```
Step 4: Check Storage Quota
```bash # Check project quota: # Harbor UI -> Projects -> myproject -> Summary
# Check via API: curl -u user:password https://harbor.example.com/api/v2.0/projects/myproject/summary
# Check storage usage: curl -u admin:password https://harbor.example.com/api/v2.0/projects/myproject/summary | jq .quota
# If quota exceeded: # 1. Delete unused images # 2. Increase quota
# Delete images: # Harbor UI -> Projects -> myproject -> Repositories -> Select -> Delete
# Increase quota: # Harbor UI -> Projects -> myproject -> Configuration -> Quota
# Or via API: curl -u admin:password -X PUT \ https://harbor.example.com/api/v2.0/projects/myproject \ -H "Content-Type: application/json" \ -d '{"metadata":{"storage_limit":"10GB"}}' ```
Step 5: Check Tag Immutability
```bash # If tag immutability enabled, cannot overwrite existing tag
# Check immutable rules: # Harbor UI -> Projects -> myproject -> Configuration -> Tag Immutability
# Check via API: curl -u user:password https://harbor.example.com/api/v2.0/projects/myproject/immutabletagrules
# Error when pushing immutable tag: # denymutable: tag is immutable
# Solutions: # 1. Use different tag # 2. Disable immutability rule # 3. Delete rule temporarily
# Disable rule: curl -u admin:password -X PUT \ https://harbor.example.com/api/v2.0/projects/myproject/immutabletagrules/1 \ -H "Content-Type: application/json" \ -d '{"disabled":true}' ```
Step 6: Check Harbor Service Status
```bash # Check Harbor status: docker-compose ps # Or: docker-compose -f docker-compose.yml ps
# Check Harbor components: docker ps | grep harbor
# Check Harbor logs: docker-compose logs harbor-core docker-compose logs harbor-registry
# Check specific service: docker logs harbor-core docker logs harbor-registryctl
# Restart Harbor: docker-compose down docker-compose up -d
# Check health: curl https://harbor.example.com/api/v2.0/systeminfo ```
Step 7: Check Network Connectivity
```bash # Test Harbor connectivity: curl -k https://harbor.example.com/v2/_catalog
# Test with authentication: curl -u user:password https://harbor.example.com/v2/_catalog
# Check DNS: dig harbor.example.com nslookup harbor.example.com
# Check port: nc -zv harbor.example.com 443
# Check certificate: openssl s_client -connect harbor.example.com:443
# If self-signed cert: # Add to trusted: cp harbor.crt /usr/local/share/ca-certificates/ update-ca-certificates
# Or add to Docker: mkdir -p /etc/docker/certs.d/harbor.example.com cp harbor.crt /etc/docker/certs.d/harbor.example.com/ca.crt
# Restart Docker: systemctl restart docker ```
Step 8: Check Proxy Settings
```bash # If using HTTP proxy:
# Configure Docker daemon: # /etc/docker/daemon.json: { "insecure-registries": ["harbor.example.com"], "registry-mirrors": [], "proxies": { "default": { "httpProxy": "http://proxy:8080", "httpsProxy": "http://proxy:8080", "noProxy": "harbor.example.com" } } }
# Restart Docker: systemctl restart docker
# For insecure registry: # Add to daemon.json: { "insecure-registries": ["harbor.example.com"] }
# Or use HTTP: docker tag myimage harbor.example.com/myproject/myimage docker push harbor.example.com/myproject/myimage
# Configure no_proxy: export no_proxy="harbor.example.com,localhost" ```
Step 9: Check Docker Configuration
```bash # Check Docker config: cat /etc/docker/daemon.json
# Increase concurrent uploads: # In daemon.json: { "max-concurrent-uploads": 10, "max-concurrent-downloads": 10 }
# Check Docker version: docker version
# Check disk space: df -h /var/lib/docker
# Check Docker logs: journalctl -u docker -f
# Restart Docker: systemctl restart docker
# Clear Docker cache: docker system prune -a ```
Step 10: Harbor Push Verification Script
```bash # Create verification script: cat << 'EOF' > /usr/local/bin/check-harbor-push.sh #!/bin/bash
HARBOR=${1:-"harbor.example.com"} PROJECT=${2:-"library"} USER=${3:-"admin"}
echo "=== Harbor Status ===" curl -s -k -u $USER https://$HARBOR/api/v2.0/systeminfo | jq '.harbor_version'
echo "" echo "=== Connectivity Test ===" nc -zv $HARBOR 443 2>&1
echo "" echo "=== Docker Login Test ===" cat ~/.docker/config.json | grep $HARBOR || echo "Not logged in"
echo "" echo "=== Project List ===" curl -s -k -u $USER https://$HARBOR/api/v2.0/projects | jq '.[].name'
echo "" echo "=== Project Quota ===" curl -s -k -u $USER https://$HARBOR/api/v2.0/projects/$PROJECT/summary | jq '.quota'
echo "" echo "=== Recent Repositories ===" curl -s -k -u $USER "https://$HARBOR/api/v2.0/projects/$PROJECT/repositories?page_size=5" | jq '.[].name'
echo "" echo "=== Test Push ===" docker tag alpine:latest $HARBOR/$PROJECT/test-image:latest docker push $HARBOR/$PROJECT/test-image:latest 2>&1 || echo "Push failed" EOF
chmod +x /usr/local/bin/check-harbor-push.sh
# Usage: /usr/local/bin/check-harbor-push.sh harbor.example.com myproject admin
# Quick test: alias test-harbor='docker push harbor.example.com/test/test:latest' ```
Harbor Push Checklist
| Check | Command | Expected |
|---|---|---|
| Authentication | docker login | Login Succeeded |
| Project exists | API/projects | Project listed |
| User permission | Project Members | Developer+ role |
| Image tag | docker images | Correct format |
| Quota | project/summary | Within limit |
| Network | curl/v2/_catalog | Connected |
Verify the Fix
```bash # After fixing push issue
# 1. Check login docker login harbor.example.com // Login Succeeded
# 2. Check project curl -u user:pass https://harbor.example.com/api/v2.0/projects/myproject // Project exists
# 3. Tag image docker tag myimage:v1 harbor.example.com/myproject/myimage:v1 // Tagged
# 4. Push image docker push harbor.example.com/myproject/myimage:v1 // Push successful
# 5. Verify in Harbor # Check Harbor UI // Image appears
# 6. Pull to verify docker pull harbor.example.com/myproject/myimage:v1 // Pull successful ```
Related Issues
- [Fix Docker Registry Push Denied](/articles/fix-docker-registry-push-denied)
- [Fix Docker Image Not Found](/articles/fix-docker-image-not-found)
- [Fix Docker Container Exec Failed](/articles/fix-docker-container-exec-failed)