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. 1.Not authenticated - Docker not logged in to Harbor
  2. 2.Insufficient permissions - User lacks push permission
  3. 3.Project not found - Target project does not exist
  4. 4.Storage quota exceeded - Project storage limit reached
  5. 5.Tag immutability - Cannot overwrite immutable tag
  6. 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

CheckCommandExpected
Authenticationdocker loginLogin Succeeded
Project existsAPI/projectsProject listed
User permissionProject MembersDeveloper+ role
Image tagdocker imagesCorrect format
Quotaproject/summaryWithin limit
Networkcurl/v2/_catalogConnected

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 ```

  • [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)