Aller au contenu
Conteneurs & Orchestration medium

Varnish Orca : Accélérer vos pipelines CI/CD

23 min de lecture

logo orca

Sur un pipeline CI/CD, une part importante de la durée de build part en téléchargement de dépendances : images Docker, packages NPM, modules Go. Chaque docker pull ou npm install sollicite les mêmes registres, encore et encore.

Varnish Orca résout ce problème en plaçant un cache intelligent entre vos outils et les registres. Résultat : des pulls 4x plus rapides, une résilience face aux pannes de Docker Hub, et une réduction massive de la bande passante sortante.

  • Installer Orca en 2 minutes avec Docker
  • Configurer Docker pour utiliser Orca comme mirror
  • Ajouter des registres multiples (Quay, GHCR, NPM, PyPI)
  • Mesurer le gain de performance sur vos builds
  • Déployer en production avec TLS et observabilité

Le problème : les mêmes artefacts retéléchargés en boucle

Section intitulée « Le problème : les mêmes artefacts retéléchargés en boucle »

Prenons une équipe de 10 développeurs. Chacun lance 5 builds par jour. Chaque build télécharge les mêmes dépendances :

  • L'image node:20-alpine (50 Mo)
  • 200 packages NPM (100 Mo)
  • Quelques images de base (200 Mo)

Calcul rapide : 10 devs × 5 builds × 350 Mo = 17,5 Go par jour. Multipliez par 20 jours ouvrés = 350 Go par mois téléchargés depuis Internet. Et ce sont toujours les mêmes fichiers !

Le constat : vos pipelines CI/CD passent leur temps à re-télécharger des artefacts qu'ils ont déjà récupérés la veille, l'heure d'avant, ou même 5 minutes plus tôt sur un autre runner.

Orca agit comme un proxy cache entre vos outils et les registres distants.

Comment ça marche, concrètement ?

  1. Votre CI exécute docker pull node:20-alpine
  2. Orca reçoit la requête (il se fait passer pour Docker Hub)
  3. Premier cas : l'image n'est pas en cache → Orca la télécharge depuis Docker Hub, la stocke, et vous la renvoie
  4. Deuxième cas : l'image est déjà en cache → Orca vous la renvoie instantanément, sans aller sur Internet

Architecture Varnish Orca : les clients (Docker, npm, Go, Helm) passent par le cache HTTP qui intercepte les requêtes vers les registres distants

Sans OrcaAvec Orca
Chaque build tire depuis Docker HubPremier build tire, les suivants servent du cache
Latence réseau à chaque pullLatence locale (< 10ms)
Vulnérable aux pannes Docker HubContinue de servir depuis le cache
Coûts d'egress élevés75%+ de réduction de trafic sortant

Orca cache tous types d'artefacts binaires immuables : une fois publié, un tag ou une version de package ne change plus, donc la réponse mise en cache reste valable. Le tableau ci-dessous correspond exactement à la configuration livrée dans l'image, vérifiée dans /etc/varnish-supervisor/default.yaml. La colonne de droite est celle qui vous intéresse au quotidien : c'est le nom d'hôte à écrire dans vos commandes pour viser tel ou tel registre amont. Notez qu'aucune entrée PyPI n'est fournie par défaut, il faut l'ajouter soi-même.

TypeRegistre par défautSubdomain Orca
Images Docker/OCIDocker Hubdockerhub.localhost
Images DockerQuay.ioquay.localhost
Images DockerGitHub Container Registryghcr.localhost
Images Kubernetesregistry.k8s.iok8s.localhost
Packages NPMregistry.npmjs.orgnpmjs.localhost
Modules Goproxy.golang.orggo.localhost
Repositories Gitgithub.comgithub.localhost
Repositories Gitgitlab.comgitlab.localhost
  • Docker 20.10+ installé
  • Accès root pour modifier /etc/docker/daemon.json
  • Port 80 ou 8888 disponible sur la machine hôte

