I’m running a private Docker Registry (registry:2) behind Traefik in a Docker Swarm setup. Traefik handles HTTPS via Let’s Encrypt, and the registry itself runs without TLS behind the proxy.
Small Docker images push successfully, confirming Traefik routing and authentication are working. However, larger images fail to upload. Traefik logs show HTTP 499 responses on the PUT /v2/.../blobs/uploads/ endpoint, indicating that the client connection is being closed during the upload.
I’ve tried using Traefik’s buffering middleware to limit request body sizes and buffer large uploads, but it doesn’t seem to resolve the issue. It appears Traefik’s default timeouts or other internal limits are still interfering with large Docker layer uploads.
Traefik
services:
traefik:
image: traefik:v3.6
command:
# Providers
- "--providers.swarm=true"
- "--providers.swarm.exposedbydefault=false"
- "--providers.swarm.network=traefik-net"
- "--providers.file.directory=/dynamic"
- "--providers.file.watch=true"
# EntryPoints
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
# ACME
- "--certificatesresolvers.letsencrypt.acme.email=mymail1@gmail.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
# API
- "--api.dashboard=true"
- "--api.insecure=false"
# Logs
- "--log.level=DEBUG"
- "--accesslog=true"
ports:
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
protocol: tcp
mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /dir/traefik-stack/acme:/letsencrypt
- /dir/traefik-stack/dynamic:/dynamic:ro
networks:
- traefik-net
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
labels:
- "traefik.enable=true"
# Dashboard router
- "traefik.http.routers.dashboard.rule=Host(`traefik.domain.io`)"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.tls=true"
# Basic‑auth middleware
- "traefik.http.routers.dashboard.middlewares=dashboard-auth@file,vpn-only@file"
# Service hint
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
networks:
traefik-net:
external: true
Registry
services:
registry:
image: registry:2
environment:
- REGISTRY_AUTH=htpasswd
- REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
- REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
- REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry
- REGISTRY_HTTP_ADDR=0.0.0.0:5000
volumes:
- /dir/registry-stack/data:/var/lib/registry
- /dir/registry-stack/auth:/auth
- /dir/registry-stack/logs:/var/log/registry
# Uncomment if using direct SSL:
# - /home/admin/infra/registry-stack/certs:/certs
networks:
- traefik-net
- registry-net
deploy:
mode: replicated
replicas: 1
placement:
constraints:
- node.role == manager
labels:
# Enable Traefik
- "traefik.enable=true"
# HTTP Router
- "traefik.http.routers.registry.rule=Host(`reg.domain.io`)"
- "traefik.http.routers.registry.entrypoints=websecure"
- "traefik.http.routers.registry.tls.certresolver=letsencrypt"
- "traefik.http.routers.registry.service=registry"
- "traefik.http.routers.registry.middlewares=limit@file,vpn-only@file"
# Service
- "traefik.http.services.registry.loadbalancer.server.port=5000"
# Redirect HTTP to HTTPS
- "traefik.http.routers.registry-http.rule=Host(`registry.domain.io`)"
- "traefik.http.routers.registry-http.entrypoints=web"
- "traefik.http.routers.registry-http.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true"
secrets:
- registry-auth
networks:
traefik-net:
external: true
registry-net:
external: true
secrets:
registry-auth:
external: true
Middleware
http:
middlewares:
limit:
buffering:
maxRequestBodyBytes: 0
memRequestBodyBytes: 0
maxResponseBodyBytes: 0
memResponseBodyBytes: 0