Coolify allows you to host a Distribution docker registry backed by S3 or GCS
To use with GCS we can add a GCS service_key.json file and use Coolify’s mounted file editor to paste in the contents of a key exported from Google GCP.
services:
registry:
image: 'registry:2'
environment:
- SERVICE_FQDN_REGISTRY_5000
- REGISTRY_AUTH=htpasswd
- REGISTRY_AUTH_HTPASSWD_REALM=Registry
- REGISTRY_AUTH_HTPASSWD_PATH=/auth/registry.password
volumes:
-
type: bind
isDirectory: false
source: ./auth/service_key.json
target: /auth/service_key.json
-
type: bind
source: ./auth/registry.password
target: /auth/registry.password
isDirectory: false
-
type: bind
source: ./config/config.yml
target: /etc/docker/registry/config.yml
isDirectory: false
-
type: bind
source: ./data
target: /data
isDirectory: true
We can then configure the storage driver as described in the Google Cloud Storage Config or S3 Storage Config guides.
Traefik
We need to add some extra commands and labels to avoid problems with images not uploading/timing out/being too big.
Specifically:
commands:
command:
# other commands here
- '--serversTransport.forwardingTimeouts.dialTimeout=60s'
- '--serversTransport.forwardingTimeouts.responseHeaderTimeout=600s'
- '--serversTransport.forwardingTimeouts.idleConnTimeout=600s'
- '--entrypoints.http.transport.respondingTimeouts.readTimeout=600s'
- '--entrypoints.http.transport.respondingTimeouts.writeTimeout=600s'
- '--entrypoints.https.transport.respondingTimeouts.readTimeout=600s'
- '--entrypoints.https.transport.respondingTimeouts.writeTimeout=600s'
and labels:
labels:
# other labels here
- traefik.http.middlewares.size-limit.sizeLimits.maxBodySize=500000000
Full example:
version: '3.8'
networks:
coolify:
external: true
services:
traefik:
container_name: coolify-proxy
image: 'traefik:v2.11'
restart: unless-stopped
extra_hosts:
- 'host.docker.internal:host-gateway'
networks:
- coolify
ports:
- '80:80'
- '443:443'
- '8080:8080'
healthcheck:
test: 'wget -qO- http://localhost:80/ping || exit 1'
interval: 4s
timeout: 2s
retries: 5
volumes:
- '/var/run/docker.sock:/var/run/docker.sock:ro'
- '/data/coolify/proxy:/traefik'
command:
- '--ping=true'
- '--ping.entrypoint=http'
- '--api.dashboard=true'
- '--api.insecure=false'
- '--entrypoints.http.address=:80'
- '--entrypoints.https.address=:443'
- '--entrypoints.http.http.encodequerysemicolons=true'
- '--entryPoints.http.http2.maxConcurrentStreams=50'
- '--entrypoints.https.http.encodequerysemicolons=true'
- '--entryPoints.https.http2.maxConcurrentStreams=50'
- '--providers.docker.exposedbydefault=false'
- '--providers.file.directory=/traefik/dynamic/'
- '--providers.file.watch=true'
- '--certificatesresolvers.letsencrypt.acme.httpchallenge=true'
- '--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json'
- '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=http'
- '--providers.docker=true'
- '--serversTransport.forwardingTimeouts.dialTimeout=60s'
- '--serversTransport.forwardingTimeouts.responseHeaderTimeout=600s'
- '--serversTransport.forwardingTimeouts.idleConnTimeout=600s'
- '--entrypoints.http.transport.respondingTimeouts.readTimeout=600s'
- '--entrypoints.http.transport.respondingTimeouts.writeTimeout=600s'
- '--entrypoints.https.transport.respondingTimeouts.readTimeout=600s'
- '--entrypoints.https.transport.respondingTimeouts.writeTimeout=600s'
labels:
- traefik.enable=true
- traefik.http.routers.traefik.entrypoints=http
- traefik.http.routers.traefik.service=api@internal
- traefik.http.services.traefik.loadbalancer.server.port=8080
- coolify.managed=true
- traefik.http.middlewares.size-limit.sizeLimits.maxBodySize=500000000