C'est la voie la plus courte pour une première évaluation : rien à configurer, les registres publics sont déjà déclarés. Comptez une quinzaine de secondes entre le lancement et la première réponse, le temps qu'Orca compile et charge ses neuf groupes VCL, un par registre. Tant que le message Varnish is ready to receive traffic n'apparaît pas dans les logs, curl échoue sans code HTTP, ce qui n'est pas un défaut de configuration.

  1. Téléchargez l'image Orca

    Fenêtre de terminal
    docker pull varnish/orca:0.15.0
  2. Lancez Orca

    Fenêtre de terminal
    docker run -d --rm \
    -p 80:80 \
    --name orca \
    varnish/orca:0.15.0
  3. Vérifiez que Orca répond

    Fenêtre de terminal
    curl -I http://localhost/healthz

    Vous devez obtenir HTTP/1.1 200 OK.

Passez à Compose dès que le cache doit survivre à un redémarrage de la machine ou porter une configuration personnalisée. Deux différences comptent face à la commande précédente : le tag est épinglé sur 0.15.0 au lieu de latest, ce qui évite qu'une mise à jour amont change le comportement sans prévenir, et restart: unless-stopped relance le conteneur au démarrage du démon Docker. Le montage en lecture seule protège votre config.yaml d'une réécriture par le conteneur.

docker-compose.yaml
services:
orca:
image: varnish/orca:0.15.0@sha256:1b97e05a9caf32b355ccb5d25cda89db59b3bfd0ee34371aa0207ac7dc66469b
ports:
- "80:80"
volumes:
- ./config.yaml:/etc/varnish-supervisor/default.yaml:ro
restart: unless-stopped

Dans un cluster, le cache se place au plus près des runners : un Orca par zone ou par cluster suffit, les nœuds le joignent par un Service interne. Le chart est distribué en OCI sur Docker Hub, pas via un dépôt Helm classique, donc l'URL commence par oci:// et aucune commande helm repo add n'est nécessaire. Le premier appel télécharge le chart, le second l'installe.

Fenêtre de terminal
helm pull oci://docker.io/varnish/orca-chart
helm install orca oci://docker.io/varnish/orca-chart

L'installation par paquet convient à un hôte dédié, hors conteneur, avec une unité systemd et des logs dans le journal système. Le binaire installé s'appelle varnish-supervisor : c'est le nom du composant, Orca étant le nom commercial de la distribution. Le dépôt est hébergé sur packagecloud et sa mise en place passe par un script fourni par l'éditeur, que vous téléchargez et relisez avant de l'exécuter plutôt que de le passer directement à bash.

Fenêtre de terminal
# Ajouter le dépôt : télécharger le script, l'inspecter, puis l'exécuter
curl -s https://packagecloud.io/install/repositories/varnishplus/60-enterprise/script.deb.sh -o varnish-repo.sh
less varnish-repo.sh
sudo bash varnish-repo.sh
# Installer
sudo apt -y install varnish-supervisor
# Vérifier
varnish-supervisor --version

Pour que Docker utilise Orca comme registry mirror, modifiez la configuration du daemon Docker.

  1. Éditez /etc/docker/daemon.json

    /etc/docker/daemon.json
    {
    "registry-mirrors": ["http://localhost"],
    "insecure-registries": ["localhost"]
    }
  2. Redémarrez Docker

    Fenêtre de terminal
    sudo systemctl restart docker
  3. Vérifiez la configuration

    Fenêtre de terminal
    docker info | grep -A2 "Registry Mirrors"

    Vous devez voir http://localhost/.

Avec le registry mirror configuré, tous vos docker pull passent par Orca automatiquement. Aucune modification de vos Dockerfiles ou scripts n'est nécessaire.

Testons ensemble pour voir la différence :

Fenêtre de terminal
# Étape 1 : Premier pull (Orca télécharge depuis Docker Hub)
docker pull alpine:3.19
# → Orca n'a pas l'image, il la récupère sur Internet
# Étape 2 : Supprimez l'image de votre machine
docker rmi alpine:3.19
# → L'image n'est plus sur VOTRE machine, mais Orca l'a gardée
# Étape 3 : Deuxième pull (Orca sert depuis son cache)
docker pull alpine:3.19
# → Cette fois, Orca répond instantanément !

