[{"data":1,"prerenderedAt":904},["ShallowReactive",2],{"\u002Fv5\u002Fdodock\u002Fdeveloppeurs\u002Farchitecture\u002Farchitecture-technique":3,"section:\u002Fv5\u002Fdodock\u002Fdeveloppeurs\u002Farchitecture\u002Farchitecture-technique":903},{"id":4,"title":5,"body":6,"description":888,"extension":889,"meta":890,"navigation":892,"path":899,"seo":900,"stem":901,"__hash__":902},"docs\u002F1.v5\u002F3.dodock\u002F10.developpeurs\u002F01.architecture\u002F1.architecture-technique.md","Architecture technique",{"type":7,"value":8,"toc":866},"minimark",[9,13,17,22,38,45,50,120,124,131,153,156,159,163,167,275,278,285,288,291,294,327,336,338,342,349,359,361,365,376,387,391,441,445,455,464,470,474,535,538,543,550,573,611,617,623,633,635,639,642,663,685,687,693,768,774,776,780,828,830,834,862],[10,11,5],"h1",{"id":12},"architecture-technique",[14,15,16],"p",{},"Dodock est un framework applicatif complet, piloté par les métadonnées. Il gère la base de données, le cache, les tâches de fond et les notifications en temps réel des applications métier.",[18,19,21],"h2",{"id":20},"vue-densemble","Vue d'ensemble",[14,23,24,25,29,30,33,34,37],{},"L'architecture de Dodock s'organise autour du concept de ",[26,27,28],"strong",{},"bench"," : un environnement qui héberge plusieurs ",[26,31,32],{},"sites"," (tenants) partageant les mêmes ",[26,35,36],{},"applications",".",[14,39,40],{},[41,42],"img",{"alt":43,"src":44},"Architecture Dodock","\u002Fimages\u002Fdodock\u002Fdeveloppeurs\u002Farchitecture\u002Farchitecture.svg",[46,47,49],"h3",{"id":48},"concepts-clés","Concepts clés",[51,52,53,66],"table",{},[54,55,56],"thead",{},[57,58,59,63],"tr",{},[60,61,62],"th",{},"Concept",[60,64,65],{},"Description",[67,68,69,80,90,100,110],"tbody",{},[57,70,71,77],{},[72,73,74],"td",{},[26,75,76],{},"Bench",[72,78,79],{},"Environnement complet contenant applications, sites et processus",[57,81,82,87],{},[72,83,84],{},[26,85,86],{},"Application",[72,88,89],{},"Package Python qui étend le framework (dodock, dokos, etc.)",[57,91,92,97],{},[72,93,94],{},[26,95,96],{},"Site",[72,98,99],{},"Tenant avec sa propre base de données et configuration",[57,101,102,107],{},[72,103,104],{},[26,105,106],{},"DocType",[72,108,109],{},"Définition d'un type de document (schéma + comportements)",[57,111,112,117],{},[72,113,114],{},[26,115,116],{},"Document",[72,118,119],{},"Instance d'un DocType (enregistrement en base)",[46,121,123],{"id":122},"architecture-multi-tenant","Architecture multi-tenant",[14,125,126,127,130],{},"Dodock est une plateforme ",[26,128,129],{},"multi-tenant",". Chaque tenant (appelé \"site\") possède :",[132,133,134,141,148],"ul",{},[135,136,137,138],"li",{},"Sa propre ",[26,139,140],{},"base de données",[135,142,143,144,147],{},"Ses propres ",[26,145,146],{},"fichiers"," uploadés",[135,149,137,150],{},[26,151,152],{},"configuration",[14,154,155],{},"Les applications sont partagées entre tous les sites du bench.",[157,158],"hr",{},[18,160,162],{"id":161},"pile-technique","Pile technique",[46,164,166],{"id":165},"composants-principaux","Composants principaux",[51,168,169,182],{},[54,170,171],{},[57,172,173,176,179],{},[60,174,175],{},"Composant",[60,177,178],{},"Technologie",[60,180,181],{},"Rôle",[67,183,184,203,216,230,248,262],{},[57,185,186,189,195],{},[72,187,188],{},"Base de données",[72,190,191,194],{},[26,192,193],{},"MariaDB"," (PostgreSQL et SQLite existent aussi)",[72,196,197,198,202],{},"Stockage des données. La clé ",[199,200,201],"code",{},"db_type"," du site choisit le moteur",[57,204,205,208,213],{},[72,206,207],{},"Cache",[72,209,210],{},[26,211,212],{},"Redis",[72,214,215],{},"Cache, files d'attente, pub\u002Fsub",[57,217,218,221,227],{},[72,219,220],{},"Backend",[72,222,223,226],{},[26,224,225],{},"Python"," (Werkzeug, Gunicorn)",[72,228,229],{},"Logique métier et API REST",[57,231,232,235,245],{},[72,233,234],{},"Temps réel",[72,236,237,240,241,244],{},[26,238,239],{},"Node.js"," (Socket.IO, ",[199,242,243],{},"socketio.js",")",[72,246,247],{},"Notifications en direct",[57,249,250,253,259],{},[72,251,252],{},"Frontend",[72,254,255,258],{},[26,256,257],{},"JavaScript"," (Vue.js)",[72,260,261],{},"Interface utilisateur",[57,263,264,267,272],{},[72,265,266],{},"Reverse Proxy",[72,268,269],{},[26,270,271],{},"Nginx",[72,273,274],{},"Routage et SSL (production)",[46,276,193],{"id":277},"mariadb",[14,279,280,281,284],{},"MariaDB stocke toutes les données : documents, métadonnées des DocTypes, utilisateurs et configurations. ",[26,282,283],{},"Chaque site possède sa propre base de données"," : sur un bench qui héberge plusieurs sites, les données de chaque site restent séparées.",[14,286,287],{},"En production, utilisez MariaDB : c'est le moteur recommandé en v5. SQLite sert seulement aux tests et au développement.",[46,289,212],{"id":290},"redis",[14,292,293],{},"Deux instances Redis assurent des fonctions distinctes :",[51,295,296,305],{},[54,297,298],{},[57,299,300,303],{},[60,301,302],{},"Instance",[60,304,181],{},[67,306,307,317],{},[57,308,309,314],{},[72,310,311],{},[26,312,313],{},"redis_cache",[72,315,316],{},"Cache en mémoire pour accélérer les lectures",[57,318,319,324],{},[72,320,321],{},[26,322,323],{},"redis_queue",[72,325,326],{},"Files d'attente des tâches de fond (RQ) et messages du temps réel",[14,328,329,330,333,334,37],{},"L'ancienne instance ",[199,331,332],{},"redis_socketio"," n'existe plus : le serveur temps réel utilise ",[199,335,323],{},[157,337],{},[18,339,341],{"id":340},"structure-des-répertoires","Structure des répertoires",[14,343,344,345,348],{},"L'initialisation d'un bench avec ",[199,346,347],{},"bench init"," crée cette structure :",[350,351,357],"pre",{"className":352,"code":354,"language":355,"meta":356},[353],"language-text","dokos-bench\u002F\n├── apps\u002F                         # Applications installées\n│   ├── frappe\u002F                   # Framework (obligatoire)\n│   ├── erpnext\u002F                  # Application métier\n│   └── custom_app\u002F               # Applications personnalisées\n│\n├── sites\u002F                        # Sites hébergés\n│   ├── assets\u002F                   # Assets compilés (JS, CSS)\n│   ├── apps.txt                  # Apps installables\n│   ├── common_site_config.json   # Configuration partagée\n│   └── monsite.localhost\u002F        # Répertoire du site\n│       ├── site_config.json      # Configuration du site\n│       ├── private\u002F              # Fichiers privés\n│       ├── public\u002F               # Fichiers publics\n│       └── locks\u002F                # Verrous de synchronisation\n│\n├── config\u002F                       # Configuration Redis\n│   ├── redis_cache.conf\n│   └── redis_queue.conf\n│\n├── logs\u002F                         # Journaux des processus\n├── env\u002F                          # Environnement virtuel Python\n└── Procfile                      # Définition des processus\n","text","",[199,358,354],{"__ignoreMap":356},[157,360],{},[18,362,364],{"id":363},"processus-et-services","Processus et services",[14,366,367,368,371,372,375],{},"L'exécution de Dodock nécessite des ",[26,369,370],{},"services système"," (base de données, cache) et des ",[26,373,374],{},"processus applicatifs"," (serveur web, workers).",[14,377,378,379,382,383,386],{},"Les services système dépendent de l'architecture de déploiement. Les processus applicatifs sont définis dans le ",[199,380,381],{},"Procfile"," en développement et dans ",[199,384,385],{},"config\u002Fsupervisor.conf"," en production.",[46,388,390],{"id":389},"services-système","Services système",[51,392,393,402],{},[54,394,395],{},[57,396,397,400],{},[60,398,399],{},"Service",[60,401,181],{},[67,403,404,413,422,431],{},[57,405,406,410],{},[72,407,408],{},[26,409,193],{},[72,411,412],{},"Base de données relationnelle",[57,414,415,419],{},[72,416,417],{},[26,418,212],{},[72,420,421],{},"Cache et files d'attente pour les workers",[57,423,424,428],{},[72,425,426],{},[26,427,271],{},[72,429,430],{},"Reverse proxy (production uniquement)",[57,432,433,438],{},[72,434,435],{},[26,436,437],{},"Supervisor",[72,439,440],{},"Gestion des processus (production uniquement)",[46,442,444],{"id":443},"processus-applicatifs","Processus applicatifs",[14,446,447,450,451,454],{},[26,448,449],{},"Serveur WSGI"," : répond aux requêtes HTTP. En développement, ",[199,452,453],{},"bench start"," lance le serveur Werkzeug. En production, Gunicorn est configuré automatiquement via Supervisor.",[14,456,457,460,461,463],{},[26,458,459],{},"Workers"," : exécutent les tâches de fond (emails, rapports, calculs). Démarrés automatiquement par ",[199,462,453],{}," en développement, configurés dans Supervisor en production.",[14,465,466,469],{},[26,467,468],{},"Scheduler"," : planifie l'exécution des tâches programmées (horaires, quotidiennes, etc.). Même gestion que les workers.",[46,471,473],{"id":472},"développement-vs-production","Développement vs Production",[51,475,476,489],{},[54,477,478],{},[57,479,480,483,486],{},[60,481,482],{},"Aspect",[60,484,485],{},"Développement",[60,487,488],{},"Production",[67,490,491,502,515,525],{},[57,492,493,496,500],{},[72,494,495],{},"Lancement",[72,497,498],{},[199,499,453],{},[72,501,437],{},[57,503,504,507,511],{},[72,505,506],{},"Configuration",[72,508,509],{},[199,510,381],{},[72,512,513],{},[199,514,385],{},[57,516,517,519,522],{},[72,518,449],{},[72,520,521],{},"Werkzeug (mono-thread)",[72,523,524],{},"Gunicorn (multi-workers)",[57,526,527,530,533],{},[72,528,529],{},"Reverse proxy",[72,531,532],{},"Non",[72,534,271],{},[46,536,537],{"id":537},"developer_mode",[14,539,540,542],{},[199,541,537],{}," est un paramètre distinct du mode de déploiement. Lorsqu'il est activé, les modifications apportées aux DocTypes, rapports et autres composants via l'interface sont répercutées dans le dépôt de l'application.",[14,544,545,546,549],{},"Cette option s'active dans le fichier ",[199,547,548],{},"site_config.json"," du site :",[350,551,555],{"className":552,"code":553,"language":554,"meta":356,"style":356},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","sites\u002F{votre_site}\u002Fsite_config.json\n","bash",[199,556,557],{"__ignoreMap":356},[558,559,562,566,570],"span",{"class":560,"line":561},"line",1,[558,563,565],{"class":564},"sBMFI","sites\u002F",[558,567,569],{"class":568},"sfazB","{votre_site}",[558,571,572],{"class":564},"\u002Fsite_config.json\n",[350,574,578],{"className":575,"code":576,"language":577,"meta":356,"style":356},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"developer_mode\": 1\n}\n","json",[199,579,580,586,605],{"__ignoreMap":356},[558,581,582],{"class":560,"line":561},[558,583,585],{"class":584},"sMK4o","{\n",[558,587,589,592,595,598,601],{"class":560,"line":588},2,[558,590,591],{"class":584},"  \"",[558,593,537],{"class":594},"spNyl",[558,596,597],{"class":584},"\"",[558,599,600],{"class":584},":",[558,602,604],{"class":603},"sbssI"," 1\n",[558,606,608],{"class":560,"line":607},3,[558,609,610],{"class":584},"}\n",[14,612,613,616],{},[26,614,615],{},"Activé"," : les modifications apportées aux DocTypes, rapports, scripts et autres composants sont sauvegardées dans le code source de l'application. Elles peuvent être versionnées avec Git, partagées et déployées sur d'autres instances.",[14,618,619,622],{},[26,620,621],{},"Désactivé"," : les modifications restent dans la base du site. Elles ne sont pas écrites dans le dépôt de l'application.",[14,624,625,626,628,629,632],{},"Activez ",[199,627,537],{}," seulement sur un site de développement. La commande ",[199,630,631],{},"bench set-config -g developer_mode 1"," l'active pour tous les sites du bench.",[157,634],{},[46,636,638],{"id":637},"résolution-du-site","Résolution du site",[14,640,641],{},"Pour une requête web, le framework choisit le site dans cet ordre :",[643,644,645,651,657],"ol",{},[135,646,647,648,244],{},"Le site imposé au serveur de développement (",[199,649,650],{},"bench serve --site",[135,652,653,654],{},"L'en-tête HTTP ",[199,655,656],{},"X-Frappe-Site-Name",[135,658,659,660,244],{},"Le nom d'hôte de la requête (en-tête ",[199,661,662],{},"Host",[14,664,665,666,668,669,672,673,676,677,680,681,684],{},"Pour une commande ",[199,667,28],{},", le site vient de l'option ",[199,670,671],{},"--site",", de la variable d'environnement ",[199,674,675],{},"FRAPPE_SITE"," ou du site par défaut (",[199,678,679],{},"bench use \u003Csite>","). Le fichier ",[199,682,683],{},"currentsite.txt"," n'est plus pris en charge.",[46,686,506],{"id":152},[14,688,689,690,692],{},"Chaque site possède un fichier ",[199,691,548],{}," :",[350,694,696],{"className":575,"code":695,"language":577,"meta":356,"style":356},"{\n  \"db_name\": \"site1_db\",\n  \"db_password\": \"••••••••\",\n  \"encryption_key\": \"••••••••\"\n}\n",[199,697,698,702,724,744,763],{"__ignoreMap":356},[558,699,700],{"class":560,"line":561},[558,701,585],{"class":584},[558,703,704,706,709,711,713,716,719,721],{"class":560,"line":588},[558,705,591],{"class":584},[558,707,708],{"class":594},"db_name",[558,710,597],{"class":584},[558,712,600],{"class":584},[558,714,715],{"class":584}," \"",[558,717,718],{"class":568},"site1_db",[558,720,597],{"class":584},[558,722,723],{"class":584},",\n",[558,725,726,728,731,733,735,737,740,742],{"class":560,"line":607},[558,727,591],{"class":584},[558,729,730],{"class":594},"db_password",[558,732,597],{"class":584},[558,734,600],{"class":584},[558,736,715],{"class":584},[558,738,739],{"class":568},"••••••••",[558,741,597],{"class":584},[558,743,723],{"class":584},[558,745,747,749,752,754,756,758,760],{"class":560,"line":746},4,[558,748,591],{"class":584},[558,750,751],{"class":594},"encryption_key",[558,753,597],{"class":584},[558,755,600],{"class":584},[558,757,715],{"class":584},[558,759,739],{"class":568},[558,761,762],{"class":584},"\"\n",[558,764,766],{"class":560,"line":765},5,[558,767,610],{"class":584},[14,769,770,771,37],{},"La configuration commune se trouve dans ",[199,772,773],{},"common_site_config.json",[157,775],{},[18,777,779],{"id":778},"cycle-de-vie-dune-requête","Cycle de vie d'une requête",[643,781,782,788,794,800,806,811,816,822],{},[135,783,784,787],{},[26,785,786],{},"Réception"," : Nginx reçoit la requête HTTP ou WebSocket",[135,789,790,793],{},[26,791,792],{},"Routage"," : Nginx route vers Gunicorn (HTTP) ou Socket.IO (WebSocket)",[135,795,796,799],{},[26,797,798],{},"Résolution"," : Le framework identifie le site (voir plus haut)",[135,801,802,805],{},[26,803,804],{},"Authentification"," : Vérification de la session utilisateur",[135,807,808,810],{},[26,809,207],{}," : Consultation du cache Redis",[135,812,813,815],{},[26,814,188],{}," : Requête MariaDB si nécessaire",[135,817,818,821],{},[26,819,820],{},"Logique métier"," : Exécution des contrôleurs et hooks",[135,823,824,827],{},[26,825,826],{},"Réponse"," : Sérialisation JSON\u002FHTML et envoi",[157,829],{},[18,831,833],{"id":832},"pour-aller-plus-loin","Pour aller plus loin",[835,836,837,846,854],"card-group",{},[838,839,843],"card",{"icon":840,"title":841,"to":842},"i-mdi-database-outline","Modèle de données","\u002Fv5\u002Fdodock\u002Fdeveloppeurs\u002Farchitecture\u002Fmodele-donnees",[14,844,845],{},"DocTypes, Documents et métadonnées",[838,847,851],{"icon":848,"title":849,"to":850},"i-mdi-folder-outline","Structure d'une application","\u002Fv5\u002Fdodock\u002Fdeveloppeurs\u002Farchitecture\u002Fstructure-application",[14,852,853],{},"Organisation et points d'extension",[838,855,859],{"icon":856,"title":857,"to":858},"i-mdi-console","Commandes Bench","\u002Fv5\u002Fadministrer\u002Fexploitation\u002Fbench\u002Fcommandes",[14,860,861],{},"Référence des commandes CLI",[863,864,865],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":356,"searchDepth":561,"depth":588,"links":867},[868,872,877,878,886,887],{"id":20,"depth":588,"text":21,"children":869},[870,871],{"id":48,"depth":607,"text":49},{"id":122,"depth":607,"text":123},{"id":161,"depth":588,"text":162,"children":873},[874,875,876],{"id":165,"depth":607,"text":166},{"id":277,"depth":607,"text":193},{"id":290,"depth":607,"text":212},{"id":340,"depth":588,"text":341},{"id":363,"depth":588,"text":364,"children":879},[880,881,882,883,884,885],{"id":389,"depth":607,"text":390},{"id":443,"depth":607,"text":444},{"id":472,"depth":607,"text":473},{"id":537,"depth":607,"text":537},{"id":637,"depth":607,"text":638},{"id":152,"depth":607,"text":506},{"id":778,"depth":588,"text":779},{"id":832,"depth":588,"text":833},"Vue d'ensemble de l'architecture technique de Dodock","md",{"icon":891,"reviewed":892,"last_verified":893,"sources":894},"i-icon-park-outline-building-four",true,"2026-11-04",[895,896,897,898],"dodock@v5:frappe\u002Fapp.py","dodock@v5:frappe\u002Fdatabase\u002F__init__.py","dodock@v5:frappe\u002Futils\u002Fbench_helper.py","dodock@v5:node_utils.js","\u002Fv5\u002Fdodock\u002Fdeveloppeurs\u002Farchitecture\u002Farchitecture-technique",{"title":5,"description":888},"1.v5\u002F3.dodock\u002F10.developpeurs\u002F01.architecture\u002F1.architecture-technique","bt2jrRVvntqi3v39tbk-kqveK_-F5mfkCS6XJvZH4xw",{},1794522727986]