[{"data":1,"prerenderedAt":915},["ShallowReactive",2],{"docs-nav":3,"/docs/installation/docker":60},[4],{"title":5,"path":6,"stem":7,"children":8,"page":59},"Docs","/docs","docs",[9,27,45],{"title":10,"path":11,"stem":12,"children":13,"page":-1},"Premiers pas","/docs/getting-started","docs/1.getting-started/index",[14,15,19,23],{"title":10,"path":11,"stem":12},{"title":16,"path":17,"stem":18},"Introduction","/docs/getting-started/introduction","docs/1.getting-started/1.introduction",{"title":20,"path":21,"stem":22},"Claim, Adopt, Fork","/docs/getting-started/concepts","docs/1.getting-started/2.concepts",{"title":24,"path":25,"stem":26},"Architecture","/docs/getting-started/architecture","docs/1.getting-started/3.architecture",{"title":28,"path":29,"stem":30,"children":31,"page":-1},"Installation","/docs/installation","docs/2.installation/index",[32,33,37,41],{"title":28,"path":29,"stem":30},{"title":34,"path":35,"stem":36},"Déploiement Docker","/docs/installation/docker","docs/2.installation/1.docker",{"title":38,"path":39,"stem":40},"Déploiement VPS","/docs/installation/vps","docs/2.installation/2.vps",{"title":42,"path":43,"stem":44},"Déploiement Alwaysdata","/docs/installation/alwaysdata","docs/2.installation/3.alwaysdata",{"title":46,"path":47,"stem":48,"children":49,"page":-1},"Administration","/docs/administration","docs/3.administration/index",[50,51,55],{"title":46,"path":47,"stem":48},{"title":52,"path":53,"stem":54},"Configuration","/docs/administration/configuration","docs/3.administration/1.configuration",{"title":56,"path":57,"stem":58},"Maintenance","/docs/administration/maintenance","docs/3.administration/2.maintenance",false,{"id":61,"title":34,"body":62,"description":910,"extension":911,"meta":912,"navigation":501,"path":35,"seo":913,"stem":36,"__hash__":914},"docs/docs/2.installation/1.docker.md",{"type":63,"value":64,"toc":899},"minimark",[65,69,81,86,99,114,117,121,124,165,168,223,226,228,232,358,378,400,402,406,412,448,469,471,475,478,621,638,640,644,702,704,708,744,752,754,758,765,801,809,811,815,887,895],[66,67,34],"h1",{"id":68},"déploiement-docker",[70,71,72,76,77,80],"p",{},[73,74,75],"strong",{},"Difficulté"," : Intermédiaire | ",[73,78,79],{},"Temps"," : 20–30 min",[82,83,85],"h2",{"id":84},"prérequis","Prérequis",[87,88,89,93,96],"ul",{},[90,91,92],"li",{},"Docker 24+ et Docker Compose 2.x",[90,94,95],{},"Domaine avec un enregistrement DNS pointant sur le serveur",[90,97,98],{},"Ports 80 et 443 disponibles",[100,101,102],"blockquote",{},[70,103,104,105,109,110,113],{},"Vous n'avez rien à écrire vous-même. Le dépôt fournit le ",[106,107,108],"code",{},"Dockerfile",", le ",[106,111,112],{},"docker-compose.yml",", le template nginx et un script d'installation. Ce guide décrit ce qu'ils font.",[115,116],"hr",{},[82,118,120],{"id":119},"_1-installation-assistée","1. Installation assistée",[70,122,123],{},"C'est la voie recommandée. Le script est interactif : il vous demande votre domaine et une adresse e-mail d'administration.",[125,126,131],"pre",{"className":127,"code":128,"language":129,"meta":130,"style":130},"language-bash shiki shiki-themes github-light github-dark","git clone https://github.com/RebelliousSmile/suddenly.git\ncd suddenly\n./scripts/install.sh\n","bash","",[106,132,133,149,159],{"__ignoreMap":130},[134,135,138,142,146],"span",{"class":136,"line":137},"line",1,[134,139,141],{"class":140},"sScJk","git",[134,143,145],{"class":144},"sZZnC"," clone",[134,147,148],{"class":144}," https://github.com/RebelliousSmile/suddenly.git\n",[134,150,152,156],{"class":136,"line":151},2,[134,153,155],{"class":154},"sj4cs","cd",[134,157,158],{"class":144}," suddenly\n",[134,160,162],{"class":136,"line":161},3,[134,163,164],{"class":140},"./scripts/install.sh\n",[70,166,167],{},"Le script enchaîne :",[169,170,171,174,193,200,207,216],"ol",{},[90,172,173],{},"vérification de Docker et Docker Compose ;",[90,175,176,177,180,181,184,185,192],{},"génération d'une ",[106,178,179],{},"SECRET_KEY"," et d'un mot de passe PostgreSQL, écrits dans un ",[106,182,183],{},".env"," neuf — ",[73,186,187,188,191],{},"inutile de copier ",[106,189,190],{},".env.example"," au préalable"," ;",[90,194,195,196,199],{},"génération de ",[106,197,198],{},"nginx/conf.d/suddenly.conf"," à partir du template, avec votre domaine ;",[90,201,202,203,206],{},"obtention d'un certificat Let's Encrypt (",[106,204,205],{},"certbot certonly --webroot",") ;",[90,208,209,212,213,192],{},[106,210,211],{},"docker compose pull && up -d",", puis ",[106,214,215],{},"migrate",[90,217,218,219,222],{},"création du compte administrateur (",[106,220,221],{},"createsuperuser",", interactif).",[70,224,225],{},"À la fin, l'instance répond en HTTPS sur votre domaine.",[115,227],{},[82,229,231],{"id":230},"_2-ce-que-compose-démarre","2. Ce que compose démarre",[233,234,235,251],"table",{},[236,237,238],"thead",{},[239,240,241,245,248],"tr",{},[242,243,244],"th",{},"Service",[242,246,247],{},"Image",[242,249,250],{},"Rôle",[252,253,254,272,287,302,316,328,343],"tbody",{},[239,255,256,262,265],{},[257,258,259],"td",{},[106,260,261],{},"web",[257,263,264],{},"build local",[257,266,267,268,271],{},"Django + gunicorn (",[106,269,270],{},"suddenly.wsgi:application",")",[239,273,274,279,284],{},[257,275,276],{},[106,277,278],{},"db",[257,280,281],{},[106,282,283],{},"postgres:16-alpine",[257,285,286],{},"Base de données",[239,288,289,294,299],{},[257,290,291],{},[106,292,293],{},"redis",[257,295,296],{},[106,297,298],{},"redis:7-alpine",[257,300,301],{},"Cache + broker Celery",[239,303,304,309,311],{},[257,305,306],{},[106,307,308],{},"celery",[257,310,264],{},[257,312,313],{},[106,314,315],{},"celery -A suddenly worker",[239,317,318,323,325],{},[257,319,320],{},[106,321,322],{},"celery-beat",[257,324,264],{},[257,326,327],{},"Tâches planifiées (scheduler en base)",[239,329,330,335,340],{},[257,331,332],{},[106,333,334],{},"nginx",[257,336,337],{},[106,338,339],{},"nginx:alpine",[257,341,342],{},"Terminaison TLS, statiques et médias — seul service exposé (80/443)",[239,344,345,350,355],{},[257,346,347],{},[106,348,349],{},"certbot",[257,351,352],{},[106,353,354],{},"certbot/certbot",[257,356,357],{},"Renouvellement du certificat toutes les 12 h",[70,359,360,361,363,364,367,368,371,372,371,374,377],{},"Le conteneur ",[106,362,261],{}," exécute ",[106,365,366],{},"scripts/entrypoint.sh"," au démarrage : ",[106,369,370],{},"collectstatic",", ",[106,373,215],{},[106,375,376],{},"createcachetable",", puis gunicorn. Les migrations sont donc appliquées à chaque déploiement, sans intervention.",[70,379,380,381,371,384,371,387,371,390,371,393,371,396,399],{},"Volumes persistants : ",[106,382,383],{},"pgdata",[106,385,386],{},"redisdata",[106,388,389],{},"static",[106,391,392],{},"media",[106,394,395],{},"certs",[106,397,398],{},"certbot-webroot",".",[115,401],{},[82,403,405],{"id":404},"_3-variables-denvironnement","3. Variables d'environnement",[70,407,408,409,411],{},"Le script écrit un ",[106,410,183],{}," fonctionnel. Les clés qui comptent :",[125,413,415],{"className":127,"code":414,"language":129,"meta":130,"style":130},"DOMAIN=votre-domaine.com\nSECRET_KEY=genere-par-le-script\nPOSTGRES_PASSWORD=genere-par-le-script\n",[106,416,417,430,439],{"__ignoreMap":130},[134,418,419,423,427],{"class":136,"line":137},[134,420,422],{"class":421},"sVt8B","DOMAIN",[134,424,426],{"class":425},"szBVR","=",[134,428,429],{"class":144},"votre-domaine.com\n",[134,431,432,434,436],{"class":136,"line":151},[134,433,179],{"class":421},[134,435,426],{"class":425},[134,437,438],{"class":144},"genere-par-le-script\n",[134,440,441,444,446],{"class":136,"line":161},[134,442,443],{"class":421},"POSTGRES_PASSWORD",[134,445,426],{"class":425},[134,447,438],{"class":144},[70,449,450,453,454,456,457,460,461,464,465,468],{},[106,451,452],{},"DJANGO_SETTINGS_MODULE=config.settings.production"," est déjà positionné dans le ",[106,455,112],{}," : c'est lui qui active ",[106,458,459],{},"DEBUG=False",", les cookies ",[106,462,463],{},"Secure"," et HSTS. Voir la page ",[466,467,52],"a",{"href":53}," pour les variables optionnelles (Redis, e-mail, stockage S3/R2).",[115,470],{},[82,472,474],{"id":473},"_4-installation-manuelle","4. Installation manuelle",[70,476,477],{},"Si vous préférez piloter chaque étape (certificat déjà en place, reverse-proxy externe…) :",[125,479,481],{"className":127,"code":480,"language":129,"meta":130,"style":130},"git clone https://github.com/RebelliousSmile/suddenly.git\ncd suddenly\n\ncp .env.example .env\nnano .env                      # DOMAIN, SECRET_KEY, POSTGRES_PASSWORD\n\ndocker compose build\ndocker compose up -d db redis\ndocker compose run --rm web python manage.py migrate\ndocker compose run --rm web python manage.py createsuperuser\ndocker compose up -d\n",[106,482,483,491,497,503,515,528,533,545,564,589,609],{"__ignoreMap":130},[134,484,485,487,489],{"class":136,"line":137},[134,486,141],{"class":140},[134,488,145],{"class":144},[134,490,148],{"class":144},[134,492,493,495],{"class":136,"line":151},[134,494,155],{"class":154},[134,496,158],{"class":144},[134,498,499],{"class":136,"line":161},[134,500,502],{"emptyLinePlaceholder":501},true,"\n",[134,504,506,509,512],{"class":136,"line":505},4,[134,507,508],{"class":140},"cp",[134,510,511],{"class":144}," .env.example",[134,513,514],{"class":144}," .env\n",[134,516,518,521,524],{"class":136,"line":517},5,[134,519,520],{"class":140},"nano",[134,522,523],{"class":144}," .env",[134,525,527],{"class":526},"sJ8bj","                      # DOMAIN, SECRET_KEY, POSTGRES_PASSWORD\n",[134,529,531],{"class":136,"line":530},6,[134,532,502],{"emptyLinePlaceholder":501},[134,534,536,539,542],{"class":136,"line":535},7,[134,537,538],{"class":140},"docker",[134,540,541],{"class":144}," compose",[134,543,544],{"class":144}," build\n",[134,546,548,550,552,555,558,561],{"class":136,"line":547},8,[134,549,538],{"class":140},[134,551,541],{"class":144},[134,553,554],{"class":144}," up",[134,556,557],{"class":154}," -d",[134,559,560],{"class":144}," db",[134,562,563],{"class":144}," redis\n",[134,565,567,569,571,574,577,580,583,586],{"class":136,"line":566},9,[134,568,538],{"class":140},[134,570,541],{"class":144},[134,572,573],{"class":144}," run",[134,575,576],{"class":154}," --rm",[134,578,579],{"class":144}," web",[134,581,582],{"class":144}," python",[134,584,585],{"class":144}," manage.py",[134,587,588],{"class":144}," migrate\n",[134,590,592,594,596,598,600,602,604,606],{"class":136,"line":591},10,[134,593,538],{"class":140},[134,595,541],{"class":144},[134,597,573],{"class":144},[134,599,576],{"class":154},[134,601,579],{"class":144},[134,603,582],{"class":144},[134,605,585],{"class":144},[134,607,608],{"class":144}," createsuperuser\n",[134,610,612,614,616,618],{"class":136,"line":611},11,[134,613,538],{"class":140},[134,615,541],{"class":144},[134,617,554],{"class":144},[134,619,620],{"class":154}," -d\n",[70,622,623,624,627,628,630,631,634,635,399],{},"Le template nginx (",[106,625,626],{},"nginx/conf.d/suddenly.conf.template",") doit être rendu avant de démarrer le conteneur ",[106,629,334],{}," — c'est ce que fait ",[106,632,633],{},"install.sh"," avec ",[106,636,637],{},"envsubst",[115,639],{},[82,641,643],{"id":642},"_5-vérification","5. Vérification",[125,645,647],{"className":127,"code":646,"language":129,"meta":130,"style":130},"docker compose ps\ndocker compose logs -f web\n\ncurl https://votre-domaine.com/health/          # {\"status\": \"ok\"}\ncurl https://votre-domaine.com/.well-known/nodeinfo\ncurl \"https://votre-domaine.com/.well-known/webfinger?resource=acct:admin@votre-domaine.com\"\n",[106,648,649,658,673,677,688,695],{"__ignoreMap":130},[134,650,651,653,655],{"class":136,"line":137},[134,652,538],{"class":140},[134,654,541],{"class":144},[134,656,657],{"class":144}," ps\n",[134,659,660,662,664,667,670],{"class":136,"line":151},[134,661,538],{"class":140},[134,663,541],{"class":144},[134,665,666],{"class":144}," logs",[134,668,669],{"class":154}," -f",[134,671,672],{"class":144}," web\n",[134,674,675],{"class":136,"line":161},[134,676,502],{"emptyLinePlaceholder":501},[134,678,679,682,685],{"class":136,"line":505},[134,680,681],{"class":140},"curl",[134,683,684],{"class":144}," https://votre-domaine.com/health/",[134,686,687],{"class":526},"          # {\"status\": \"ok\"}\n",[134,689,690,692],{"class":136,"line":517},[134,691,681],{"class":140},[134,693,694],{"class":144}," https://votre-domaine.com/.well-known/nodeinfo\n",[134,696,697,699],{"class":136,"line":530},[134,698,681],{"class":140},[134,700,701],{"class":144}," \"https://votre-domaine.com/.well-known/webfinger?resource=acct:admin@votre-domaine.com\"\n",[115,703],{},[82,705,707],{"id":706},"_6-mise-à-jour","6. Mise à jour",[125,709,711],{"className":127,"code":710,"language":129,"meta":130,"style":130},"git pull origin main\ndocker compose build\ndocker compose up -d\n",[106,712,713,726,734],{"__ignoreMap":130},[134,714,715,717,720,723],{"class":136,"line":137},[134,716,141],{"class":140},[134,718,719],{"class":144}," pull",[134,721,722],{"class":144}," origin",[134,724,725],{"class":144}," main\n",[134,727,728,730,732],{"class":136,"line":151},[134,729,538],{"class":140},[134,731,541],{"class":144},[134,733,544],{"class":144},[134,735,736,738,740,742],{"class":136,"line":161},[134,737,538],{"class":140},[134,739,541],{"class":144},[134,741,554],{"class":144},[134,743,620],{"class":154},[70,745,746,747,749,750,399],{},"Inutile de lancer ",[106,748,215],{}," : l'entrypoint s'en charge au redémarrage du conteneur ",[106,751,261],{},[115,753],{},[82,755,757],{"id":756},"sauvegarde-et-restauration","Sauvegarde et restauration",[70,759,760,761,764],{},"Le dépôt fournit deux scripts plutôt qu'un ",[106,762,763],{},"pg_dump"," manuel :",[125,766,768],{"className":127,"code":767,"language":129,"meta":130,"style":130},"./scripts/backup.sh [dossier]   # dump PostgreSQL + médias + .env, purge au-delà de 7 jours\n./scripts/restore.sh \u003Cprefixe>  # interactif : DROP DATABASE puis restauration\n",[106,769,770,781],{"__ignoreMap":130},[134,771,772,775,778],{"class":136,"line":137},[134,773,774],{"class":140},"./scripts/backup.sh",[134,776,777],{"class":421}," [dossier]   ",[134,779,780],{"class":526},"# dump PostgreSQL + médias + .env, purge au-delà de 7 jours\n",[134,782,783,786,789,792,795,798],{"class":136,"line":151},[134,784,785],{"class":140},"./scripts/restore.sh",[134,787,788],{"class":425}," \u003C",[134,790,791],{"class":144},"prefix",[134,793,794],{"class":421},"e",[134,796,797],{"class":425},">",[134,799,800],{"class":526},"  # interactif : DROP DATABASE puis restauration\n",[100,802,803],{},[70,804,805,808],{},[106,806,807],{},"restore.sh"," détruit la base avant de la recréer. Il demande confirmation, mais lisez ce qu'il vous propose.",[115,810],{},[82,812,814],{"id":813},"dépannage","Dépannage",[233,816,817,827],{},[236,818,819],{},[239,820,821,824],{},[242,822,823],{},"Problème",[242,825,826],{},"Solution",[252,828,829,839,849,863,877],{},[239,830,831,834],{},[257,832,833],{},"Conteneur ne démarre pas",[257,835,836],{},[106,837,838],{},"docker compose logs [service]",[239,840,841,844],{},[257,842,843],{},"Erreur de connexion DB",[257,845,846],{},[106,847,848],{},"docker compose exec db pg_isready -U suddenly",[239,850,851,854],{},[257,852,853],{},"Erreur 502 Bad Gateway",[257,855,856,857,859,860],{},"Vérifier que ",[106,858,261],{}," tourne : ",[106,861,862],{},"docker compose ps",[239,864,865,870],{},[257,866,867],{},[106,868,869],{},"ModuleNotFoundError: config.wsgi",[257,871,872,873,876],{},"Le module WSGI est ",[106,874,875],{},"suddenly.wsgi"," — vous avez une commande gunicorn personnalisée à corriger",[239,878,879,882],{},[257,880,881],{},"Réinitialisation complète",[257,883,884],{},[106,885,886],{},"docker compose down -v && docker compose build --no-cache && docker compose up -d",[100,888,889],{},[70,890,891,894],{},[106,892,893],{},"docker compose down -v"," supprime les volumes — toutes les données seront perdues.",[896,897,898],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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 .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":130,"searchDepth":151,"depth":151,"links":900},[901,902,903,904,905,906,907,908,909],{"id":84,"depth":151,"text":85},{"id":119,"depth":151,"text":120},{"id":230,"depth":151,"text":231},{"id":404,"depth":151,"text":405},{"id":473,"depth":151,"text":474},{"id":642,"depth":151,"text":643},{"id":706,"depth":151,"text":707},{"id":756,"depth":151,"text":757},{"id":813,"depth":151,"text":814},"Déployer Suddenly avec Docker Compose en production.","md",{},{"title":34,"description":910},"qrhCVzdB5eT7zWDAo5f61vKsAejCkL8eZ1ONtsm1bjE",1784021864437]