Résultats que j'ai mesurés (sur l'image node:20-alpine, 50 Mo) :

PullTempsCe qui se passe
Premier6.0sOrca télécharge depuis Docker Hub, stocke en cache
Second1.5sOrca sert directement depuis son cache local
Gain4xLe transfert Internet est évité

Pour les packages NPM, c'est un peu différent. Docker utilise automatiquement le registry mirror configuré, mais NPM doit être configuré explicitement.

Option 1 : Ponctuellement (pour un seul npm install) :

Fenêtre de terminal
npm install express --registry=http://npmjs.localhost

Option 2 : Globalement (recommandé pour le CI/CD) :

Fenêtre de terminal
npm config set registry http://npmjs.localhost

Le client Go lit la variable d'environnement GOPROXY pour savoir où chercher les modules. La pointer vers Orca suffit, aucun fichier de configuration n'est à modifier. Gardez en tête que GOPROXY accepte une liste de sources, et que le séparateur change le comportement de repli : avec une virgule, Go ne passe à la source suivante que sur une réponse 404 ou 410 ; avec une barre verticale, il bascule sur toute erreur, y compris un délai d'attente dépassé. Pour qu'un build survive à un redémarrage d'Orca, écrivez donc GOPROXY=http://go.localhost|direct.

Fenêtre de terminal
# Pour une commande
GOPROXY=http://go.localhost go mod tidy
# Ou exportez-la dans votre profil shell
export GOPROXY=http://go.localhost

Helm 3.8+ supporte les registres OCI. Utilisez le subdomain correspondant :

Fenêtre de terminal
# Chart depuis GitHub Container Registry via Orca
helm pull oci://ghcr.localhost/prometheus-community/charts/prometheus --plain-http

La configuration par défaut d'Orca inclut déjà les registres les plus courants (Docker Hub, NPM, Go, GitHub). Vous n'avez rien à configurer pour commencer.

Créez un fichier config.yaml personnalisé uniquement si vous avez besoin de :

  • Ajouter un registre privé d'entreprise
  • Configurer des politiques de cache (TTL)
  • Activer la haute disponibilité avec plusieurs remotes
config.yaml
varnish:
http:
- port: 80
virtual_registry:
registries:
# Docker Hub comme registre par défaut
- name: dockerhub
default: true
remotes:
- url: https://docker.io
- url: https://mirror.gcr.io # Fallback sur le mirror Google
# GitHub Container Registry
- name: ghcr
remotes:
- url: https://ghcr.io
# Quay.io
- name: quay
remotes:
- url: https://quay.io
# NPM
- name: npmjs
remotes:
- url: https://registry.npmjs.org
# PyPI
- name: pypi
remotes:
- url: https://pypi.org
# Registre privé d'entreprise
- name: internal
remotes:
- url: https://registry.entreprise.local

Montez ce fichier dans le conteneur :

Fenêtre de terminal
docker run -d --rm \
-p 80:80 \
--name orca \
-v $(pwd)/config.yaml:/etc/varnish-supervisor/default.yaml:ro \
varnish/orca:0.15.0

Ces cinq clés se placent au niveau d'une entrée de registries, pas au niveau global. Deux méritent une attention particulière : default: true ne doit figurer que sur un seul registre, celui qui répondra aux requêtes arrivant sans préfixe d'hôte, et default_ttl vaut 120 secondes, une valeur pensée pour les métadonnées mutables comme les tags flottants, pas pour les couches d'images qui sont immuables et gardées bien plus longtemps.

OptionDéfautDescription
name-Identifiant unique, utilisé pour le routing par subdomain
defaultfalseSi true, reçoit les requêtes sans subdomain
load_balancerfallbackStratégie : fallback, random, ou hash
default_ttl120TTL en secondes pour les objets sans politique spécifique
auth_ttl3600TTL du cache d'autorisation (Premium)

Un registre peut avoir plusieurs remotes pour la haute disponibilité :

