This error occurs when Docker cannot establish a TCP connection to a container registry. The registry service may not be running, the port may be incorrect, or network/firewall rules are blocking the connection.
The "connection refused" error when connecting to a Docker registry indicates that your Docker client is attempting to reach a registry server, but the TCP connection is being actively refused. This means either nothing is listening on the specified port, or a firewall is blocking the connection at the network level. This error commonly appears in several scenarios: - **Private registries**: When connecting to a self-hosted registry like Harbor, Nexus, or the official Docker Registry image - **Local development**: When pushing/pulling from a local registry running on localhost:5000 - **CI/CD pipelines**: When the registry service container hasn't fully started yet - **BuildKit builds**: When using `docker buildx` to push to a local registry with different network contexts The URL in the error message (e.g., `https://myregistry:5000/v2/`) reveals the registry hostname, port, and protocol being used. The `/v2/` path is the Docker Registry HTTP API endpoint that clients use to check registry availability.
First, check if your registry container is actually running:
# List running containers
docker ps | grep registry
# Check all containers (including stopped)
docker ps -a | grep registryIf the registry is stopped, check the logs for errors:
docker logs registryStart or restart the registry if needed:
# If stopped
docker start registry
# If not created, start a basic local registry
docker run -d --restart=always -p 5000:5000 --name registry registry:2Verify the registry is listening on the expected port:
Check container port mapping:
docker port registry
# Should show: 5000/tcp -> 0.0.0.0:5000Verify port is listening on host:
# Linux
ss -tlnp | grep 5000
netstat -tlnp | grep 5000
# macOS
lsof -i :5000
# Windows
netstat -ano | findstr 5000Test connectivity:
# Check if registry responds
curl -v http://localhost:5000/v2/
# Expected response: {"repositories":[]} or similarIf the port isn't mapped, recreate the registry with correct port binding:
docker rm -f registry
docker run -d --restart=always -p 5000:5000 --name registry registry:2The hostname you use depends on where Docker commands run:
From host machine:
# Use localhost
docker tag myimage localhost:5000/myimage
docker push localhost:5000/myimageFrom another container (e.g., in CI/CD):
# Use the registry container name or Docker network hostname
docker tag myimage registry:5000/myimage
docker push registry:5000/myimage
# Or use host.docker.internal (Docker Desktop)
docker tag myimage host.docker.internal:5000/myimage
docker push host.docker.internal:5000/myimageIn Docker Compose:
services:
registry:
image: registry:2
ports:
- "5000:5000"
builder:
image: docker:latest
environment:
# Use service name as hostname
REGISTRY_HOST: registry:5000
depends_on:
- registryIf your registry uses HTTP instead of HTTPS, Docker requires explicit configuration:
Docker Desktop (Windows/macOS):
1. Open Docker Desktop Settings
2. Go to Docker Engine
3. Add your registry to the insecure-registries list:
{
"insecure-registries": ["myregistry:5000", "localhost:5000"]
}4. Click "Apply & Restart"
Linux - Edit daemon.json:
sudo tee /etc/docker/daemon.json << EOF
{
"insecure-registries": ["myregistry:5000", "localhost:5000"]
}
EOF
sudo systemctl restart dockerVerify configuration:
docker info | grep -A5 "Insecure Registries"Note: "Insecure" here refers to HTTP (not HTTPS), not to authentication. For production, always use HTTPS.
BuildKit (used by docker buildx) runs in a separate context and may not reach localhost registries:
Problem: BuildKit container can't reach localhost:5000 because localhost refers to the BuildKit container, not the host.
Solution 1: Use host network mode for buildx:
docker buildx create --name hostbuilder --driver docker-container --driver-opt network=host
docker buildx use hostbuilder
docker buildx build --push -t localhost:5000/myimage .Solution 2: Use host.docker.internal (Docker Desktop):
docker buildx build --push -t host.docker.internal:5000/myimage .Solution 3: Put registry and buildx on same Docker network:
# Create network
docker network create buildnet
# Start registry on network
docker run -d --name registry --network buildnet -p 5000:5000 registry:2
# Create buildx builder on same network
docker buildx create --name netbuilder --driver docker-container --driver-opt network=buildnet
docker buildx use netbuilder
# Push using registry container name
docker buildx build --push -t registry:5000/myimage .Registry containers need time to initialize. Add a wait step in CI/CD:
GitLab CI example:
services:
- name: registry:2
alias: registry
variables:
REGISTRY_HOST: registry:5000
build:
script:
# Wait for registry to be ready
- |
echo "Waiting for registry..."
timeout 30 sh -c 'until curl -sf http://registry:5000/v2/; do sleep 1; done'
echo "Registry is ready!"
- docker build -t $REGISTRY_HOST/myimage .
- docker push $REGISTRY_HOST/myimageGitHub Actions example:
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
- name: Wait for registry
run: |
timeout 30 sh -c 'until curl -sf http://localhost:5000/v2/; do sleep 1; done'
- name: Build and push
run: |
docker build -t localhost:5000/myimage .
docker push localhost:5000/myimageFirewall rules may block registry port:
Linux with UFW:
# Check status
sudo ufw status
# Allow port 5000
sudo ufw allow 5000/tcpLinux with firewalld:
# Check ports
sudo firewall-cmd --list-ports
# Allow port 5000
sudo firewall-cmd --permanent --add-port=5000/tcp
sudo firewall-cmd --reloadCheck Docker network connectivity:
# List networks
docker network ls
# Inspect network
docker network inspect bridge
# Test connectivity from a container
docker run --rm curlimages/curl curl -v http://host.docker.internal:5000/v2/Windows firewall:
# Check if port is allowed
Get-NetFirewallRule | Where-Object {$_.LocalPort -eq 5000}
# Add rule
New-NetFirewallRule -DisplayName "Docker Registry" -Direction Inbound -LocalPort 5000 -Protocol TCP -Action AllowIf the registry container keeps crashing or becomes unresponsive:
Check container logs:
docker logs registry --tail 100
docker logs registry -f # Follow logsCommon registry issues and fixes:
Storage issues:
# Check disk space in registry
docker exec registry df -h /var/lib/registry
# If full, prune old images (WARNING: removes unused images)
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.ymlConfiguration problems:
# Check registry config
docker exec registry cat /etc/docker/registry/config.yml
# Start with verbose logging
docker run -d -p 5000:5000 --name registry \
-e REGISTRY_LOG_LEVEL=debug \
registry:2Memory issues:
# Check container stats
docker stats registry --no-stream
# Restart with memory limit
docker run -d -p 5000:5000 --name registry \
--memory=512m \
registry:2Understanding Docker Registry networking:
When working with registries, network context matters greatly:
- Host context: Commands run directly on the host can use localhost:5000
- Container context: Commands run inside containers must use container names, bridge IPs, or host.docker.internal
- BuildKit context: BuildKit runs in its own container and needs special network configuration
Registry authentication and TLS:
For production registries, always configure TLS and authentication:
# Generate self-signed certificate
mkdir -p certs
openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout certs/domain.key -x509 -days 365 \
-out certs/domain.crt \
-subj "/CN=myregistry" \
-addext "subjectAltName=DNS:myregistry,IP:192.168.1.100"
# Start registry with TLS
docker run -d -p 5000:5000 --name registry \
-v $(pwd)/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry:2
# Configure Docker to trust the certificate
sudo mkdir -p /etc/docker/certs.d/myregistry:5000
sudo cp certs/domain.crt /etc/docker/certs.d/myregistry:5000/ca.crtUsing Docker registry mirror:
For air-gapped or slow network environments, configure registry as a pull-through cache:
# config.yml for registry
version: 0.1
proxy:
remoteurl: https://registry-1.docker.io
storage:
filesystem:
rootdirectory: /var/lib/registrydocker run -d -p 5000:5000 --name mirror \
-v $(pwd)/config.yml:/etc/docker/registry/config.yml \
registry:2Debugging with Docker events:
Monitor Docker daemon events to see connection attempts:
docker events --filter 'type=image' &
docker push myregistry:5000/testAlternative registries with built-in UI:
If you frequently have registry issues, consider registries with web interfaces for easier debugging:
- Harbor (enterprise features, vulnerability scanning)
- Nexus Repository (supports multiple package formats)
- GitLab Container Registry (integrated with GitLab CI)
- Portus (open source UI for Docker Registry)
image operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker
cannot open '/etc/passwd': Permission denied
How to fix 'cannot open: Permission denied' in Docker
Error response from daemon: failed to create the ipvlan port
How to fix 'failed to create the ipvlan port' in Docker
toomanyrequests: Rate exceeded for anonymous users
How to fix 'Rate exceeded for anonymous users' in Docker Hub