Ein Docker Swarm Mode sichert den Ausfall eines Systems ab. Dabei werden die Stacks oder Services von einem Node zum anderen geschoben. Dazu muss für den neuen Node jedoch gegebenenfalls das Image neu aus dem Internet geladen werden. Da die Zugriffe auf das Docker Hub limitiert sind, macht es ggf. Sinn einen eigenen Cache aufzusetzen, über den die Daten nur einmalig geladen werden.
Das Vorgehen ist recht einfach. Verzeichnisse erstellen für den Container:
mkdir /mnt/cephfs/containers/docker-registry
mkdir /mnt/cephfs/containers/docker-registry/data
mkdir /mnt/cephfs/containers/docker-registry/config
Datei für die Einstellungen der Registry erstellen und befüllen:
nano /mnt/cephfs/containers/docker-registry/config/config.yml
Die Datei wird mit folgendem Inhalt befüllt
version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
delete:
enabled: true
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
proxy:
remoteurl: https://registry-1.docker.io
Jetzt kann in Portainer ein neuer Stack angelegt werden (Name: docker-registry), mit diesem Inhalt:
version: "3.2"
services:
docker-registry:
image: registry:2
restart: unless-stopped
ports:
- 5000:5000
volumes:
- /mnt/cephfs/containers/docker-registry/data/:/var/lib/registry/
- /mnt/cephfs/containers/docker-registry/config/config.yml:/etc/docker/registry/config.yml
# Docker Swarm Single
deploy:
mode: replicated
replicas: 1
placement:
constraints: [node.role == manager]
update_config:
parallelism: 1
delay: 120s
Als letzten Schritt muss noch dem Portainer erklärt werden, dass er von nunan diesen Registry Cache erwenden soll. Das muss auf allen Cluster-Nodes umgesetzt werden:
nano /etc/docker/daemon.json
Hier wird der Ort der Registry und der Vermerk eingetragen, dass über http abgefragt wird.
{
"log-driver": "journald",
"insecure-registries": ["http://<<YOURIP-OR-FQDN>>:5000"]
}
Danach kann der Docker Deamon neugestartet werden.
systemctl restart docker
Einen Testaufruf, ob die registry verfügbar ist, kann man wie folgt durchfühern:
curl -v http://<<YOURIP-OR-FQDN>>:5000
Danach muss jeder Stack angepasst werden. Statt des Images als „Default-Angabe“ muss nun die andere Registry verwendet werden. Beispielsweise:
services:
web:
image: example.com:5000/group/project:latest
Die Ausfallzeit für Portainer lag nun bei mir bei 15 Sekunden.
Als letztes wird noch ein Docker Stack erstellt, der alle 24 Stunden aufräumt. Insbesondere bei Migrates oder Failovers bleiben einige Fragmente (images) für eventuelle Rollbacks übrig. Um den Speicherplatz automatisch wieder freizugeben, macht dieser Stack sinn:
version: '3.7'
x-default-opts:
&default-opts
logging:
options:
max-size: "1m"
# driver: "gelf"
# options:
# gelf-address: "udp://127.0.0.1:5000"
services:
docker-system-prune:
image: docker.home.mxxh.me:5000/alpinelinux/docker-cli
# 86400 = 24h
command: sh -c "while true; do docker image prune -af; sleep 86400; done"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
logging:
driver: json-file
deploy:
mode: global
Quellen:
https://hub.docker.com/_/registry
https://distribution.github.io/distribution/about/configuration/
https://forums.docker.com/t/docker-compose-error-local-registry-isolated-server/134746/8
https://geek-cookbook.funkypenguin.co.nz/docker-swarm/registry/
https://forum.hilscher.com/thread-793.html
https://docs.portainer.io/admin/registries/manage
https://github.com/distribution/distribution/blob/main/cmd/registry/config-example.yml
https://stackoverflow.com/questions/49674004/docker-repository-server-gave-http-response-to-https-client
https://github.com/moby/moby/issues/31254