- name: dockerhub
default: true
load_balancer: fallback
remotes:
- url: https://docker.io
priority: 1 # Essayé en premier
- url: https://mirror.gcr.io
priority: 2 # Fallback si Docker Hub échoue

Sans sonde, Orca ne découvre qu'un remote est mort qu'au moment où une requête réelle échoue, et c'est votre build qui paie l'attente. La sonde probe interroge périodiquement un chemin léger, ici /v2/, la racine de l'API de distribution OCI. Les quatre paramètres se lisent ensemble : threshold sur window définit la règle de décision, 3 succès sur les 8 derniers essais pour être déclaré sain. Un seuil trop bas fait basculer le trafic au moindre hoquet réseau, un seuil trop haut retarde la bascule vers le fallback.

- name: dockerhub
remotes:
- url: https://docker.io
probe:
url: /v2/
interval: 5 # Vérification toutes les 5s
timeout: 2 # Timeout de 2s
threshold: 3 # 3 succès requis pour être "healthy"
window: 8 # Sur les 8 derniers checks

En production, utilisez toujours HTTPS : sans chiffrement, les jetons d'authentification que vos clients envoient vers les registres privés circulent en clair sur le réseau. Orca termine le TLS lui-même, aucun reverse proxy supplémentaire n'est requis. Choisissez l'onglet selon votre contexte : des certificats fournis par votre PKI interne, un certificat Let's Encrypt obtenu automatiquement par ACME si le service est joignable depuis Internet, ou un certificat auto-signé réservé aux essais locaux.

config.yaml
varnish:
http:
- port: 80
https:
- port: 443
certificates:
- cert: /certs/tls.crt
private_key: /certs/tls.key

Un cache sans mesure ne prouve rien. La métrique qui décide de tout est le taux de hit : sous 50 %, votre cache travaille pour rien et il faut chercher pourquoi, souvent des tags flottants ou un TTL trop court. Orca exporte ces compteurs en OpenTelemetry, ce qui permet de les envoyer directement à Prometheus via son point d'entrée OTLP, sans collecteur intermédiaire. Voici ce que vous obtenez :

  • Taux de cache hit/miss par registre
  • Latence des requêtes
  • Bande passante économisée
  • Santé des backends
config.yaml
otel:
service_name: orca-production
metrics:
endpoint: http://prometheus:9090/api/v1/otlp/v1/metrics
protocol: http/protobuf
export_interval: 60

Par défaut, le cache est en mémoire et perdu au redémarrage. La version Premium permet de persister le cache sur disque :

config.yaml
varnish:
storage:
stores:
- name: disk1
path: /var/cache/orca/disk1
size: 100G

Commencez toujours par docker logs orca : Orca annonce sa version, celle de Varnish et l'échéance de sa licence dès les premières lignes. Les deux cas ci-dessous couvrent la quasi-totalité des démarrages ratés, et seul le premier est bloquant. Un conteneur qui reste en vie mais ne répond pas relève plutôt du temps de chargement des VCL, décrit plus haut.

SymptômeCauseSolution
Port 80 occupéAutre service (nginx, apache)Utilisez -p 8888:80 ou arrêtez le service
mlock() failedLimite mémoire verrouilléeWarning bénin, Orca fonctionne quand même

Ces erreurs remontent du client Docker, pas d'Orca : le message que vous lisez décrit ce que Docker a compris, pas ce qui s'est réellement passé côté cache. Le réflexe utile est donc de comparer les deux journaux, celui de docker et celui du conteneur, avant de modifier la configuration. Le premier symptôme piège systématiquement au premier essai, parce que Docker exige du HTTPS sur tout mirror qui n'est pas déclaré comme non sécurisé.

SymptômeCauseSolution
failed to do request: EOFDocker attend du HTTPSAjoutez "insecure-registries": ["localhost"]
UNAUTHORIZEDRegistre privé sans authConfigurez docker login
404 Not FoundMauvais routing de registreVérifiez le subdomain (ex: quay.localhost)

