Resolent Too many open files dins d’un contenidor a Docker Desktop
Aquí explico la solució a que treballes amb Linux, tens el Docker Desktop per a córrer contenidors, i dins d’un o més dels teus contenidors reps el missatge «Too Many Open Files».
Docker Desktop treballa diferent que Docker, i certament comporta uns quants problemes quan comences a donar-li canya.
Un dels problemes resideix en que els directoris locals del teu ordinador que montes dins el contenidor, utilitzen el procès virtiofsd per a fer aquesta màgia.
Aquest procès te un límit de 120.000 File Descriptors.
Això ho pots comprovar fàcilment (Max open files):
pidof virtiofsd
6417
cat /proc/6417/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 255202 255202 processes
Max open files 120000 120000 files
Max locked memory 8385822720 8385822720 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 255202 255202 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
Si treballes amb PHP i amb projectes Symfony, i Docker, molts cops es munta el directori del projecte de l’ordinador (li direm host) a una carpeta dins el contenidor Docker, que el servidor web o el PHP-FPM llegiran. Així des del teu ordinador, amb l’IDE, fas canvis al codi, i dins el contenidor els canvis són immediats i pots provar. Això es fa servir molt per a desenvolupar, definint els mapejos a docker-compose.yml.
Això és molt còmode però xoca amb els límits de Docker Desktop.
Quan tens un projecte petit no és problema, però si treballes amb projectes grans, la teva carpeta vendor tindrà decenes de milers d’arxius. La teva carpeta var on es genera la cache, també. I carpetes com node_modules també. Arribaran al límit i obtindràs errors indicant «Too many Open Files» que no et deixaran ni fer un php bin/console cache:clear

Podem aconseguir diverses instàncies de virtiofsd, separant els directoris als Docker Desktop tindrà accès.

Cada instància tindrà el límit de 120.000 File Descriptors.
És quelcom bastant pesat, ja que els projectes de Symfony tenen molts directoris amb molts arxius.
Si executem aquesta comanda podrem veure quants FD té cada procés:
lsof | awk '{print $1,$2}' | sort | uniq -c | sort -nr | head -10
En el meu cas em retorna:
333700 phpstorm 15539
318960 firefox 7378
223329 virtiofsd 6417
23920 cef_serve 15903
19807 gnome-she 3442
15873 Docker 6409
8778 Isolated 10013
8384 Isolated 9261
8250 Isolated 8817
8242 PanGPUI 3742
El primer número és la quantitat de descriptors que te el procés, després hi ha el nom del procés i finalment el seu PID.
Com podem veure el meu virtiofsd te 223.329 File Descriptors en ús. Molt més que el límit de 120.000 de virtiofsd.
Si mirem quants arxius hi ha a cada directori del projecte veurem que:
cd vendor
find . -type f | wc -l
60731
cd ../var
find . -type f | wc -l
14874
cd ../node_modules
find . -type f | wc -l
33795
La millor solució seria fer servir només Docker i no Docker Desktop. Però si desinstaleu Docker Desktop us esborrarà totes les imatges, així que si us heu trobat amb aquest error potser no podeu desintal·lar Docker Desktop a curt termini, i necessiteu una solució ràpida per a sortir del pas.
La solució que jo us proposo és moure els subdirectoris de Symfony var i node_modules amb desenes de milers d’arxius, al contenidor, enlloc de que formin part del mount entre l’ordinador i Docker.
D’aquesta manera deixem vendor, que encara que te desenes de milers d’arxius, és pràctic que el vostre IDE a l’ordinador local hi tingui accès, però reduïm en desenes de milers d’arxius la llista dels que virtiofsd està apuntant amb un FD.
Per a fer que var i node_modules no estiguin dins de la carpeta de projectes el que faig és moure aquestes carpetes, dins del Contenidor, a una altra ubicació dins del contenidor, per exemple:
move node_modules /var/www/
ln --symbolic /var/www/node_modules /var/www/projecte/node_modules
move var /var/www/
ln --symbolic /var/www/var /var/www/projecte/var
Si no podeu moure els directoris perquè us dóna error de Too many open files, podeu esborrar-los des del host, i des de dins del contenidor crear-los a /var/www o a la vostra ruta preferida del Contenidor.