Un docker pull rapide ne prouve rien : Docker peut avoir servi une couche déjà présente localement. La preuve se lit dans les compteurs de Varnish. Lancez varnishstat avant puis après un pull, et comparez : MAIN.cache_hit doit progresser, MAIN.cache_miss rester stable. Sur une instance fraîchement démarrée, les deux valent zéro, ce qui est normal et non un signe de panne.

Fenêtre de terminal
# Health check
curl -I http://localhost/healthz
# Voir les logs
docker logs orca
# Métriques de cache (si varnishstat disponible)
docker exec orca varnishstat -1 | grep "cache_hit\|cache_miss"

Ce message apparaît au démarrage :

Warning: mlock() of VSM failed: Cannot allocate memory (12)

C'est bénin. Varnish tente de verrouiller sa mémoire partagée (VSM) en RAM pour éviter qu'elle soit swappée. Sur Docker avec des limites mémoire, cette opération peut échouer, mais Orca fonctionne correctement sans.

La ligne de partage est nette : la version gratuite couvre le cache des registres publics, tout ce qui touche au contrôle, à la persistance et aux registres privés relève du Premium. Concrètement, une instance Free perd son cache à chaque redémarrage et ne sait pas mettre en cache un registre authentifié. Les binaires du firewall sont bien présents dans l'image publique, mais le composant refuse de démarrer sans licence, ce n'est donc pas une piste de contournement.

FonctionnalitéFreePremium
Cache registres publics
TLS (HTTPS)
Cache mémoire
Métriques OpenTelemetry
Tracing OpenTelemetry
Cache registres privés
Stockage persistant (disque)
Programmabilité VCL
Mirror Git
Artifact Firewall (allow/hide/deny/quarantine)
Support

La licence Free est embarquée dans l'image et valide environ 1 an après la date de release. L'image 0.15.0, publiée le 14 juillet 2026, annonce au démarrage License: Expires 2027-07-12. Pour continuer à utiliser Orca gratuitement, mettez à jour vers une version plus récente avant cette échéance. La date exacte se lit dans docker logs orca dès les premières secondes.

Tout ce qui précède fait d'Orca un cache : il accélère et résiste aux pannes, mais il sert tout ce qu'on lui demande. Il ne décide pas si une dépendance a le droit d'entrer. C'est précisément le rôle de l'Artifact Firewall, la brique Premium d'Orca.

Activé par enable_firewall: true sur un virtual registry, le firewall évalue chaque résolution contre des règles et rend une décision : allow (servir), hide (masquer la version), deny (refuser) ou quarantine (retenir un package trop récent). Vous bloquez ainsi un package malveillant connu, une version vulnérable ou un nom interne usurpé (dependency confusion) avant qu'il n'entre dans vos builds.

Le firewall est un addon de licence Premium : sur l'image publique, le cache fonctionne mais le firewall ne démarre pas tant qu'une licence valide n'est pas fournie. Varnish propose une licence d'essai pour le tester.

Si vous utilisez un gestionnaire d'artefacts payant comme JFrog Artifactory, AWS ECR, Azure ACR ou Google Artifact Registry, Orca peut réduire votre facture.

Pourquoi ? Ces services facturent généralement le transfert de données (egress). Chaque docker pull ou npm install depuis votre CI/CD compte comme du trafic sortant facturable.

Avec Orca, vos pipelines tirent les artefacts depuis le cache local au lieu du registre distant. Résultat : moins de transfert = moins de coûts.

  • Orca est un Virtual Registry Manager : il cache les artefacts (Docker, NPM, Go, Helm) au niveau HTTP
  • Gain de performance 4x sur les pulls d'images Docker depuis le cache
  • Réduction de 75%+ du trafic sortant vers les registres
  • Résilience : continue de servir les artefacts même si Docker Hub tombe
  • Configuration YAML simple : pas de VCL à écrire, déploiement en 2 minutes
  • Routing par subdomain : npmjs.localhost pour NPM, ghcr.localhost pour GHCR, etc.
  • OpenTelemetry intégré pour surveiller le taux de cache hit
  • Économies JFrog/ECR/ACR : réduction de 50-70% sur les factures de registres payants grâce à la diminution du transfert de données

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn