[{"data":1,"prerenderedAt":4937},["ShallowReactive",2],{"profile-data":3,"blog-post-\u002Fblog\u002F43-dokploy-deploy-laravel-nuxt":88},{"id":4,"title":5,"availability":6,"avatar":20,"clientSatisfaction":21,"currentFocus":22,"description":26,"experience":27,"extension":28,"footer":29,"heroHeadline":32,"meta":33,"name":34,"pricingRanges":35,"projectsDelivered":46,"social":48,"stem":61,"tagline":62,"whoIWorkWith":63,"workApproach":83,"__hash__":87},"profile\u002Fprofile.yml","Senior Software Engineer | Full-Stack Developer | DevOps Enthusiast",{"status":7,"statusText":8,"startDate":9,"startDateContext":10,"description":11,"responseTime":12,"timezone":13,"slotsAvailable":14,"paymentTerms":15,"cta":16,"note":19},"available","Available for new projects","April 2025","Next opening","Open to freelance, consulting, and collaborative projects. Flexible with remote, async, and agile workflows. Comfortable working across time zones and with distributed teams.","3h","GMT+5",3,"20% upfront, rest on milestones",{"text":17,"url":18},"Email Now To Discuss Your Project Or Idea","mailto:mubaidr@gmail.com","I aim to reply as quickly as possible with the attention your message deserves.","\u002Fmubaidr.png",100,[23,24,25],"Infrastructure as Code (IaC)","Cloud-native tooling and observability","AI-assisted development workflows","Delivering robust, scalable, and user-focused software solutions that drive business success.",13,"yml",{"message":30,"lastUpdated":31},"Thank you for your interest. I look forward to collaborating and building something exceptional together.","2025-06-28T12:00:00.000Z","Senior Software Engineer building scalable systems and developer tools. Open source maintainer",{},"Muhammad Ubaid R.",{"mvp":36,"architectureAudit":41,"hourly":45},{"min":37,"max":38,"currency":39,"description":40},5000,15000,"USD","Full-stack MVP development",{"min":42,"max":43,"currency":39,"description":44},1500,3000,"System architecture review and recommendations",{"min":21,"max":46,"currency":39,"description":47},125,"Hourly consulting and development",[49,53,57],{"name":50,"url":51,"icon":52},"GitHub","https:\u002F\u002Fgithub.com\u002Fmubaidr","i-ph-github-logo",{"name":54,"url":55,"icon":56},"LinkedIn","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fmubaidr","i-ph-linkedin-logo",{"name":58,"url":59,"icon":60},"X","https:\u002F\u002Fx.com\u002Fmubaidr","i-ph-x-logo","profile","Delivered 125+ projects with 100% client satisfaction. 13 years building scalable systems.",[64,68,72,75,79],{"name":65,"icon":66,"description":67},"Startups","i-ph-rocket-launch","Early-stage companies building MVPs and scaling products",{"name":69,"icon":70,"description":71},"SMEs","i-ph-buildings","Small to medium enterprises optimizing and modernizing systems",{"name":73,"icon":70,"description":74},"Enterprise","Large organizations requiring architecture and performance expertise",{"name":76,"icon":77,"description":78},"Agencies","i-ph-users-three","Digital agencies needing technical leadership and delivery support",{"name":80,"icon":81,"description":82},"Individual Founders","i-ph-user","Solo founders turning ideas into production-ready applications",[84,85,86],"Architecting solutions and managing product lifecycles - optimizing performance, scalability, and security","Leading agile teams and collaborating with clients - Ensuring clarity, timeliness, and adaptability in all project phases","Automating workflows and ensuring code quality","kah6FarLEWIb1aJERf-A2v09d44jRxlAI-CWvfBY268",{"id":89,"title":90,"abstract":91,"author":92,"authorUrl":93,"body":94,"date":4920,"dateUpdated":4920,"description":4921,"excerpt":4922,"extension":4923,"featured":341,"headline":90,"image":4922,"meta":4924,"navigation":341,"ogImage":4922,"path":4926,"seo":4927,"series":4922,"seriesDescription":4922,"seriesOrder":4922,"socialImage":4928,"stem":4935,"tags":4922,"__hash__":4936},"blog\u002Fblog\u002F43-dokploy-deploy-laravel-nuxt.md","Deploying Laravel + Nuxt with Dokploy: Production Setup Guide","Comprehensive guide to deploying Laravel backend and Nuxt frontend using Dokploy with Docker Compose. Covers domain configuration, environment variables, DNS setup, HTTPS with Let's Encrypt, and Traefik routing best practices.","mubaidr","https:\u002F\u002Fmubaidr.js.org",{"type":95,"value":96,"toc":4863},"minimark",[97,101,105,108,112,120,125,128,181,185,188,286,293,297,300,431,438,442,445,718,722,728,1091,1097,1101,1104,1198,1205,1306,1310,1315,3338,3342,3346,3356,3519,3523,3526,3541,3550,3554,3571,3575,3578,3582,3621,3625,3628,3690,3700,3704,3707,3711,3754,3758,3761,3775,3779,3782,3786,3789,3803,3807,3810,3814,3817,3834,3838,3842,3845,3889,3893,3896,3975,3979,3982,4074,4078,4081,4153,4157,4161,4168,4172,4175,4273,4277,4280,4391,4395,4401,4407,4411,4414,4501,4508,4512,4516,4598,4602,4605,4609,4612,4626,4629,4633,4642,4645,4671,4675,4679,4685,4690,4710,4714,4719,4729,4733,4745,4753,4769,4773,4778,4782,4808,4812,4817,4821,4846,4850,4853,4856,4859],[98,99,90],"h2",{"id":100},"deploying-laravel-nuxt-with-dokploy-production-setup-guide",[102,103,104],"p",{},"Dokploy combines Docker Compose deployment with Traefik reverse proxy and Let's Encrypt SSL into a single interface. After deploying multiple Laravel + Nuxt stacks through Dokploy, I've settled on a repeatable pattern that handles the full stack: Nginx, PHP-FPM, MySQL, Redis, Reverb, and the Nuxt frontend.",[102,106,107],{},"This guide covers the complete setup from Docker Compose files to DNS configuration and HTTPS enablement.",[98,109,111],{"id":110},"docker-compose-structure","Docker Compose Structure",[102,113,114,115,119],{},"The foundation is a production ",[116,117,118],"code",{},"docker-compose.yml"," that defines services for the Laravel backend, Nuxt frontend, MySQL, Redis, and supporting workers. Each service has resource limits, health checks, and restart policies.",[121,122,124],"h3",{"id":123},"core-services","Core Services",[102,126,127],{},"The stack consists of these services:",[129,130,131,139,145,151,157,163,169,175],"ul",{},[132,133,134,138],"li",{},[135,136,137],"strong",{},"nginx-production",": Nginx reverse proxy serving the Laravel application",[132,140,141,144],{},[135,142,143],{},"backend-production",": PHP-FPM container running Laravel",[132,146,147,150],{},[135,148,149],{},"frontend-production",": Nuxt frontend application",[132,152,153,156],{},[135,154,155],{},"mysql-production",": MySQL 8.0 database",[132,158,159,162],{},[135,160,161],{},"redis-production",": Redis for caching and queues",[132,164,165,168],{},[135,166,167],{},"reverb-production",": Laravel Reverb for WebSocket connections",[132,170,171,174],{},[135,172,173],{},"scheduler-production",": Laravel task scheduler",[132,176,177,180],{},[135,178,179],{},"worker-production",": Laravel queue worker",[121,182,184],{"id":183},"volume-strategy","Volume Strategy",[102,186,187],{},"Shared volumes handle storage and public assets:",[189,190,195],"pre",{"className":191,"code":192,"language":193,"meta":194,"style":194},"language-yaml shiki shiki-themes material-theme-lighter github-light github-dark monokai","volumes:\n  mysql-production-data:\n  backend-production-storage:\n  backend-production-phpunit-cache:\n  backend-production-composer-cache:\n  redis-production-data:\n  backend-production-public:\n  networks:\n    production-network:\n      driver: bridge\n","yaml","",[116,196,197,210,218,225,233,241,249,257,265,273],{"__ignoreMap":194},[198,199,202,206],"span",{"class":200,"line":201},"line",1,[198,203,205],{"class":204},"sHsBP","volumes",[198,207,209],{"class":208},"swvn1",":\n",[198,211,213,216],{"class":200,"line":212},2,[198,214,215],{"class":204},"  mysql-production-data",[198,217,209],{"class":208},[198,219,220,223],{"class":200,"line":14},[198,221,222],{"class":204},"  backend-production-storage",[198,224,209],{"class":208},[198,226,228,231],{"class":200,"line":227},4,[198,229,230],{"class":204},"  backend-production-phpunit-cache",[198,232,209],{"class":208},[198,234,236,239],{"class":200,"line":235},5,[198,237,238],{"class":204},"  backend-production-composer-cache",[198,240,209],{"class":208},[198,242,244,247],{"class":200,"line":243},6,[198,245,246],{"class":204},"  redis-production-data",[198,248,209],{"class":208},[198,250,252,255],{"class":200,"line":251},7,[198,253,254],{"class":204},"  backend-production-public",[198,256,209],{"class":208},[198,258,260,263],{"class":200,"line":259},8,[198,261,262],{"class":204},"  networks",[198,264,209],{"class":208},[198,266,268,271],{"class":200,"line":267},9,[198,269,270],{"class":204},"    production-network",[198,272,209],{"class":208},[198,274,276,279,282],{"class":200,"line":275},10,[198,277,278],{"class":204},"      driver",[198,280,281],{"class":208},":",[198,283,285],{"class":284},"sLACW"," bridge\n",[102,287,288,289,292],{},"The ",[116,290,291],{},"backend-production-public"," volume is critical - it's mounted to both the backend and frontend containers so that Laravel's public assets and Nuxt's built output are accessible through Nginx.",[98,294,296],{"id":295},"nginx-configuration","Nginx Configuration",[102,298,299],{},"Nginx sits in front of PHP-FPM and handles static files, PHP processing, and security headers. The configuration uses the Docker network alias for backend communication:",[189,301,305],{"className":302,"code":303,"language":304,"meta":194,"style":194},"language-nginx shiki shiki-themes material-theme-lighter github-light github-dark monokai","server {\n    listen 80;\n    server_name api.yourdomain.com;\n    root \u002Fvar\u002Fwww\u002Fpublic;\n    index index.php;\n    client_max_body_size 50m;\n\n    location \u002F {\n        try_files $uri $uri\u002F \u002Findex.php?$query_string;\n    }\n\n    location ~ \\.php$ {\n        fastcgi_pass backend:9000;\n        fastcgi_index index.php;\n        include fastcgi_params;\n        fastcgi_param SCRIPT_FILENAME \u002Fvar\u002Fwww\u002Fpublic$fastcgi_script_name;\n        fastcgi_read_timeout 90;\n    }\n\n    location ~ \u002F\\.(?!well-known).* {\n        deny all;\n    }\n}\n","nginx",[116,306,307,312,317,322,327,332,337,343,348,353,358,363,369,374,380,386,392,398,403,408,414,420,425],{"__ignoreMap":194},[198,308,309],{"class":200,"line":201},[198,310,311],{},"server {\n",[198,313,314],{"class":200,"line":212},[198,315,316],{},"    listen 80;\n",[198,318,319],{"class":200,"line":14},[198,320,321],{},"    server_name api.yourdomain.com;\n",[198,323,324],{"class":200,"line":227},[198,325,326],{},"    root \u002Fvar\u002Fwww\u002Fpublic;\n",[198,328,329],{"class":200,"line":235},[198,330,331],{},"    index index.php;\n",[198,333,334],{"class":200,"line":243},[198,335,336],{},"    client_max_body_size 50m;\n",[198,338,339],{"class":200,"line":251},[198,340,342],{"emptyLinePlaceholder":341},true,"\n",[198,344,345],{"class":200,"line":259},[198,346,347],{},"    location \u002F {\n",[198,349,350],{"class":200,"line":267},[198,351,352],{},"        try_files $uri $uri\u002F \u002Findex.php?$query_string;\n",[198,354,355],{"class":200,"line":275},[198,356,357],{},"    }\n",[198,359,361],{"class":200,"line":360},11,[198,362,342],{"emptyLinePlaceholder":341},[198,364,366],{"class":200,"line":365},12,[198,367,368],{},"    location ~ \\.php$ {\n",[198,370,371],{"class":200,"line":27},[198,372,373],{},"        fastcgi_pass backend:9000;\n",[198,375,377],{"class":200,"line":376},14,[198,378,379],{},"        fastcgi_index index.php;\n",[198,381,383],{"class":200,"line":382},15,[198,384,385],{},"        include fastcgi_params;\n",[198,387,389],{"class":200,"line":388},16,[198,390,391],{},"        fastcgi_param SCRIPT_FILENAME \u002Fvar\u002Fwww\u002Fpublic$fastcgi_script_name;\n",[198,393,395],{"class":200,"line":394},17,[198,396,397],{},"        fastcgi_read_timeout 90;\n",[198,399,401],{"class":200,"line":400},18,[198,402,357],{},[198,404,406],{"class":200,"line":405},19,[198,407,342],{"emptyLinePlaceholder":341},[198,409,411],{"class":200,"line":410},20,[198,412,413],{},"    location ~ \u002F\\.(?!well-known).* {\n",[198,415,417],{"class":200,"line":416},21,[198,418,419],{},"        deny all;\n",[198,421,423],{"class":200,"line":422},22,[198,424,357],{},[198,426,428],{"class":200,"line":427},23,[198,429,430],{},"}\n",[102,432,433,434,437],{},"Save this as ",[116,435,436],{},"backend\u002Fdocker\u002Fnginx-production.conf"," and mount it into the Nginx container.",[98,439,441],{"id":440},"backend-dockerfile","Backend Dockerfile",[102,443,444],{},"The Laravel Dockerfile uses a multi-stage build to keep the production image small while having all build dependencies available for Composer and PHP extensions:",[189,446,450],{"className":447,"code":448,"language":449,"meta":194,"style":194},"language-dockerfile shiki shiki-themes material-theme-lighter github-light github-dark monokai","# Stage 1: Build environment and Composer dependencies\nFROM php:8.4-fpm AS builder\n\nRUN apt-get update && apt-get install -y --no-install-recommends \\\n    curl unzip libonig-dev libssl-dev libxml2-dev libcurl4-openssl-dev \\\n    libicu-dev libzip-dev libpng-dev libjpeg62-turbo-dev libwebp-dev libfreetype6-dev \\\n    && pecl install redis-6.3.0 \\\n    && docker-php-ext-enable redis \\\n    && docker-php-ext-configure gd --with-jpeg --with-freetype --with-webp \\\n    && docker-php-ext-install -j$(nproc) intl zip gd bcmath opcache pdo_mysql soap pcntl \\\n    && apt-get autoremove -y && apt-get clean && rm -rf \u002Fvar\u002Flib\u002Fapt\u002Flists\u002F* \u002Ftmp\u002F* \u002Fvar\u002Ftmp\u002F*\n\nWORKDIR \u002Fvar\u002Fwww\nCOPY . \u002Fvar\u002Fwww\n\nRUN curl -sS https:\u002F\u002Fgetcomposer.org\u002Finstaller | php -- --install-dir=\u002Fusr\u002Flocal\u002Fbin --filename=composer \\\n    && composer install --no-dev --optimize-autoloader --no-interaction --no-progress --prefer-dist --no-scripts \\\n    && composer run-script post-autoload-dump --no-interaction\n\n# Stage 2: Production environment\nFROM php:8.4-fpm\n\nRUN apt-get update && apt-get install -y --no-install-recommends \\\n    libicu-dev libzip-dev libpng-dev libjpeg62-turbo-dev libwebp-dev libxml2 \\\n    libssl3 libcurl4 libfreetype6 rsync gosu \\\n    && apt-get autoremove -y && apt-get clean && rm -rf \u002Fvar\u002Flib\u002Fapt\u002Flists\u002F* \u002Ftmp\u002F* \u002Fvar\u002Ftmp\u002F*\n\nCOPY --from=builder \u002Fusr\u002Flocal\u002Flib\u002Fphp\u002Fextensions\u002F \u002Fusr\u002Flocal\u002Flib\u002Fphp\u002Fextensions\u002F\nCOPY --from=builder \u002Fusr\u002Flocal\u002Fetc\u002Fphp\u002Fconf.d\u002F \u002Fusr\u002Flocal\u002Fetc\u002Fphp\u002Fconf.d\u002F\n\nRUN mv \"$PHP_INI_DIR\u002Fphp.ini-production\" \"$PHP_INI_DIR\u002Fphp.ini\"\n\nCOPY --from=builder \u002Fvar\u002Fwww \u002Fvar\u002Fwww\nRUN cp -a \u002Fvar\u002Fwww\u002Fpublic \u002Fvar\u002Fwww\u002Fpublic-src\n\nWORKDIR \u002Fvar\u002Fwww\n\nRUN sed -i \\\n    -e 's|^error_log = .*|error_log = \u002Fvar\u002Fwww\u002Fstorage\u002Flogs\u002Fphp-fpm.log|' \\\n    -e 's|^access.log = .*|access.log = \u002Fvar\u002Fwww\u002Fstorage\u002Flogs\u002Fphp-fpm-access.log|' \\\n    \u002Fusr\u002Flocal\u002Fetc\u002Fphp-fpm.d\u002Fdocker.conf\n\nCOPY docker\u002Fdocker-entrypoint.sh \u002Fusr\u002Flocal\u002Fbin\u002Fdocker-entrypoint.sh\nRUN chmod +x \u002Fusr\u002Flocal\u002Fbin\u002Fdocker-entrypoint.sh\n\nRUN chown -R www-data:www-data \u002Fvar\u002Fwww\n\nEXPOSE 9000\n\nENTRYPOINT [\"docker-entrypoint.sh\"]\nCMD [\"php-fpm\"]\n","dockerfile",[116,451,452,457,462,466,471,476,481,486,491,496,501,506,510,515,520,524,529,534,539,543,548,553,557,561,567,573,578,583,589,595,600,606,611,617,623,628,633,638,644,650,656,662,667,673,679,684,690,695,701,706,712],{"__ignoreMap":194},[198,453,454],{"class":200,"line":201},[198,455,456],{},"# Stage 1: Build environment and Composer dependencies\n",[198,458,459],{"class":200,"line":212},[198,460,461],{},"FROM php:8.4-fpm AS builder\n",[198,463,464],{"class":200,"line":14},[198,465,342],{"emptyLinePlaceholder":341},[198,467,468],{"class":200,"line":227},[198,469,470],{},"RUN apt-get update && apt-get install -y --no-install-recommends \\\n",[198,472,473],{"class":200,"line":235},[198,474,475],{},"    curl unzip libonig-dev libssl-dev libxml2-dev libcurl4-openssl-dev \\\n",[198,477,478],{"class":200,"line":243},[198,479,480],{},"    libicu-dev libzip-dev libpng-dev libjpeg62-turbo-dev libwebp-dev libfreetype6-dev \\\n",[198,482,483],{"class":200,"line":251},[198,484,485],{},"    && pecl install redis-6.3.0 \\\n",[198,487,488],{"class":200,"line":259},[198,489,490],{},"    && docker-php-ext-enable redis \\\n",[198,492,493],{"class":200,"line":267},[198,494,495],{},"    && docker-php-ext-configure gd --with-jpeg --with-freetype --with-webp \\\n",[198,497,498],{"class":200,"line":275},[198,499,500],{},"    && docker-php-ext-install -j$(nproc) intl zip gd bcmath opcache pdo_mysql soap pcntl \\\n",[198,502,503],{"class":200,"line":360},[198,504,505],{},"    && apt-get autoremove -y && apt-get clean && rm -rf \u002Fvar\u002Flib\u002Fapt\u002Flists\u002F* \u002Ftmp\u002F* \u002Fvar\u002Ftmp\u002F*\n",[198,507,508],{"class":200,"line":365},[198,509,342],{"emptyLinePlaceholder":341},[198,511,512],{"class":200,"line":27},[198,513,514],{},"WORKDIR \u002Fvar\u002Fwww\n",[198,516,517],{"class":200,"line":376},[198,518,519],{},"COPY . \u002Fvar\u002Fwww\n",[198,521,522],{"class":200,"line":382},[198,523,342],{"emptyLinePlaceholder":341},[198,525,526],{"class":200,"line":388},[198,527,528],{},"RUN curl -sS https:\u002F\u002Fgetcomposer.org\u002Finstaller | php -- --install-dir=\u002Fusr\u002Flocal\u002Fbin --filename=composer \\\n",[198,530,531],{"class":200,"line":394},[198,532,533],{},"    && composer install --no-dev --optimize-autoloader --no-interaction --no-progress --prefer-dist --no-scripts \\\n",[198,535,536],{"class":200,"line":400},[198,537,538],{},"    && composer run-script post-autoload-dump --no-interaction\n",[198,540,541],{"class":200,"line":405},[198,542,342],{"emptyLinePlaceholder":341},[198,544,545],{"class":200,"line":410},[198,546,547],{},"# Stage 2: Production environment\n",[198,549,550],{"class":200,"line":416},[198,551,552],{},"FROM php:8.4-fpm\n",[198,554,555],{"class":200,"line":422},[198,556,342],{"emptyLinePlaceholder":341},[198,558,559],{"class":200,"line":427},[198,560,470],{},[198,562,564],{"class":200,"line":563},24,[198,565,566],{},"    libicu-dev libzip-dev libpng-dev libjpeg62-turbo-dev libwebp-dev libxml2 \\\n",[198,568,570],{"class":200,"line":569},25,[198,571,572],{},"    libssl3 libcurl4 libfreetype6 rsync gosu \\\n",[198,574,576],{"class":200,"line":575},26,[198,577,505],{},[198,579,581],{"class":200,"line":580},27,[198,582,342],{"emptyLinePlaceholder":341},[198,584,586],{"class":200,"line":585},28,[198,587,588],{},"COPY --from=builder \u002Fusr\u002Flocal\u002Flib\u002Fphp\u002Fextensions\u002F \u002Fusr\u002Flocal\u002Flib\u002Fphp\u002Fextensions\u002F\n",[198,590,592],{"class":200,"line":591},29,[198,593,594],{},"COPY --from=builder \u002Fusr\u002Flocal\u002Fetc\u002Fphp\u002Fconf.d\u002F \u002Fusr\u002Flocal\u002Fetc\u002Fphp\u002Fconf.d\u002F\n",[198,596,598],{"class":200,"line":597},30,[198,599,342],{"emptyLinePlaceholder":341},[198,601,603],{"class":200,"line":602},31,[198,604,605],{},"RUN mv \"$PHP_INI_DIR\u002Fphp.ini-production\" \"$PHP_INI_DIR\u002Fphp.ini\"\n",[198,607,609],{"class":200,"line":608},32,[198,610,342],{"emptyLinePlaceholder":341},[198,612,614],{"class":200,"line":613},33,[198,615,616],{},"COPY --from=builder \u002Fvar\u002Fwww \u002Fvar\u002Fwww\n",[198,618,620],{"class":200,"line":619},34,[198,621,622],{},"RUN cp -a \u002Fvar\u002Fwww\u002Fpublic \u002Fvar\u002Fwww\u002Fpublic-src\n",[198,624,626],{"class":200,"line":625},35,[198,627,342],{"emptyLinePlaceholder":341},[198,629,631],{"class":200,"line":630},36,[198,632,514],{},[198,634,636],{"class":200,"line":635},37,[198,637,342],{"emptyLinePlaceholder":341},[198,639,641],{"class":200,"line":640},38,[198,642,643],{},"RUN sed -i \\\n",[198,645,647],{"class":200,"line":646},39,[198,648,649],{},"    -e 's|^error_log = .*|error_log = \u002Fvar\u002Fwww\u002Fstorage\u002Flogs\u002Fphp-fpm.log|' \\\n",[198,651,653],{"class":200,"line":652},40,[198,654,655],{},"    -e 's|^access.log = .*|access.log = \u002Fvar\u002Fwww\u002Fstorage\u002Flogs\u002Fphp-fpm-access.log|' \\\n",[198,657,659],{"class":200,"line":658},41,[198,660,661],{},"    \u002Fusr\u002Flocal\u002Fetc\u002Fphp-fpm.d\u002Fdocker.conf\n",[198,663,665],{"class":200,"line":664},42,[198,666,342],{"emptyLinePlaceholder":341},[198,668,670],{"class":200,"line":669},43,[198,671,672],{},"COPY docker\u002Fdocker-entrypoint.sh \u002Fusr\u002Flocal\u002Fbin\u002Fdocker-entrypoint.sh\n",[198,674,676],{"class":200,"line":675},44,[198,677,678],{},"RUN chmod +x \u002Fusr\u002Flocal\u002Fbin\u002Fdocker-entrypoint.sh\n",[198,680,682],{"class":200,"line":681},45,[198,683,342],{"emptyLinePlaceholder":341},[198,685,687],{"class":200,"line":686},46,[198,688,689],{},"RUN chown -R www-data:www-data \u002Fvar\u002Fwww\n",[198,691,693],{"class":200,"line":692},47,[198,694,342],{"emptyLinePlaceholder":341},[198,696,698],{"class":200,"line":697},48,[198,699,700],{},"EXPOSE 9000\n",[198,702,704],{"class":200,"line":703},49,[198,705,342],{"emptyLinePlaceholder":341},[198,707,709],{"class":200,"line":708},50,[198,710,711],{},"ENTRYPOINT [\"docker-entrypoint.sh\"]\n",[198,713,715],{"class":200,"line":714},51,[198,716,717],{},"CMD [\"php-fpm\"]\n",[98,719,721],{"id":720},"docker-entrypoint-script","Docker Entrypoint Script",[102,723,724,725,281],{},"The entrypoint script handles permissions, public asset synchronization, and optional migrations. This runs as root first to fix volume ownership, then drops to ",[116,726,727],{},"www-data",[189,729,733],{"className":730,"code":731,"language":732,"meta":194,"style":194},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark monokai","#!\u002Fbin\u002Fsh\nset -e\n\n# 1. Fix volume ownership - must run as root\nmkdir -p \u002Fvar\u002Fwww\u002Fstorage\u002Flogs \\\n    \u002Fvar\u002Fwww\u002Fstorage\u002Fframework\u002Fcache \\\n    \u002Fvar\u002Fwww\u002Fstorage\u002Fframework\u002Fsessions \\\n    \u002Fvar\u002Fwww\u002Fstorage\u002Fframework\u002Fviews \\\n    \u002Fvar\u002Fwww\u002Fbootstrap\u002Fcache\nchown -R www-data:www-data \u002Fvar\u002Fwww\u002Fstorage \u002Fvar\u002Fwww\u002Fbootstrap\u002Fcache\n\n# 2. Sync public\u002F into the shared volume (if mounted)\nif mountpoint -q \u002Fvar\u002Fwww\u002Fpublic; then\n    echo \"Syncing public\u002F into shared volume...\"\n    rsync -a --delete \u002Fvar\u002Fwww\u002Fpublic-src\u002F \u002Fvar\u002Fwww\u002Fpublic\u002F\n    chown -R www-data:www-data \u002Fvar\u002Fwww\u002Fpublic\nfi\n\n# 3. Release tasks - only the designated service runs these\nif [ \"$RUN_MIGRATIONS\" = \"true\" ]; then\n    gosu www-data php artisan storage:link --force --no-interaction 2>\u002Fdev\u002Fnull || true\n    gosu www-data php artisan migrate --force --no-interaction\n    gosu www-data php artisan config:cache --no-interaction\n    gosu www-data php artisan route:cache --no-interaction\n    gosu www-data php artisan view:cache --no-interaction\n    gosu www-data php artisan queue:restart --no-interaction 2>\u002Fdev\u002Fnull || true\nfi\n\n# 4. Execute the main container command as www-data\nexec gosu www-data \"$@\"\n","bash",[116,734,735,741,751,755,760,776,783,790,797,802,819,823,828,849,864,881,893,898,902,907,939,974,992,1007,1022,1037,1060,1064,1068,1073],{"__ignoreMap":194},[198,736,737],{"class":200,"line":201},[198,738,740],{"class":739},"ss7Ak","#!\u002Fbin\u002Fsh\n",[198,742,743,747],{"class":200,"line":212},[198,744,746],{"class":745},"sMLJd","set",[198,748,750],{"class":749},"sFhLe"," -e\n",[198,752,753],{"class":200,"line":14},[198,754,342],{"emptyLinePlaceholder":341},[198,756,757],{"class":200,"line":227},[198,758,759],{"class":739},"# 1. Fix volume ownership - must run as root\n",[198,761,762,766,769,772],{"class":200,"line":235},[198,763,765],{"class":764},"sR7ES","mkdir",[198,767,768],{"class":749}," -p",[198,770,771],{"class":284}," \u002Fvar\u002Fwww\u002Fstorage\u002Flogs",[198,773,775],{"class":774},"sQeA1"," \\\n",[198,777,778,781],{"class":200,"line":243},[198,779,780],{"class":284},"    \u002Fvar\u002Fwww\u002Fstorage\u002Fframework\u002Fcache",[198,782,775],{"class":774},[198,784,785,788],{"class":200,"line":251},[198,786,787],{"class":284},"    \u002Fvar\u002Fwww\u002Fstorage\u002Fframework\u002Fsessions",[198,789,775],{"class":774},[198,791,792,795],{"class":200,"line":259},[198,793,794],{"class":284},"    \u002Fvar\u002Fwww\u002Fstorage\u002Fframework\u002Fviews",[198,796,775],{"class":774},[198,798,799],{"class":200,"line":267},[198,800,801],{"class":284},"    \u002Fvar\u002Fwww\u002Fbootstrap\u002Fcache\n",[198,803,804,807,810,813,816],{"class":200,"line":275},[198,805,806],{"class":764},"chown",[198,808,809],{"class":749}," -R",[198,811,812],{"class":284}," www-data:www-data",[198,814,815],{"class":284}," \u002Fvar\u002Fwww\u002Fstorage",[198,817,818],{"class":284}," \u002Fvar\u002Fwww\u002Fbootstrap\u002Fcache\n",[198,820,821],{"class":200,"line":360},[198,822,342],{"emptyLinePlaceholder":341},[198,824,825],{"class":200,"line":365},[198,826,827],{"class":739},"# 2. Sync public\u002F into the shared volume (if mounted)\n",[198,829,830,834,837,840,843,846],{"class":200,"line":27},[198,831,833],{"class":832},"sRxSC","if",[198,835,836],{"class":764}," mountpoint",[198,838,839],{"class":749}," -q",[198,841,842],{"class":284}," \u002Fvar\u002Fwww\u002Fpublic",[198,844,845],{"class":208},";",[198,847,848],{"class":832}," then\n",[198,850,851,854,858,861],{"class":200,"line":376},[198,852,853],{"class":745},"    echo",[198,855,857],{"class":856},"siCPE"," \"",[198,859,860],{"class":284},"Syncing public\u002F into shared volume...",[198,862,863],{"class":856},"\"\n",[198,865,866,869,872,875,878],{"class":200,"line":382},[198,867,868],{"class":764},"    rsync",[198,870,871],{"class":749}," -a",[198,873,874],{"class":749}," --delete",[198,876,877],{"class":284}," \u002Fvar\u002Fwww\u002Fpublic-src\u002F",[198,879,880],{"class":284}," \u002Fvar\u002Fwww\u002Fpublic\u002F\n",[198,882,883,886,888,890],{"class":200,"line":388},[198,884,885],{"class":764},"    chown",[198,887,809],{"class":749},[198,889,812],{"class":284},[198,891,892],{"class":284}," \u002Fvar\u002Fwww\u002Fpublic\n",[198,894,895],{"class":200,"line":394},[198,896,897],{"class":832},"fi\n",[198,899,900],{"class":200,"line":400},[198,901,342],{"emptyLinePlaceholder":341},[198,903,904],{"class":200,"line":405},[198,905,906],{"class":739},"# 3. Release tasks - only the designated service runs these\n",[198,908,909,911,914,916,920,923,927,929,932,934,937],{"class":200,"line":410},[198,910,833],{"class":832},[198,912,913],{"class":208}," [",[198,915,857],{"class":856},[198,917,919],{"class":918},"ss--_","$RUN_MIGRATIONS",[198,921,922],{"class":856},"\"",[198,924,926],{"class":925},"sGXK2"," =",[198,928,857],{"class":856},[198,930,931],{"class":284},"true",[198,933,922],{"class":856},[198,935,936],{"class":208}," ];",[198,938,848],{"class":832},[198,940,941,944,947,950,953,956,959,962,965,968,971],{"class":200,"line":416},[198,942,943],{"class":764},"    gosu",[198,945,946],{"class":284}," www-data",[198,948,949],{"class":284}," php",[198,951,952],{"class":284}," artisan",[198,954,955],{"class":284}," storage:link",[198,957,958],{"class":749}," --force",[198,960,961],{"class":749}," --no-interaction",[198,963,964],{"class":925}," 2>",[198,966,967],{"class":284},"\u002Fdev\u002Fnull",[198,969,970],{"class":925}," ||",[198,972,973],{"class":745}," true\n",[198,975,976,978,980,982,984,987,989],{"class":200,"line":422},[198,977,943],{"class":764},[198,979,946],{"class":284},[198,981,949],{"class":284},[198,983,952],{"class":284},[198,985,986],{"class":284}," migrate",[198,988,958],{"class":749},[198,990,991],{"class":749}," --no-interaction\n",[198,993,994,996,998,1000,1002,1005],{"class":200,"line":427},[198,995,943],{"class":764},[198,997,946],{"class":284},[198,999,949],{"class":284},[198,1001,952],{"class":284},[198,1003,1004],{"class":284}," config:cache",[198,1006,991],{"class":749},[198,1008,1009,1011,1013,1015,1017,1020],{"class":200,"line":563},[198,1010,943],{"class":764},[198,1012,946],{"class":284},[198,1014,949],{"class":284},[198,1016,952],{"class":284},[198,1018,1019],{"class":284}," route:cache",[198,1021,991],{"class":749},[198,1023,1024,1026,1028,1030,1032,1035],{"class":200,"line":569},[198,1025,943],{"class":764},[198,1027,946],{"class":284},[198,1029,949],{"class":284},[198,1031,952],{"class":284},[198,1033,1034],{"class":284}," view:cache",[198,1036,991],{"class":749},[198,1038,1039,1041,1043,1045,1047,1050,1052,1054,1056,1058],{"class":200,"line":575},[198,1040,943],{"class":764},[198,1042,946],{"class":284},[198,1044,949],{"class":284},[198,1046,952],{"class":284},[198,1048,1049],{"class":284}," queue:restart",[198,1051,961],{"class":749},[198,1053,964],{"class":925},[198,1055,967],{"class":284},[198,1057,970],{"class":925},[198,1059,973],{"class":745},[198,1061,1062],{"class":200,"line":580},[198,1063,897],{"class":832},[198,1065,1066],{"class":200,"line":585},[198,1067,342],{"emptyLinePlaceholder":341},[198,1069,1070],{"class":200,"line":591},[198,1071,1072],{"class":739},"# 4. Execute the main container command as www-data\n",[198,1074,1075,1078,1081,1083,1085,1089],{"class":200,"line":597},[198,1076,1077],{"class":745},"exec",[198,1079,1080],{"class":284}," gosu",[198,1082,946],{"class":284},[198,1084,857],{"class":856},[198,1086,1088],{"class":1087},"sVMSR","$@",[198,1090,863],{"class":856},[102,1092,433,1093,1096],{},[116,1094,1095],{},"backend\u002Fdocker\u002Fdocker-entrypoint.sh"," and make it executable.",[98,1098,1100],{"id":1099},"frontend-dockerfile","Frontend Dockerfile",[102,1102,1103],{},"The Nuxt frontend needs a Dockerfile that builds the static assets and serves them via Nginx or the built-in Nitro server:",[189,1105,1107],{"className":447,"code":1106,"language":449,"meta":194,"style":194},"# Stage 1: Build Nuxt application\nFROM node:20-alpine AS builder\n\nWORKDIR \u002Fapp\n\nCOPY package*.json .\u002F\nRUN npm ci --silent\n\nCOPY . .\nRUN npm run generate\n\n# Stage 2: Production\nFROM nginx:1.31-alpine\n\nCOPY --from=builder \u002Fapp\u002F.output\u002Fpublic \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\nCOPY nginx.conf \u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf\n\nEXPOSE 80\nCMD [\"nginx\", \"-g\", \"daemon off;\"]\n",[116,1108,1109,1114,1119,1123,1128,1132,1137,1142,1146,1151,1156,1160,1165,1170,1174,1179,1184,1188,1193],{"__ignoreMap":194},[198,1110,1111],{"class":200,"line":201},[198,1112,1113],{},"# Stage 1: Build Nuxt application\n",[198,1115,1116],{"class":200,"line":212},[198,1117,1118],{},"FROM node:20-alpine AS builder\n",[198,1120,1121],{"class":200,"line":14},[198,1122,342],{"emptyLinePlaceholder":341},[198,1124,1125],{"class":200,"line":227},[198,1126,1127],{},"WORKDIR \u002Fapp\n",[198,1129,1130],{"class":200,"line":235},[198,1131,342],{"emptyLinePlaceholder":341},[198,1133,1134],{"class":200,"line":243},[198,1135,1136],{},"COPY package*.json .\u002F\n",[198,1138,1139],{"class":200,"line":251},[198,1140,1141],{},"RUN npm ci --silent\n",[198,1143,1144],{"class":200,"line":259},[198,1145,342],{"emptyLinePlaceholder":341},[198,1147,1148],{"class":200,"line":267},[198,1149,1150],{},"COPY . .\n",[198,1152,1153],{"class":200,"line":275},[198,1154,1155],{},"RUN npm run generate\n",[198,1157,1158],{"class":200,"line":360},[198,1159,342],{"emptyLinePlaceholder":341},[198,1161,1162],{"class":200,"line":365},[198,1163,1164],{},"# Stage 2: Production\n",[198,1166,1167],{"class":200,"line":27},[198,1168,1169],{},"FROM nginx:1.31-alpine\n",[198,1171,1172],{"class":200,"line":376},[198,1173,342],{"emptyLinePlaceholder":341},[198,1175,1176],{"class":200,"line":382},[198,1177,1178],{},"COPY --from=builder \u002Fapp\u002F.output\u002Fpublic \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\n",[198,1180,1181],{"class":200,"line":388},[198,1182,1183],{},"COPY nginx.conf \u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf\n",[198,1185,1186],{"class":200,"line":394},[198,1187,342],{"emptyLinePlaceholder":341},[198,1189,1190],{"class":200,"line":400},[198,1191,1192],{},"EXPOSE 80\n",[198,1194,1195],{"class":200,"line":405},[198,1196,1197],{},"CMD [\"nginx\", \"-g\", \"daemon off;\"]\n",[102,1199,1200,1201,1204],{},"The frontend ",[116,1202,1203],{},"nginx.conf"," for serving the static Nuxt output:",[189,1206,1208],{"className":302,"code":1207,"language":304,"meta":194,"style":194},"server {\n    listen 80;\n    server_name yourdomain.com;\n    root \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml;\n    index index.html;\n\n    location \u002F {\n        try_files $uri $uri\u002F \u002Findex.html;\n    }\n\n    # Cache static assets\n    location ~* \\.(js|css|png|jpg|svg|ico|woff|woff2)$ {\n        expires 1y;\n        add_header Cache-Control \"public, immutable\";\n    }\n\n    # Security headers\n    add_header X-Frame-Options \"SAMEORIGIN\";\n    add_header X-Content-Type-Options \"nosniff\";\n    add_header X-XSS-Protection \"1; mode=block\";\n}\n",[116,1209,1210,1214,1218,1223,1228,1233,1237,1241,1246,1250,1254,1259,1264,1269,1274,1278,1282,1287,1292,1297,1302],{"__ignoreMap":194},[198,1211,1212],{"class":200,"line":201},[198,1213,311],{},[198,1215,1216],{"class":200,"line":212},[198,1217,316],{},[198,1219,1220],{"class":200,"line":14},[198,1221,1222],{},"    server_name yourdomain.com;\n",[198,1224,1225],{"class":200,"line":227},[198,1226,1227],{},"    root \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml;\n",[198,1229,1230],{"class":200,"line":235},[198,1231,1232],{},"    index index.html;\n",[198,1234,1235],{"class":200,"line":243},[198,1236,342],{"emptyLinePlaceholder":341},[198,1238,1239],{"class":200,"line":251},[198,1240,347],{},[198,1242,1243],{"class":200,"line":259},[198,1244,1245],{},"        try_files $uri $uri\u002F \u002Findex.html;\n",[198,1247,1248],{"class":200,"line":267},[198,1249,357],{},[198,1251,1252],{"class":200,"line":275},[198,1253,342],{"emptyLinePlaceholder":341},[198,1255,1256],{"class":200,"line":360},[198,1257,1258],{},"    # Cache static assets\n",[198,1260,1261],{"class":200,"line":365},[198,1262,1263],{},"    location ~* \\.(js|css|png|jpg|svg|ico|woff|woff2)$ {\n",[198,1265,1266],{"class":200,"line":27},[198,1267,1268],{},"        expires 1y;\n",[198,1270,1271],{"class":200,"line":376},[198,1272,1273],{},"        add_header Cache-Control \"public, immutable\";\n",[198,1275,1276],{"class":200,"line":382},[198,1277,357],{},[198,1279,1280],{"class":200,"line":388},[198,1281,342],{"emptyLinePlaceholder":341},[198,1283,1284],{"class":200,"line":394},[198,1285,1286],{},"    # Security headers\n",[198,1288,1289],{"class":200,"line":400},[198,1290,1291],{},"    add_header X-Frame-Options \"SAMEORIGIN\";\n",[198,1293,1294],{"class":200,"line":405},[198,1295,1296],{},"    add_header X-Content-Type-Options \"nosniff\";\n",[198,1298,1299],{"class":200,"line":410},[198,1300,1301],{},"    add_header X-XSS-Protection \"1; mode=block\";\n",[198,1303,1304],{"class":200,"line":416},[198,1305,430],{},[98,1307,1309],{"id":1308},"complete-docker-compose","Complete Docker Compose",[102,1311,1312,1313,281],{},"Here's the full production ",[116,1314,118],{},[189,1316,1318],{"className":191,"code":1317,"language":193,"meta":194,"style":194},"name: paragonrentals_production\n\nservices:\n  nginx-production:\n    image: nginx:1.31-alpine\n    volumes:\n      - .\u002Fbackend\u002Fdocker\u002Fnginx-production.conf:\u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf:ro\n      - backend-production-storage:\u002Fvar\u002Fwww\u002Fstorage:ro\n      - backend-production-public:\u002Fvar\u002Fwww\u002Fpublic:ro\n    depends_on:\n      backend-production:\n        condition: service_healthy\n    networks:\n      - production-network\n    restart: unless-stopped\n    cpus: 0.15\n    mem_limit: 128m\n    mem_reservation: 64m\n\n  backend-production:\n    build:\n      context: .\u002Fbackend\n      dockerfile: Dockerfile.production\n    env_file:\n      - .env\n    environment:\n      RUN_MIGRATIONS: \"true\"\n    depends_on:\n      mysql-production:\n        condition: service_healthy\n      redis-production:\n        condition: service_healthy\n    volumes:\n      - backend-production-storage:\u002Fvar\u002Fwww\u002Fstorage\n      - backend-production-public:\u002Fvar\u002Fwww\u002Fpublic\n    networks:\n      production-network:\n        aliases:\n          - backend\n    restart: unless-stopped\n    cpus: 0.75\n    mem_limit: 896m\n    mem_reservation: 512m\n    healthcheck:\n      test:\n        [\"CMD-SHELL\", 'php -r ''exit(@fsockopen(\"127.0.0.1\", 9000) ? 0 : 1);''']\n      interval: 60s\n      timeout: 5s\n      retries: 3\n      start_period: 30s\n\n  frontend-production:\n    build:\n      context: .\u002Ffrontend\n      dockerfile: Dockerfile.production\n    env_file:\n      - .env\n    environment:\n      NUXT_LARAVEL_API_URL: ${NUXT_LARAVEL_API_URL}\n      NUXT_LARAVEL_BASE_URL: ${NUXT_LARAVEL_BASE_URL}\n      NUXT_PUBLIC_LARAVEL_BASE_URL: ${NUXT_PUBLIC_LARAVEL_BASE_URL}\n      NUXT_PUBLIC_LARAVEL_API_URL: ${NUXT_PUBLIC_LARAVEL_API_URL}\n      NUXT_PUBLIC_APP_URL: ${NUXT_PUBLIC_APP_URL}\n      NUXT_PUBLIC_REVERB_APP_KEY: ${NUXT_PUBLIC_REVERB_APP_KEY}\n      NUXT_PUBLIC_REVERB_HOST: ${NUXT_PUBLIC_REVERB_HOST}\n      NUXT_PUBLIC_REVERB_PORT: ${NUXT_PUBLIC_REVERB_PORT}\n      NUXT_PUBLIC_REVERB_SCHEME: ${NUXT_PUBLIC_REVERB_SCHEME}\n    depends_on:\n      backend-production:\n        condition: service_healthy\n    networks:\n      - production-network\n    restart: unless-stopped\n    cpus: 0.50\n    mem_limit: 768m\n    mem_reservation: 256m\n\n  mysql-production:\n    image: mysql:8.0\n    environment:\n      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}\n      MYSQL_DATABASE: ${DB_DATABASE}\n      MYSQL_USER: ${DB_USERNAME}\n      MYSQL_PASSWORD: ${DB_PASSWORD}\n    command: >\n      --innodb-buffer-pool-size=256M\n      --max-connections=50\n    volumes:\n      - mysql-production-data:\u002Fvar\u002Flib\u002Fmysql\n    networks:\n      - production-network\n    restart: unless-stopped\n    cpus: 0.75\n    mem_limit: 768m\n    mem_reservation: 384m\n    healthcheck:\n      test:\n        [\n          \"CMD\",\n          \"mysqladmin\",\n          \"ping\",\n          \"-h\",\n          \"localhost\",\n          \"-u\",\n          \"root\",\n          \"-p${DB_ROOT_PASSWORD}\",\n        ]\n      interval: 60s\n      timeout: 10s\n      retries: 5\n      start_period: 60s\n\n  redis-production:\n    image: redis:8-alpine\n    environment:\n      REDIS_PASSWORD: ${REDIS_PASSWORD}\n    command: >\n      redis-server\n      --requirepass ${REDIS_PASSWORD}\n      --appendonly yes\n      --maxmemory 96mb\n      --maxmemory-policy allkeys-lru\n    volumes:\n      - redis-production-data:\u002Fdata\n    networks:\n      - production-network\n    restart: unless-stopped\n    cpus: 0.20\n    mem_limit: 128m\n    mem_reservation: 64m\n    healthcheck:\n      test: [\"CMD\", \"redis-cli\", \"-a\", \"${REDIS_PASSWORD}\", \"ping\"]\n      interval: 60s\n      timeout: 5s\n      retries: 5\n      start_period: 10s\n\n  reverb-production:\n    build:\n      context: .\u002Fbackend\n      dockerfile: Dockerfile.production\n    command: sh -c 'php artisan reverb:start --host=0.0.0.0 --port=${REVERB_PORT:-6001}'\n    env_file:\n      - .env\n    networks:\n      - production-network\n    depends_on:\n      backend-production:\n        condition: service_healthy\n      redis-production:\n        condition: service_healthy\n    volumes:\n      - backend-production-storage:\u002Fvar\u002Fwww\u002Fstorage\n    restart: unless-stopped\n    cpus: 0.25\n    mem_limit: 384m\n    mem_reservation: 128m\n    healthcheck:\n      test:\n        [\n          \"CMD\",\n          \"php\",\n          \"-r\",\n          \"exit(@fsockopen('127.0.0.1', getenv('REVERB_PORT') ?: 6001) ? 0 : 1);\",\n        ]\n      interval: 60s\n      timeout: 5s\n      retries: 3\n      start_period: 15s\n\n  scheduler-production:\n    build:\n      context: .\u002Fbackend\n      dockerfile: Dockerfile.production\n    command: php artisan schedule:work\n    env_file:\n      - .env\n    depends_on:\n      backend-production:\n        condition: service_healthy\n      redis-production:\n        condition: service_healthy\n    volumes:\n      - backend-production-storage:\u002Fvar\u002Fwww\u002Fstorage\n    networks:\n      - production-network\n    restart: unless-stopped\n    cpus: 0.10\n    mem_limit: 256m\n    mem_reservation: 64m\n\n  worker-production:\n    build:\n      context: .\u002Fbackend\n      dockerfile: Dockerfile.production\n    command: >\n      php artisan queue:work\n      --verbose\n      --tries=3\n      --timeout=90\n      --sleep=3\n      --max-time=3600\n    env_file:\n      - .env\n    depends_on:\n      backend-production:\n        condition: service_healthy\n      redis-production:\n        condition: service_healthy\n    volumes:\n      - backend-production-storage:\u002Fvar\u002Fwww\u002Fstorage\n    restart: unless-stopped\n    networks:\n      - production-network\n    cpus: 0.50\n    mem_limit: 512m\n    mem_reservation: 128m\n    healthcheck:\n      test: [\"CMD-SHELL\", \"grep -q 'queue:work' \u002Fproc\u002F1\u002Fcmdline\"]\n      interval: 60s\n      timeout: 5s\n      retries: 3\n      start_period: 15s\n\nvolumes:\n  mysql-production-data:\n  backend-production-storage:\n  backend-production-phpunit-cache:\n  backend-production-composer-cache:\n  redis-production-data:\n  backend-production-public:\n\nnetworks:\n  production-network:\n    driver: bridge\n",[116,1319,1320,1330,1334,1341,1348,1358,1365,1373,1380,1387,1394,1401,1411,1418,1425,1435,1446,1456,1466,1470,1477,1484,1494,1504,1511,1518,1525,1538,1544,1551,1559,1566,1574,1580,1587,1594,1600,1607,1614,1622,1630,1639,1648,1657,1664,1671,1706,1716,1726,1736,1746,1750,1758,1765,1775,1784,1791,1798,1805,1816,1827,1838,1849,1860,1871,1882,1893,1904,1911,1918,1927,1934,1941,1950,1960,1970,1980,1985,1993,2003,2010,2021,2032,2043,2054,2065,2071,2077,2084,2092,2099,2106,2115,2124,2133,2143,2150,2157,2163,2177,2188,2200,2212,2224,2236,2248,2260,2266,2275,2285,2295,2304,2309,2317,2327,2334,2345,2354,2360,2366,2372,2378,2384,2391,2399,2405,2412,2421,2431,2440,2449,2456,2508,2517,2526,2535,2544,2549,2557,2564,2573,2582,2592,2599,2606,2613,2620,2627,2634,2643,2650,2659,2666,2673,2682,2692,2701,2710,2717,2724,2729,2740,2752,2764,2776,2781,2790,2799,2808,2818,2823,2831,2838,2847,2856,2866,2873,2880,2887,2894,2903,2910,2919,2926,2933,2940,2947,2956,2966,2975,2984,2989,2997,3004,3013,3022,3031,3037,3043,3049,3055,3061,3067,3074,3081,3088,3095,3104,3111,3120,3127,3134,3143,3150,3157,3166,3175,3184,3191,3217,3226,3235,3244,3253,3258,3265,3272,3279,3286,3293,3300,3307,3312,3320,3328],{"__ignoreMap":194},[198,1321,1322,1325,1327],{"class":200,"line":201},[198,1323,1324],{"class":204},"name",[198,1326,281],{"class":208},[198,1328,1329],{"class":284}," paragonrentals_production\n",[198,1331,1332],{"class":200,"line":212},[198,1333,342],{"emptyLinePlaceholder":341},[198,1335,1336,1339],{"class":200,"line":14},[198,1337,1338],{"class":204},"services",[198,1340,209],{"class":208},[198,1342,1343,1346],{"class":200,"line":227},[198,1344,1345],{"class":204},"  nginx-production",[198,1347,209],{"class":208},[198,1349,1350,1353,1355],{"class":200,"line":235},[198,1351,1352],{"class":204},"    image",[198,1354,281],{"class":208},[198,1356,1357],{"class":284}," nginx:1.31-alpine\n",[198,1359,1360,1363],{"class":200,"line":243},[198,1361,1362],{"class":204},"    volumes",[198,1364,209],{"class":208},[198,1366,1367,1370],{"class":200,"line":251},[198,1368,1369],{"class":208},"      -",[198,1371,1372],{"class":284}," .\u002Fbackend\u002Fdocker\u002Fnginx-production.conf:\u002Fetc\u002Fnginx\u002Fconf.d\u002Fdefault.conf:ro\n",[198,1374,1375,1377],{"class":200,"line":259},[198,1376,1369],{"class":208},[198,1378,1379],{"class":284}," backend-production-storage:\u002Fvar\u002Fwww\u002Fstorage:ro\n",[198,1381,1382,1384],{"class":200,"line":267},[198,1383,1369],{"class":208},[198,1385,1386],{"class":284}," backend-production-public:\u002Fvar\u002Fwww\u002Fpublic:ro\n",[198,1388,1389,1392],{"class":200,"line":275},[198,1390,1391],{"class":204},"    depends_on",[198,1393,209],{"class":208},[198,1395,1396,1399],{"class":200,"line":360},[198,1397,1398],{"class":204},"      backend-production",[198,1400,209],{"class":208},[198,1402,1403,1406,1408],{"class":200,"line":365},[198,1404,1405],{"class":204},"        condition",[198,1407,281],{"class":208},[198,1409,1410],{"class":284}," service_healthy\n",[198,1412,1413,1416],{"class":200,"line":27},[198,1414,1415],{"class":204},"    networks",[198,1417,209],{"class":208},[198,1419,1420,1422],{"class":200,"line":376},[198,1421,1369],{"class":208},[198,1423,1424],{"class":284}," production-network\n",[198,1426,1427,1430,1432],{"class":200,"line":382},[198,1428,1429],{"class":204},"    restart",[198,1431,281],{"class":208},[198,1433,1434],{"class":284}," unless-stopped\n",[198,1436,1437,1440,1442],{"class":200,"line":388},[198,1438,1439],{"class":204},"    cpus",[198,1441,281],{"class":208},[198,1443,1445],{"class":1444},"sYThS"," 0.15\n",[198,1447,1448,1451,1453],{"class":200,"line":394},[198,1449,1450],{"class":204},"    mem_limit",[198,1452,281],{"class":208},[198,1454,1455],{"class":284}," 128m\n",[198,1457,1458,1461,1463],{"class":200,"line":400},[198,1459,1460],{"class":204},"    mem_reservation",[198,1462,281],{"class":208},[198,1464,1465],{"class":284}," 64m\n",[198,1467,1468],{"class":200,"line":405},[198,1469,342],{"emptyLinePlaceholder":341},[198,1471,1472,1475],{"class":200,"line":410},[198,1473,1474],{"class":204},"  backend-production",[198,1476,209],{"class":208},[198,1478,1479,1482],{"class":200,"line":416},[198,1480,1481],{"class":204},"    build",[198,1483,209],{"class":208},[198,1485,1486,1489,1491],{"class":200,"line":422},[198,1487,1488],{"class":204},"      context",[198,1490,281],{"class":208},[198,1492,1493],{"class":284}," .\u002Fbackend\n",[198,1495,1496,1499,1501],{"class":200,"line":427},[198,1497,1498],{"class":204},"      dockerfile",[198,1500,281],{"class":208},[198,1502,1503],{"class":284}," Dockerfile.production\n",[198,1505,1506,1509],{"class":200,"line":563},[198,1507,1508],{"class":204},"    env_file",[198,1510,209],{"class":208},[198,1512,1513,1515],{"class":200,"line":569},[198,1514,1369],{"class":208},[198,1516,1517],{"class":284}," .env\n",[198,1519,1520,1523],{"class":200,"line":575},[198,1521,1522],{"class":204},"    environment",[198,1524,209],{"class":208},[198,1526,1527,1530,1532,1534,1536],{"class":200,"line":580},[198,1528,1529],{"class":204},"      RUN_MIGRATIONS",[198,1531,281],{"class":208},[198,1533,857],{"class":856},[198,1535,931],{"class":284},[198,1537,863],{"class":856},[198,1539,1540,1542],{"class":200,"line":585},[198,1541,1391],{"class":204},[198,1543,209],{"class":208},[198,1545,1546,1549],{"class":200,"line":591},[198,1547,1548],{"class":204},"      mysql-production",[198,1550,209],{"class":208},[198,1552,1553,1555,1557],{"class":200,"line":597},[198,1554,1405],{"class":204},[198,1556,281],{"class":208},[198,1558,1410],{"class":284},[198,1560,1561,1564],{"class":200,"line":602},[198,1562,1563],{"class":204},"      redis-production",[198,1565,209],{"class":208},[198,1567,1568,1570,1572],{"class":200,"line":608},[198,1569,1405],{"class":204},[198,1571,281],{"class":208},[198,1573,1410],{"class":284},[198,1575,1576,1578],{"class":200,"line":613},[198,1577,1362],{"class":204},[198,1579,209],{"class":208},[198,1581,1582,1584],{"class":200,"line":619},[198,1583,1369],{"class":208},[198,1585,1586],{"class":284}," backend-production-storage:\u002Fvar\u002Fwww\u002Fstorage\n",[198,1588,1589,1591],{"class":200,"line":625},[198,1590,1369],{"class":208},[198,1592,1593],{"class":284}," backend-production-public:\u002Fvar\u002Fwww\u002Fpublic\n",[198,1595,1596,1598],{"class":200,"line":630},[198,1597,1415],{"class":204},[198,1599,209],{"class":208},[198,1601,1602,1605],{"class":200,"line":635},[198,1603,1604],{"class":204},"      production-network",[198,1606,209],{"class":208},[198,1608,1609,1612],{"class":200,"line":640},[198,1610,1611],{"class":204},"        aliases",[198,1613,209],{"class":208},[198,1615,1616,1619],{"class":200,"line":646},[198,1617,1618],{"class":208},"          -",[198,1620,1621],{"class":284}," backend\n",[198,1623,1624,1626,1628],{"class":200,"line":652},[198,1625,1429],{"class":204},[198,1627,281],{"class":208},[198,1629,1434],{"class":284},[198,1631,1632,1634,1636],{"class":200,"line":658},[198,1633,1439],{"class":204},[198,1635,281],{"class":208},[198,1637,1638],{"class":1444}," 0.75\n",[198,1640,1641,1643,1645],{"class":200,"line":664},[198,1642,1450],{"class":204},[198,1644,281],{"class":208},[198,1646,1647],{"class":284}," 896m\n",[198,1649,1650,1652,1654],{"class":200,"line":669},[198,1651,1460],{"class":204},[198,1653,281],{"class":208},[198,1655,1656],{"class":284}," 512m\n",[198,1658,1659,1662],{"class":200,"line":675},[198,1660,1661],{"class":204},"    healthcheck",[198,1663,209],{"class":208},[198,1665,1666,1669],{"class":200,"line":681},[198,1667,1668],{"class":204},"      test",[198,1670,209],{"class":208},[198,1672,1673,1676,1678,1681,1683,1686,1689,1692,1695,1698,1700,1703],{"class":200,"line":686},[198,1674,1675],{"class":208},"        [",[198,1677,922],{"class":856},[198,1679,1680],{"class":284},"CMD-SHELL",[198,1682,922],{"class":856},[198,1684,1685],{"class":208},",",[198,1687,1688],{"class":856}," '",[198,1690,1691],{"class":284},"php -r ",[198,1693,1694],{"class":774},"''",[198,1696,1697],{"class":284},"exit(@fsockopen(\"127.0.0.1\", 9000) ? 0 : 1);",[198,1699,1694],{"class":774},[198,1701,1702],{"class":856},"'",[198,1704,1705],{"class":208},"]\n",[198,1707,1708,1711,1713],{"class":200,"line":692},[198,1709,1710],{"class":204},"      interval",[198,1712,281],{"class":208},[198,1714,1715],{"class":284}," 60s\n",[198,1717,1718,1721,1723],{"class":200,"line":697},[198,1719,1720],{"class":204},"      timeout",[198,1722,281],{"class":208},[198,1724,1725],{"class":284}," 5s\n",[198,1727,1728,1731,1733],{"class":200,"line":703},[198,1729,1730],{"class":204},"      retries",[198,1732,281],{"class":208},[198,1734,1735],{"class":1444}," 3\n",[198,1737,1738,1741,1743],{"class":200,"line":708},[198,1739,1740],{"class":204},"      start_period",[198,1742,281],{"class":208},[198,1744,1745],{"class":284}," 30s\n",[198,1747,1748],{"class":200,"line":714},[198,1749,342],{"emptyLinePlaceholder":341},[198,1751,1753,1756],{"class":200,"line":1752},52,[198,1754,1755],{"class":204},"  frontend-production",[198,1757,209],{"class":208},[198,1759,1761,1763],{"class":200,"line":1760},53,[198,1762,1481],{"class":204},[198,1764,209],{"class":208},[198,1766,1768,1770,1772],{"class":200,"line":1767},54,[198,1769,1488],{"class":204},[198,1771,281],{"class":208},[198,1773,1774],{"class":284}," .\u002Ffrontend\n",[198,1776,1778,1780,1782],{"class":200,"line":1777},55,[198,1779,1498],{"class":204},[198,1781,281],{"class":208},[198,1783,1503],{"class":284},[198,1785,1787,1789],{"class":200,"line":1786},56,[198,1788,1508],{"class":204},[198,1790,209],{"class":208},[198,1792,1794,1796],{"class":200,"line":1793},57,[198,1795,1369],{"class":208},[198,1797,1517],{"class":284},[198,1799,1801,1803],{"class":200,"line":1800},58,[198,1802,1522],{"class":204},[198,1804,209],{"class":208},[198,1806,1808,1811,1813],{"class":200,"line":1807},59,[198,1809,1810],{"class":204},"      NUXT_LARAVEL_API_URL",[198,1812,281],{"class":208},[198,1814,1815],{"class":284}," ${NUXT_LARAVEL_API_URL}\n",[198,1817,1819,1822,1824],{"class":200,"line":1818},60,[198,1820,1821],{"class":204},"      NUXT_LARAVEL_BASE_URL",[198,1823,281],{"class":208},[198,1825,1826],{"class":284}," ${NUXT_LARAVEL_BASE_URL}\n",[198,1828,1830,1833,1835],{"class":200,"line":1829},61,[198,1831,1832],{"class":204},"      NUXT_PUBLIC_LARAVEL_BASE_URL",[198,1834,281],{"class":208},[198,1836,1837],{"class":284}," ${NUXT_PUBLIC_LARAVEL_BASE_URL}\n",[198,1839,1841,1844,1846],{"class":200,"line":1840},62,[198,1842,1843],{"class":204},"      NUXT_PUBLIC_LARAVEL_API_URL",[198,1845,281],{"class":208},[198,1847,1848],{"class":284}," ${NUXT_PUBLIC_LARAVEL_API_URL}\n",[198,1850,1852,1855,1857],{"class":200,"line":1851},63,[198,1853,1854],{"class":204},"      NUXT_PUBLIC_APP_URL",[198,1856,281],{"class":208},[198,1858,1859],{"class":284}," ${NUXT_PUBLIC_APP_URL}\n",[198,1861,1863,1866,1868],{"class":200,"line":1862},64,[198,1864,1865],{"class":204},"      NUXT_PUBLIC_REVERB_APP_KEY",[198,1867,281],{"class":208},[198,1869,1870],{"class":284}," ${NUXT_PUBLIC_REVERB_APP_KEY}\n",[198,1872,1874,1877,1879],{"class":200,"line":1873},65,[198,1875,1876],{"class":204},"      NUXT_PUBLIC_REVERB_HOST",[198,1878,281],{"class":208},[198,1880,1881],{"class":284}," ${NUXT_PUBLIC_REVERB_HOST}\n",[198,1883,1885,1888,1890],{"class":200,"line":1884},66,[198,1886,1887],{"class":204},"      NUXT_PUBLIC_REVERB_PORT",[198,1889,281],{"class":208},[198,1891,1892],{"class":284}," ${NUXT_PUBLIC_REVERB_PORT}\n",[198,1894,1896,1899,1901],{"class":200,"line":1895},67,[198,1897,1898],{"class":204},"      NUXT_PUBLIC_REVERB_SCHEME",[198,1900,281],{"class":208},[198,1902,1903],{"class":284}," ${NUXT_PUBLIC_REVERB_SCHEME}\n",[198,1905,1907,1909],{"class":200,"line":1906},68,[198,1908,1391],{"class":204},[198,1910,209],{"class":208},[198,1912,1914,1916],{"class":200,"line":1913},69,[198,1915,1398],{"class":204},[198,1917,209],{"class":208},[198,1919,1921,1923,1925],{"class":200,"line":1920},70,[198,1922,1405],{"class":204},[198,1924,281],{"class":208},[198,1926,1410],{"class":284},[198,1928,1930,1932],{"class":200,"line":1929},71,[198,1931,1415],{"class":204},[198,1933,209],{"class":208},[198,1935,1937,1939],{"class":200,"line":1936},72,[198,1938,1369],{"class":208},[198,1940,1424],{"class":284},[198,1942,1944,1946,1948],{"class":200,"line":1943},73,[198,1945,1429],{"class":204},[198,1947,281],{"class":208},[198,1949,1434],{"class":284},[198,1951,1953,1955,1957],{"class":200,"line":1952},74,[198,1954,1439],{"class":204},[198,1956,281],{"class":208},[198,1958,1959],{"class":1444}," 0.50\n",[198,1961,1963,1965,1967],{"class":200,"line":1962},75,[198,1964,1450],{"class":204},[198,1966,281],{"class":208},[198,1968,1969],{"class":284}," 768m\n",[198,1971,1973,1975,1977],{"class":200,"line":1972},76,[198,1974,1460],{"class":204},[198,1976,281],{"class":208},[198,1978,1979],{"class":284}," 256m\n",[198,1981,1983],{"class":200,"line":1982},77,[198,1984,342],{"emptyLinePlaceholder":341},[198,1986,1988,1991],{"class":200,"line":1987},78,[198,1989,1990],{"class":204},"  mysql-production",[198,1992,209],{"class":208},[198,1994,1996,1998,2000],{"class":200,"line":1995},79,[198,1997,1352],{"class":204},[198,1999,281],{"class":208},[198,2001,2002],{"class":284}," mysql:8.0\n",[198,2004,2006,2008],{"class":200,"line":2005},80,[198,2007,1522],{"class":204},[198,2009,209],{"class":208},[198,2011,2013,2016,2018],{"class":200,"line":2012},81,[198,2014,2015],{"class":204},"      MYSQL_ROOT_PASSWORD",[198,2017,281],{"class":208},[198,2019,2020],{"class":284}," ${DB_ROOT_PASSWORD}\n",[198,2022,2024,2027,2029],{"class":200,"line":2023},82,[198,2025,2026],{"class":204},"      MYSQL_DATABASE",[198,2028,281],{"class":208},[198,2030,2031],{"class":284}," ${DB_DATABASE}\n",[198,2033,2035,2038,2040],{"class":200,"line":2034},83,[198,2036,2037],{"class":204},"      MYSQL_USER",[198,2039,281],{"class":208},[198,2041,2042],{"class":284}," ${DB_USERNAME}\n",[198,2044,2046,2049,2051],{"class":200,"line":2045},84,[198,2047,2048],{"class":204},"      MYSQL_PASSWORD",[198,2050,281],{"class":208},[198,2052,2053],{"class":284}," ${DB_PASSWORD}\n",[198,2055,2057,2060,2062],{"class":200,"line":2056},85,[198,2058,2059],{"class":204},"    command",[198,2061,281],{"class":208},[198,2063,2064],{"class":832}," >\n",[198,2066,2068],{"class":200,"line":2067},86,[198,2069,2070],{"class":284},"      --innodb-buffer-pool-size=256M\n",[198,2072,2074],{"class":200,"line":2073},87,[198,2075,2076],{"class":284},"      --max-connections=50\n",[198,2078,2080,2082],{"class":200,"line":2079},88,[198,2081,1362],{"class":204},[198,2083,209],{"class":208},[198,2085,2087,2089],{"class":200,"line":2086},89,[198,2088,1369],{"class":208},[198,2090,2091],{"class":284}," mysql-production-data:\u002Fvar\u002Flib\u002Fmysql\n",[198,2093,2095,2097],{"class":200,"line":2094},90,[198,2096,1415],{"class":204},[198,2098,209],{"class":208},[198,2100,2102,2104],{"class":200,"line":2101},91,[198,2103,1369],{"class":208},[198,2105,1424],{"class":284},[198,2107,2109,2111,2113],{"class":200,"line":2108},92,[198,2110,1429],{"class":204},[198,2112,281],{"class":208},[198,2114,1434],{"class":284},[198,2116,2118,2120,2122],{"class":200,"line":2117},93,[198,2119,1439],{"class":204},[198,2121,281],{"class":208},[198,2123,1638],{"class":1444},[198,2125,2127,2129,2131],{"class":200,"line":2126},94,[198,2128,1450],{"class":204},[198,2130,281],{"class":208},[198,2132,1969],{"class":284},[198,2134,2136,2138,2140],{"class":200,"line":2135},95,[198,2137,1460],{"class":204},[198,2139,281],{"class":208},[198,2141,2142],{"class":284}," 384m\n",[198,2144,2146,2148],{"class":200,"line":2145},96,[198,2147,1661],{"class":204},[198,2149,209],{"class":208},[198,2151,2153,2155],{"class":200,"line":2152},97,[198,2154,1668],{"class":204},[198,2156,209],{"class":208},[198,2158,2160],{"class":200,"line":2159},98,[198,2161,2162],{"class":208},"        [\n",[198,2164,2166,2169,2172,2174],{"class":200,"line":2165},99,[198,2167,2168],{"class":856},"          \"",[198,2170,2171],{"class":284},"CMD",[198,2173,922],{"class":856},[198,2175,2176],{"class":208},",\n",[198,2178,2179,2181,2184,2186],{"class":200,"line":21},[198,2180,2168],{"class":856},[198,2182,2183],{"class":284},"mysqladmin",[198,2185,922],{"class":856},[198,2187,2176],{"class":208},[198,2189,2191,2193,2196,2198],{"class":200,"line":2190},101,[198,2192,2168],{"class":856},[198,2194,2195],{"class":284},"ping",[198,2197,922],{"class":856},[198,2199,2176],{"class":208},[198,2201,2203,2205,2208,2210],{"class":200,"line":2202},102,[198,2204,2168],{"class":856},[198,2206,2207],{"class":284},"-h",[198,2209,922],{"class":856},[198,2211,2176],{"class":208},[198,2213,2215,2217,2220,2222],{"class":200,"line":2214},103,[198,2216,2168],{"class":856},[198,2218,2219],{"class":284},"localhost",[198,2221,922],{"class":856},[198,2223,2176],{"class":208},[198,2225,2227,2229,2232,2234],{"class":200,"line":2226},104,[198,2228,2168],{"class":856},[198,2230,2231],{"class":284},"-u",[198,2233,922],{"class":856},[198,2235,2176],{"class":208},[198,2237,2239,2241,2244,2246],{"class":200,"line":2238},105,[198,2240,2168],{"class":856},[198,2242,2243],{"class":284},"root",[198,2245,922],{"class":856},[198,2247,2176],{"class":208},[198,2249,2251,2253,2256,2258],{"class":200,"line":2250},106,[198,2252,2168],{"class":856},[198,2254,2255],{"class":284},"-p${DB_ROOT_PASSWORD}",[198,2257,922],{"class":856},[198,2259,2176],{"class":208},[198,2261,2263],{"class":200,"line":2262},107,[198,2264,2265],{"class":208},"        ]\n",[198,2267,2269,2271,2273],{"class":200,"line":2268},108,[198,2270,1710],{"class":204},[198,2272,281],{"class":208},[198,2274,1715],{"class":284},[198,2276,2278,2280,2282],{"class":200,"line":2277},109,[198,2279,1720],{"class":204},[198,2281,281],{"class":208},[198,2283,2284],{"class":284}," 10s\n",[198,2286,2288,2290,2292],{"class":200,"line":2287},110,[198,2289,1730],{"class":204},[198,2291,281],{"class":208},[198,2293,2294],{"class":1444}," 5\n",[198,2296,2298,2300,2302],{"class":200,"line":2297},111,[198,2299,1740],{"class":204},[198,2301,281],{"class":208},[198,2303,1715],{"class":284},[198,2305,2307],{"class":200,"line":2306},112,[198,2308,342],{"emptyLinePlaceholder":341},[198,2310,2312,2315],{"class":200,"line":2311},113,[198,2313,2314],{"class":204},"  redis-production",[198,2316,209],{"class":208},[198,2318,2320,2322,2324],{"class":200,"line":2319},114,[198,2321,1352],{"class":204},[198,2323,281],{"class":208},[198,2325,2326],{"class":284}," redis:8-alpine\n",[198,2328,2330,2332],{"class":200,"line":2329},115,[198,2331,1522],{"class":204},[198,2333,209],{"class":208},[198,2335,2337,2340,2342],{"class":200,"line":2336},116,[198,2338,2339],{"class":204},"      REDIS_PASSWORD",[198,2341,281],{"class":208},[198,2343,2344],{"class":284}," ${REDIS_PASSWORD}\n",[198,2346,2348,2350,2352],{"class":200,"line":2347},117,[198,2349,2059],{"class":204},[198,2351,281],{"class":208},[198,2353,2064],{"class":832},[198,2355,2357],{"class":200,"line":2356},118,[198,2358,2359],{"class":284},"      redis-server\n",[198,2361,2363],{"class":200,"line":2362},119,[198,2364,2365],{"class":284},"      --requirepass ${REDIS_PASSWORD}\n",[198,2367,2369],{"class":200,"line":2368},120,[198,2370,2371],{"class":284},"      --appendonly yes\n",[198,2373,2375],{"class":200,"line":2374},121,[198,2376,2377],{"class":284},"      --maxmemory 96mb\n",[198,2379,2381],{"class":200,"line":2380},122,[198,2382,2383],{"class":284},"      --maxmemory-policy allkeys-lru\n",[198,2385,2387,2389],{"class":200,"line":2386},123,[198,2388,1362],{"class":204},[198,2390,209],{"class":208},[198,2392,2394,2396],{"class":200,"line":2393},124,[198,2395,1369],{"class":208},[198,2397,2398],{"class":284}," redis-production-data:\u002Fdata\n",[198,2400,2401,2403],{"class":200,"line":46},[198,2402,1415],{"class":204},[198,2404,209],{"class":208},[198,2406,2408,2410],{"class":200,"line":2407},126,[198,2409,1369],{"class":208},[198,2411,1424],{"class":284},[198,2413,2415,2417,2419],{"class":200,"line":2414},127,[198,2416,1429],{"class":204},[198,2418,281],{"class":208},[198,2420,1434],{"class":284},[198,2422,2424,2426,2428],{"class":200,"line":2423},128,[198,2425,1439],{"class":204},[198,2427,281],{"class":208},[198,2429,2430],{"class":1444}," 0.20\n",[198,2432,2434,2436,2438],{"class":200,"line":2433},129,[198,2435,1450],{"class":204},[198,2437,281],{"class":208},[198,2439,1455],{"class":284},[198,2441,2443,2445,2447],{"class":200,"line":2442},130,[198,2444,1460],{"class":204},[198,2446,281],{"class":208},[198,2448,1465],{"class":284},[198,2450,2452,2454],{"class":200,"line":2451},131,[198,2453,1661],{"class":204},[198,2455,209],{"class":208},[198,2457,2459,2461,2463,2465,2467,2469,2471,2473,2475,2478,2480,2482,2484,2487,2489,2491,2493,2496,2498,2500,2502,2504,2506],{"class":200,"line":2458},132,[198,2460,1668],{"class":204},[198,2462,281],{"class":208},[198,2464,913],{"class":208},[198,2466,922],{"class":856},[198,2468,2171],{"class":284},[198,2470,922],{"class":856},[198,2472,1685],{"class":208},[198,2474,857],{"class":856},[198,2476,2477],{"class":284},"redis-cli",[198,2479,922],{"class":856},[198,2481,1685],{"class":208},[198,2483,857],{"class":856},[198,2485,2486],{"class":284},"-a",[198,2488,922],{"class":856},[198,2490,1685],{"class":208},[198,2492,857],{"class":856},[198,2494,2495],{"class":284},"${REDIS_PASSWORD}",[198,2497,922],{"class":856},[198,2499,1685],{"class":208},[198,2501,857],{"class":856},[198,2503,2195],{"class":284},[198,2505,922],{"class":856},[198,2507,1705],{"class":208},[198,2509,2511,2513,2515],{"class":200,"line":2510},133,[198,2512,1710],{"class":204},[198,2514,281],{"class":208},[198,2516,1715],{"class":284},[198,2518,2520,2522,2524],{"class":200,"line":2519},134,[198,2521,1720],{"class":204},[198,2523,281],{"class":208},[198,2525,1725],{"class":284},[198,2527,2529,2531,2533],{"class":200,"line":2528},135,[198,2530,1730],{"class":204},[198,2532,281],{"class":208},[198,2534,2294],{"class":1444},[198,2536,2538,2540,2542],{"class":200,"line":2537},136,[198,2539,1740],{"class":204},[198,2541,281],{"class":208},[198,2543,2284],{"class":284},[198,2545,2547],{"class":200,"line":2546},137,[198,2548,342],{"emptyLinePlaceholder":341},[198,2550,2552,2555],{"class":200,"line":2551},138,[198,2553,2554],{"class":204},"  reverb-production",[198,2556,209],{"class":208},[198,2558,2560,2562],{"class":200,"line":2559},139,[198,2561,1481],{"class":204},[198,2563,209],{"class":208},[198,2565,2567,2569,2571],{"class":200,"line":2566},140,[198,2568,1488],{"class":204},[198,2570,281],{"class":208},[198,2572,1493],{"class":284},[198,2574,2576,2578,2580],{"class":200,"line":2575},141,[198,2577,1498],{"class":204},[198,2579,281],{"class":208},[198,2581,1503],{"class":284},[198,2583,2585,2587,2589],{"class":200,"line":2584},142,[198,2586,2059],{"class":204},[198,2588,281],{"class":208},[198,2590,2591],{"class":284}," sh -c 'php artisan reverb:start --host=0.0.0.0 --port=${REVERB_PORT:-6001}'\n",[198,2593,2595,2597],{"class":200,"line":2594},143,[198,2596,1508],{"class":204},[198,2598,209],{"class":208},[198,2600,2602,2604],{"class":200,"line":2601},144,[198,2603,1369],{"class":208},[198,2605,1517],{"class":284},[198,2607,2609,2611],{"class":200,"line":2608},145,[198,2610,1415],{"class":204},[198,2612,209],{"class":208},[198,2614,2616,2618],{"class":200,"line":2615},146,[198,2617,1369],{"class":208},[198,2619,1424],{"class":284},[198,2621,2623,2625],{"class":200,"line":2622},147,[198,2624,1391],{"class":204},[198,2626,209],{"class":208},[198,2628,2630,2632],{"class":200,"line":2629},148,[198,2631,1398],{"class":204},[198,2633,209],{"class":208},[198,2635,2637,2639,2641],{"class":200,"line":2636},149,[198,2638,1405],{"class":204},[198,2640,281],{"class":208},[198,2642,1410],{"class":284},[198,2644,2646,2648],{"class":200,"line":2645},150,[198,2647,1563],{"class":204},[198,2649,209],{"class":208},[198,2651,2653,2655,2657],{"class":200,"line":2652},151,[198,2654,1405],{"class":204},[198,2656,281],{"class":208},[198,2658,1410],{"class":284},[198,2660,2662,2664],{"class":200,"line":2661},152,[198,2663,1362],{"class":204},[198,2665,209],{"class":208},[198,2667,2669,2671],{"class":200,"line":2668},153,[198,2670,1369],{"class":208},[198,2672,1586],{"class":284},[198,2674,2676,2678,2680],{"class":200,"line":2675},154,[198,2677,1429],{"class":204},[198,2679,281],{"class":208},[198,2681,1434],{"class":284},[198,2683,2685,2687,2689],{"class":200,"line":2684},155,[198,2686,1439],{"class":204},[198,2688,281],{"class":208},[198,2690,2691],{"class":1444}," 0.25\n",[198,2693,2695,2697,2699],{"class":200,"line":2694},156,[198,2696,1450],{"class":204},[198,2698,281],{"class":208},[198,2700,2142],{"class":284},[198,2702,2704,2706,2708],{"class":200,"line":2703},157,[198,2705,1460],{"class":204},[198,2707,281],{"class":208},[198,2709,1455],{"class":284},[198,2711,2713,2715],{"class":200,"line":2712},158,[198,2714,1661],{"class":204},[198,2716,209],{"class":208},[198,2718,2720,2722],{"class":200,"line":2719},159,[198,2721,1668],{"class":204},[198,2723,209],{"class":208},[198,2725,2727],{"class":200,"line":2726},160,[198,2728,2162],{"class":208},[198,2730,2732,2734,2736,2738],{"class":200,"line":2731},161,[198,2733,2168],{"class":856},[198,2735,2171],{"class":284},[198,2737,922],{"class":856},[198,2739,2176],{"class":208},[198,2741,2743,2745,2748,2750],{"class":200,"line":2742},162,[198,2744,2168],{"class":856},[198,2746,2747],{"class":284},"php",[198,2749,922],{"class":856},[198,2751,2176],{"class":208},[198,2753,2755,2757,2760,2762],{"class":200,"line":2754},163,[198,2756,2168],{"class":856},[198,2758,2759],{"class":284},"-r",[198,2761,922],{"class":856},[198,2763,2176],{"class":208},[198,2765,2767,2769,2772,2774],{"class":200,"line":2766},164,[198,2768,2168],{"class":856},[198,2770,2771],{"class":284},"exit(@fsockopen('127.0.0.1', getenv('REVERB_PORT') ?: 6001) ? 0 : 1);",[198,2773,922],{"class":856},[198,2775,2176],{"class":208},[198,2777,2779],{"class":200,"line":2778},165,[198,2780,2265],{"class":208},[198,2782,2784,2786,2788],{"class":200,"line":2783},166,[198,2785,1710],{"class":204},[198,2787,281],{"class":208},[198,2789,1715],{"class":284},[198,2791,2793,2795,2797],{"class":200,"line":2792},167,[198,2794,1720],{"class":204},[198,2796,281],{"class":208},[198,2798,1725],{"class":284},[198,2800,2802,2804,2806],{"class":200,"line":2801},168,[198,2803,1730],{"class":204},[198,2805,281],{"class":208},[198,2807,1735],{"class":1444},[198,2809,2811,2813,2815],{"class":200,"line":2810},169,[198,2812,1740],{"class":204},[198,2814,281],{"class":208},[198,2816,2817],{"class":284}," 15s\n",[198,2819,2821],{"class":200,"line":2820},170,[198,2822,342],{"emptyLinePlaceholder":341},[198,2824,2826,2829],{"class":200,"line":2825},171,[198,2827,2828],{"class":204},"  scheduler-production",[198,2830,209],{"class":208},[198,2832,2834,2836],{"class":200,"line":2833},172,[198,2835,1481],{"class":204},[198,2837,209],{"class":208},[198,2839,2841,2843,2845],{"class":200,"line":2840},173,[198,2842,1488],{"class":204},[198,2844,281],{"class":208},[198,2846,1493],{"class":284},[198,2848,2850,2852,2854],{"class":200,"line":2849},174,[198,2851,1498],{"class":204},[198,2853,281],{"class":208},[198,2855,1503],{"class":284},[198,2857,2859,2861,2863],{"class":200,"line":2858},175,[198,2860,2059],{"class":204},[198,2862,281],{"class":208},[198,2864,2865],{"class":284}," php artisan schedule:work\n",[198,2867,2869,2871],{"class":200,"line":2868},176,[198,2870,1508],{"class":204},[198,2872,209],{"class":208},[198,2874,2876,2878],{"class":200,"line":2875},177,[198,2877,1369],{"class":208},[198,2879,1517],{"class":284},[198,2881,2883,2885],{"class":200,"line":2882},178,[198,2884,1391],{"class":204},[198,2886,209],{"class":208},[198,2888,2890,2892],{"class":200,"line":2889},179,[198,2891,1398],{"class":204},[198,2893,209],{"class":208},[198,2895,2897,2899,2901],{"class":200,"line":2896},180,[198,2898,1405],{"class":204},[198,2900,281],{"class":208},[198,2902,1410],{"class":284},[198,2904,2906,2908],{"class":200,"line":2905},181,[198,2907,1563],{"class":204},[198,2909,209],{"class":208},[198,2911,2913,2915,2917],{"class":200,"line":2912},182,[198,2914,1405],{"class":204},[198,2916,281],{"class":208},[198,2918,1410],{"class":284},[198,2920,2922,2924],{"class":200,"line":2921},183,[198,2923,1362],{"class":204},[198,2925,209],{"class":208},[198,2927,2929,2931],{"class":200,"line":2928},184,[198,2930,1369],{"class":208},[198,2932,1586],{"class":284},[198,2934,2936,2938],{"class":200,"line":2935},185,[198,2937,1415],{"class":204},[198,2939,209],{"class":208},[198,2941,2943,2945],{"class":200,"line":2942},186,[198,2944,1369],{"class":208},[198,2946,1424],{"class":284},[198,2948,2950,2952,2954],{"class":200,"line":2949},187,[198,2951,1429],{"class":204},[198,2953,281],{"class":208},[198,2955,1434],{"class":284},[198,2957,2959,2961,2963],{"class":200,"line":2958},188,[198,2960,1439],{"class":204},[198,2962,281],{"class":208},[198,2964,2965],{"class":1444}," 0.10\n",[198,2967,2969,2971,2973],{"class":200,"line":2968},189,[198,2970,1450],{"class":204},[198,2972,281],{"class":208},[198,2974,1979],{"class":284},[198,2976,2978,2980,2982],{"class":200,"line":2977},190,[198,2979,1460],{"class":204},[198,2981,281],{"class":208},[198,2983,1465],{"class":284},[198,2985,2987],{"class":200,"line":2986},191,[198,2988,342],{"emptyLinePlaceholder":341},[198,2990,2992,2995],{"class":200,"line":2991},192,[198,2993,2994],{"class":204},"  worker-production",[198,2996,209],{"class":208},[198,2998,3000,3002],{"class":200,"line":2999},193,[198,3001,1481],{"class":204},[198,3003,209],{"class":208},[198,3005,3007,3009,3011],{"class":200,"line":3006},194,[198,3008,1488],{"class":204},[198,3010,281],{"class":208},[198,3012,1493],{"class":284},[198,3014,3016,3018,3020],{"class":200,"line":3015},195,[198,3017,1498],{"class":204},[198,3019,281],{"class":208},[198,3021,1503],{"class":284},[198,3023,3025,3027,3029],{"class":200,"line":3024},196,[198,3026,2059],{"class":204},[198,3028,281],{"class":208},[198,3030,2064],{"class":832},[198,3032,3034],{"class":200,"line":3033},197,[198,3035,3036],{"class":284},"      php artisan queue:work\n",[198,3038,3040],{"class":200,"line":3039},198,[198,3041,3042],{"class":284},"      --verbose\n",[198,3044,3046],{"class":200,"line":3045},199,[198,3047,3048],{"class":284},"      --tries=3\n",[198,3050,3052],{"class":200,"line":3051},200,[198,3053,3054],{"class":284},"      --timeout=90\n",[198,3056,3058],{"class":200,"line":3057},201,[198,3059,3060],{"class":284},"      --sleep=3\n",[198,3062,3064],{"class":200,"line":3063},202,[198,3065,3066],{"class":284},"      --max-time=3600\n",[198,3068,3070,3072],{"class":200,"line":3069},203,[198,3071,1508],{"class":204},[198,3073,209],{"class":208},[198,3075,3077,3079],{"class":200,"line":3076},204,[198,3078,1369],{"class":208},[198,3080,1517],{"class":284},[198,3082,3084,3086],{"class":200,"line":3083},205,[198,3085,1391],{"class":204},[198,3087,209],{"class":208},[198,3089,3091,3093],{"class":200,"line":3090},206,[198,3092,1398],{"class":204},[198,3094,209],{"class":208},[198,3096,3098,3100,3102],{"class":200,"line":3097},207,[198,3099,1405],{"class":204},[198,3101,281],{"class":208},[198,3103,1410],{"class":284},[198,3105,3107,3109],{"class":200,"line":3106},208,[198,3108,1563],{"class":204},[198,3110,209],{"class":208},[198,3112,3114,3116,3118],{"class":200,"line":3113},209,[198,3115,1405],{"class":204},[198,3117,281],{"class":208},[198,3119,1410],{"class":284},[198,3121,3123,3125],{"class":200,"line":3122},210,[198,3124,1362],{"class":204},[198,3126,209],{"class":208},[198,3128,3130,3132],{"class":200,"line":3129},211,[198,3131,1369],{"class":208},[198,3133,1586],{"class":284},[198,3135,3137,3139,3141],{"class":200,"line":3136},212,[198,3138,1429],{"class":204},[198,3140,281],{"class":208},[198,3142,1434],{"class":284},[198,3144,3146,3148],{"class":200,"line":3145},213,[198,3147,1415],{"class":204},[198,3149,209],{"class":208},[198,3151,3153,3155],{"class":200,"line":3152},214,[198,3154,1369],{"class":208},[198,3156,1424],{"class":284},[198,3158,3160,3162,3164],{"class":200,"line":3159},215,[198,3161,1439],{"class":204},[198,3163,281],{"class":208},[198,3165,1959],{"class":1444},[198,3167,3169,3171,3173],{"class":200,"line":3168},216,[198,3170,1450],{"class":204},[198,3172,281],{"class":208},[198,3174,1656],{"class":284},[198,3176,3178,3180,3182],{"class":200,"line":3177},217,[198,3179,1460],{"class":204},[198,3181,281],{"class":208},[198,3183,1455],{"class":284},[198,3185,3187,3189],{"class":200,"line":3186},218,[198,3188,1661],{"class":204},[198,3190,209],{"class":208},[198,3192,3194,3196,3198,3200,3202,3204,3206,3208,3210,3213,3215],{"class":200,"line":3193},219,[198,3195,1668],{"class":204},[198,3197,281],{"class":208},[198,3199,913],{"class":208},[198,3201,922],{"class":856},[198,3203,1680],{"class":284},[198,3205,922],{"class":856},[198,3207,1685],{"class":208},[198,3209,857],{"class":856},[198,3211,3212],{"class":284},"grep -q 'queue:work' \u002Fproc\u002F1\u002Fcmdline",[198,3214,922],{"class":856},[198,3216,1705],{"class":208},[198,3218,3220,3222,3224],{"class":200,"line":3219},220,[198,3221,1710],{"class":204},[198,3223,281],{"class":208},[198,3225,1715],{"class":284},[198,3227,3229,3231,3233],{"class":200,"line":3228},221,[198,3230,1720],{"class":204},[198,3232,281],{"class":208},[198,3234,1725],{"class":284},[198,3236,3238,3240,3242],{"class":200,"line":3237},222,[198,3239,1730],{"class":204},[198,3241,281],{"class":208},[198,3243,1735],{"class":1444},[198,3245,3247,3249,3251],{"class":200,"line":3246},223,[198,3248,1740],{"class":204},[198,3250,281],{"class":208},[198,3252,2817],{"class":284},[198,3254,3256],{"class":200,"line":3255},224,[198,3257,342],{"emptyLinePlaceholder":341},[198,3259,3261,3263],{"class":200,"line":3260},225,[198,3262,205],{"class":204},[198,3264,209],{"class":208},[198,3266,3268,3270],{"class":200,"line":3267},226,[198,3269,215],{"class":204},[198,3271,209],{"class":208},[198,3273,3275,3277],{"class":200,"line":3274},227,[198,3276,222],{"class":204},[198,3278,209],{"class":208},[198,3280,3282,3284],{"class":200,"line":3281},228,[198,3283,230],{"class":204},[198,3285,209],{"class":208},[198,3287,3289,3291],{"class":200,"line":3288},229,[198,3290,238],{"class":204},[198,3292,209],{"class":208},[198,3294,3296,3298],{"class":200,"line":3295},230,[198,3297,246],{"class":204},[198,3299,209],{"class":208},[198,3301,3303,3305],{"class":200,"line":3302},231,[198,3304,254],{"class":204},[198,3306,209],{"class":208},[198,3308,3310],{"class":200,"line":3309},232,[198,3311,342],{"emptyLinePlaceholder":341},[198,3313,3315,3318],{"class":200,"line":3314},233,[198,3316,3317],{"class":204},"networks",[198,3319,209],{"class":208},[198,3321,3323,3326],{"class":200,"line":3322},234,[198,3324,3325],{"class":204},"  production-network",[198,3327,209],{"class":208},[198,3329,3331,3334,3336],{"class":200,"line":3330},235,[198,3332,3333],{"class":204},"    driver",[198,3335,281],{"class":208},[198,3337,285],{"class":284},[98,3339,3341],{"id":3340},"environment-variables","Environment Variables",[121,3343,3345],{"id":3344},"the-env-file","The .env File",[102,3347,3348,3349,3352,3353,3355],{},"Create a ",[116,3350,3351],{},".env"," file at the root of your project (alongside ",[116,3354,118],{},"). Dokploy will read this file and inject variables into each service:",[189,3357,3361],{"className":3358,"code":3359,"language":3360,"meta":194,"style":194},"language-env shiki shiki-themes material-theme-lighter github-light github-dark monokai","# Database\nDB_CONNECTION=mysql\nDB_HOST=mysql-production\nDB_PORT=3306\nDB_DATABASE=your_database\nDB_USERNAME=your_username\nDB_PASSWORD=your_password\nDB_ROOT_PASSWORD=your_root_password\n\n# Redis\nREDIS_PASSWORD=your_redis_password\n\n# Laravel App\nAPP_NAME=\"Your App\"\nAPP_ENV=production\nAPP_KEY=your_base64_app_key\nAPP_DEBUG=false\nAPP_URL=https:\u002F\u002Fyourdomain.com\n\n# Reverb (WebSockets)\nREVERB_PORT=6001\nNUXT_PUBLIC_REVERB_APP_KEY=your_reverb_app_key\nNUXT_PUBLIC_REVERB_HOST=yourdomain.com\nNUXT_PUBLIC_REVERB_PORT=443\nNUXT_PUBLIC_REVERB_SCHEME=https\n\n# Nuxt Frontend\nNUXT_LARAVEL_API_URL=https:\u002F\u002Fapi.yourdomain.com\nNUXT_LARAVEL_BASE_URL=https:\u002F\u002Fapi.yourdomain.com\nNUXT_PUBLIC_LARAVEL_BASE_URL=https:\u002F\u002Fapi.yourdomain.com\nNUXT_PUBLIC_LARAVEL_API_URL=https:\u002F\u002Fapi.yourdomain.com\nNUXT_PUBLIC_APP_URL=https:\u002F\u002Fyourdomain.com\n","env",[116,3362,3363,3368,3373,3378,3383,3388,3393,3398,3403,3407,3412,3417,3421,3426,3431,3436,3441,3446,3451,3455,3460,3465,3470,3475,3480,3485,3489,3494,3499,3504,3509,3514],{"__ignoreMap":194},[198,3364,3365],{"class":200,"line":201},[198,3366,3367],{},"# Database\n",[198,3369,3370],{"class":200,"line":212},[198,3371,3372],{},"DB_CONNECTION=mysql\n",[198,3374,3375],{"class":200,"line":14},[198,3376,3377],{},"DB_HOST=mysql-production\n",[198,3379,3380],{"class":200,"line":227},[198,3381,3382],{},"DB_PORT=3306\n",[198,3384,3385],{"class":200,"line":235},[198,3386,3387],{},"DB_DATABASE=your_database\n",[198,3389,3390],{"class":200,"line":243},[198,3391,3392],{},"DB_USERNAME=your_username\n",[198,3394,3395],{"class":200,"line":251},[198,3396,3397],{},"DB_PASSWORD=your_password\n",[198,3399,3400],{"class":200,"line":259},[198,3401,3402],{},"DB_ROOT_PASSWORD=your_root_password\n",[198,3404,3405],{"class":200,"line":267},[198,3406,342],{"emptyLinePlaceholder":341},[198,3408,3409],{"class":200,"line":275},[198,3410,3411],{},"# Redis\n",[198,3413,3414],{"class":200,"line":360},[198,3415,3416],{},"REDIS_PASSWORD=your_redis_password\n",[198,3418,3419],{"class":200,"line":365},[198,3420,342],{"emptyLinePlaceholder":341},[198,3422,3423],{"class":200,"line":27},[198,3424,3425],{},"# Laravel App\n",[198,3427,3428],{"class":200,"line":376},[198,3429,3430],{},"APP_NAME=\"Your App\"\n",[198,3432,3433],{"class":200,"line":382},[198,3434,3435],{},"APP_ENV=production\n",[198,3437,3438],{"class":200,"line":388},[198,3439,3440],{},"APP_KEY=your_base64_app_key\n",[198,3442,3443],{"class":200,"line":394},[198,3444,3445],{},"APP_DEBUG=false\n",[198,3447,3448],{"class":200,"line":400},[198,3449,3450],{},"APP_URL=https:\u002F\u002Fyourdomain.com\n",[198,3452,3453],{"class":200,"line":405},[198,3454,342],{"emptyLinePlaceholder":341},[198,3456,3457],{"class":200,"line":410},[198,3458,3459],{},"# Reverb (WebSockets)\n",[198,3461,3462],{"class":200,"line":416},[198,3463,3464],{},"REVERB_PORT=6001\n",[198,3466,3467],{"class":200,"line":422},[198,3468,3469],{},"NUXT_PUBLIC_REVERB_APP_KEY=your_reverb_app_key\n",[198,3471,3472],{"class":200,"line":427},[198,3473,3474],{},"NUXT_PUBLIC_REVERB_HOST=yourdomain.com\n",[198,3476,3477],{"class":200,"line":563},[198,3478,3479],{},"NUXT_PUBLIC_REVERB_PORT=443\n",[198,3481,3482],{"class":200,"line":569},[198,3483,3484],{},"NUXT_PUBLIC_REVERB_SCHEME=https\n",[198,3486,3487],{"class":200,"line":575},[198,3488,342],{"emptyLinePlaceholder":341},[198,3490,3491],{"class":200,"line":580},[198,3492,3493],{},"# Nuxt Frontend\n",[198,3495,3496],{"class":200,"line":585},[198,3497,3498],{},"NUXT_LARAVEL_API_URL=https:\u002F\u002Fapi.yourdomain.com\n",[198,3500,3501],{"class":200,"line":591},[198,3502,3503],{},"NUXT_LARAVEL_BASE_URL=https:\u002F\u002Fapi.yourdomain.com\n",[198,3505,3506],{"class":200,"line":597},[198,3507,3508],{},"NUXT_PUBLIC_LARAVEL_BASE_URL=https:\u002F\u002Fapi.yourdomain.com\n",[198,3510,3511],{"class":200,"line":602},[198,3512,3513],{},"NUXT_PUBLIC_LARAVEL_API_URL=https:\u002F\u002Fapi.yourdomain.com\n",[198,3515,3516],{"class":200,"line":608},[198,3517,3518],{},"NUXT_PUBLIC_APP_URL=https:\u002F\u002Fyourdomain.com\n",[121,3520,3522],{"id":3521},"dokploy-environment-variables","Dokploy Environment Variables",[102,3524,3525],{},"After importing the Docker Compose file into Dokploy, you can also set environment variables through the Dokploy UI. Go to your application → Environment Variables and add them there. This is useful for secrets that shouldn't live in a file:",[3527,3528,3529,3532,3535,3538],"ol",{},[132,3530,3531],{},"Open your application in Dokploy",[132,3533,3534],{},"Click \"Environment\" in the left sidebar",[132,3536,3537],{},"Add key-value pairs for each variable",[132,3539,3540],{},"Click \"Save\"",[102,3542,3543,3544,3546,3547,3549],{},"Dokploy injects these as Docker environment variables at runtime. Variables set in the UI override values from ",[116,3545,3351],{}," files. Use the UI for secrets and ",[116,3548,3351],{}," for configuration that might change per environment.",[121,3551,3553],{"id":3552},"passing-variables-to-specific-services","Passing Variables to Specific Services",[102,3555,3556,3557,3560,3561,3564,3565,3567,3568,3570],{},"In the Docker Compose file, use the ",[116,3558,3559],{},"env_file"," and ",[116,3562,3563],{},"environment"," directives to control which variables each service receives. The ",[116,3566,143],{}," service needs application secrets. The ",[116,3569,149],{}," service needs only the public-facing URLs and Reverb configuration.",[98,3572,3574],{"id":3573},"adding-domains-in-dokploy","Adding Domains in Dokploy",[102,3576,3577],{},"Dokploy uses Traefik as a reverse proxy to route requests to your services. To expose a service on a domain:",[121,3579,3581],{"id":3580},"for-the-frontend-nuxt","For the Frontend (Nuxt)",[3527,3583,3584,3586,3589,3618],{},[132,3585,3531],{},[132,3587,3588],{},"Go to \"Domains\" in the left sidebar",[132,3590,3591,3592],{},"Add a new domain:\n",[129,3593,3594,3603,3612],{},[132,3595,3596,3599,3600],{},[135,3597,3598],{},"Domain",": ",[116,3601,3602],{},"yourdomain.com",[132,3604,3605,3599,3608,3611],{},[135,3606,3607],{},"Port",[116,3609,3610],{},"80"," (internal container port)",[132,3613,3614,3617],{},[135,3615,3616],{},"HTTPS",": Enabled",[132,3619,3620],{},"Traefik will automatically request a Let's Encrypt certificate",[121,3622,3624],{"id":3623},"for-the-backend-api","For the Backend API",[102,3626,3627],{},"If your Nginx container listens on port 80 internally, you can create a second domain in the same application:",[189,3629,3631],{"className":191,"code":3630,"language":193,"meta":194,"style":194},"# Add this to your docker-compose.yml service labels\nlabels:\n  - \"traefik.enable=true\"\n  - \"traefik.http.routers.backend.rule=Host(`api.yourdomain.com`)\"\n  - \"traefik.http.routers.backend.entrypoints=web,websecure\"\n  - \"traefik.http.routers.backend.tls.certresolver=letsencrypt\"\n",[116,3632,3633,3638,3645,3657,3668,3679],{"__ignoreMap":194},[198,3634,3635],{"class":200,"line":201},[198,3636,3637],{"class":739},"# Add this to your docker-compose.yml service labels\n",[198,3639,3640,3643],{"class":200,"line":212},[198,3641,3642],{"class":204},"labels",[198,3644,209],{"class":208},[198,3646,3647,3650,3652,3655],{"class":200,"line":14},[198,3648,3649],{"class":208},"  -",[198,3651,857],{"class":856},[198,3653,3654],{"class":284},"traefik.enable=true",[198,3656,863],{"class":856},[198,3658,3659,3661,3663,3666],{"class":200,"line":227},[198,3660,3649],{"class":208},[198,3662,857],{"class":856},[198,3664,3665],{"class":284},"traefik.http.routers.backend.rule=Host(`api.yourdomain.com`)",[198,3667,863],{"class":856},[198,3669,3670,3672,3674,3677],{"class":200,"line":235},[198,3671,3649],{"class":208},[198,3673,857],{"class":856},[198,3675,3676],{"class":284},"traefik.http.routers.backend.entrypoints=web,websecure",[198,3678,863],{"class":856},[198,3680,3681,3683,3685,3688],{"class":200,"line":243},[198,3682,3649],{"class":208},[198,3684,857],{"class":856},[198,3686,3687],{"class":284},"traefik.http.routers.backend.tls.certresolver=letsencrypt",[198,3689,863],{"class":856},[102,3691,3692,3693,3696,3697,3699],{},"Or set it through the Dokploy UI by adding a second domain pointing to ",[116,3694,3695],{},"api.yourdomain.com"," with port ",[116,3698,3610],{},".",[98,3701,3703],{"id":3702},"dns-configuration","DNS Configuration",[102,3705,3706],{},"Before Dokploy can issue SSL certificates, your domains must resolve to the Dokploy server.",[121,3708,3710],{"id":3709},"steps","Steps",[3527,3712,3713,3719,3742,3748],{},[132,3714,3715,3718],{},[135,3716,3717],{},"Get your server IP",": Find the public IP address of the server running Dokploy",[132,3720,3721,3724,3725],{},[135,3722,3723],{},"Configure A records"," at your DNS provider:\n",[129,3726,3727,3732,3736],{},[132,3728,3729,3731],{},[116,3730,3602],{}," → your server IP",[132,3733,3734,3731],{},[116,3735,3695],{},[132,3737,3738,3741],{},[116,3739,3740],{},"www.yourdomain.com"," → your server IP (optional)",[132,3743,3744,3747],{},[135,3745,3746],{},"Wait for propagation",": DNS changes typically take 5-30 minutes",[132,3749,3750,3753],{},[135,3751,3752],{},"Verify in Dokploy",": Go to your domain settings and confirm Dokploy detects the domain",[121,3755,3757],{"id":3756},"using-cloudflare","Using Cloudflare",[102,3759,3760],{},"If you use Cloudflare:",[129,3762,3763,3766,3769,3772],{},[132,3764,3765],{},"Set the DNS record to \"DNS only\" (orange cloud off) during initial setup",[132,3767,3768],{},"Let Dokploy validate the domain and issue the certificate",[132,3770,3771],{},"Once working, you can enable the proxy (orange cloud on)",[132,3773,3774],{},"Ensure your Cloudflare SSL\u002FTLS mode is set to \"Full\" or \"Full (Strict)\"",[98,3776,3778],{"id":3777},"enabling-https-with-lets-encrypt","Enabling HTTPS with Let's Encrypt",[102,3780,3781],{},"Dokploy integrates Traefik with Let's Encrypt for automatic SSL certificates.",[121,3783,3785],{"id":3784},"automatic-https","Automatic HTTPS",[102,3787,3788],{},"When you add a domain in Dokploy with HTTPS enabled, Traefik automatically:",[3527,3790,3791,3794,3797,3800],{},[132,3792,3793],{},"Receives the ACME challenge from Let's Encrypt",[132,3795,3796],{},"Validates domain ownership",[132,3798,3799],{},"Issues and renews certificates automatically",[132,3801,3802],{},"Redirects HTTP to HTTPS",[121,3804,3806],{"id":3805},"certificate-storage","Certificate Storage",[102,3808,3809],{},"Certificates are stored in a Docker volume managed by Traefik. You can see them in Dokploy under \"Settings\" → \"SSL Certificates\".",[121,3811,3813],{"id":3812},"manual-certificate-steps","Manual Certificate Steps",[102,3815,3816],{},"If automatic issuance fails:",[3527,3818,3819,3822,3825,3828,3831],{},[132,3820,3821],{},"Ensure port 80 is open and reachable from the internet",[132,3823,3824],{},"Ensure port 443 is open",[132,3826,3827],{},"Check that no other service is using port 80 on your server",[132,3829,3830],{},"Verify DNS is fully propagated",[132,3832,3833],{},"In Dokploy, go to \"Settings\" → \"Traefik\" and check the logs for ACME errors",[98,3835,3837],{"id":3836},"dokploy-setup-tips","Dokploy Setup Tips",[121,3839,3841],{"id":3840},"resource-limits","Resource Limits",[102,3843,3844],{},"Always set CPU and memory limits on your services. Without them, one runaway process can consume the entire server. The compose file above includes modest limits for each service:",[189,3846,3848],{"className":191,"code":3847,"language":193,"meta":194,"style":194},"cpus: 0.50 # Max CPU cores\nmem_limit: 768m # Hard memory limit\nmem_reservation: 256m # Guaranteed memory\n",[116,3849,3850,3863,3876],{"__ignoreMap":194},[198,3851,3852,3855,3857,3860],{"class":200,"line":201},[198,3853,3854],{"class":204},"cpus",[198,3856,281],{"class":208},[198,3858,3859],{"class":1444}," 0.50",[198,3861,3862],{"class":739}," # Max CPU cores\n",[198,3864,3865,3868,3870,3873],{"class":200,"line":212},[198,3866,3867],{"class":204},"mem_limit",[198,3869,281],{"class":208},[198,3871,3872],{"class":284}," 768m",[198,3874,3875],{"class":739}," # Hard memory limit\n",[198,3877,3878,3881,3883,3886],{"class":200,"line":14},[198,3879,3880],{"class":204},"mem_reservation",[198,3882,281],{"class":208},[198,3884,3885],{"class":284}," 256m",[198,3887,3888],{"class":739}," # Guaranteed memory\n",[121,3890,3892],{"id":3891},"health-checks","Health Checks",[102,3894,3895],{},"Every service should have a health check. This lets Traefik and Docker know when a service is ready to receive traffic:",[189,3897,3899],{"className":191,"code":3898,"language":193,"meta":194,"style":194},"healthcheck:\n  test: [\"CMD-SHELL\", 'php -r ''exit(@fsockopen(\"127.0.0.1\", 9000) ? 0 : 1);''']\n  interval: 60s\n  timeout: 5s\n  retries: 3\n  start_period: 30s\n",[116,3900,3901,3908,3939,3948,3957,3966],{"__ignoreMap":194},[198,3902,3903,3906],{"class":200,"line":201},[198,3904,3905],{"class":204},"healthcheck",[198,3907,209],{"class":208},[198,3909,3910,3913,3915,3917,3919,3921,3923,3925,3927,3929,3931,3933,3935,3937],{"class":200,"line":212},[198,3911,3912],{"class":204},"  test",[198,3914,281],{"class":208},[198,3916,913],{"class":208},[198,3918,922],{"class":856},[198,3920,1680],{"class":284},[198,3922,922],{"class":856},[198,3924,1685],{"class":208},[198,3926,1688],{"class":856},[198,3928,1691],{"class":284},[198,3930,1694],{"class":774},[198,3932,1697],{"class":284},[198,3934,1694],{"class":774},[198,3936,1702],{"class":856},[198,3938,1705],{"class":208},[198,3940,3941,3944,3946],{"class":200,"line":14},[198,3942,3943],{"class":204},"  interval",[198,3945,281],{"class":208},[198,3947,1715],{"class":284},[198,3949,3950,3953,3955],{"class":200,"line":227},[198,3951,3952],{"class":204},"  timeout",[198,3954,281],{"class":208},[198,3956,1725],{"class":284},[198,3958,3959,3962,3964],{"class":200,"line":235},[198,3960,3961],{"class":204},"  retries",[198,3963,281],{"class":208},[198,3965,1735],{"class":1444},[198,3967,3968,3971,3973],{"class":200,"line":243},[198,3969,3970],{"class":204},"  start_period",[198,3972,281],{"class":208},[198,3974,1745],{"class":284},[121,3976,3978],{"id":3977},"database-backups","Database Backups",[102,3980,3981],{},"Set up automated database backups using Dokploy's built-in backup feature or a cron job:",[189,3983,3985],{"className":730,"code":3984,"language":732,"meta":194,"style":194},"# Example backup script\n#!\u002Fbin\u002Fbash\nBACKUP_DIR=\"\u002Fbackups\u002Fmysql\"\nDATE=$(date +%Y%m%d_%H%M%S)\ndocker exec mysql-production mysqldump -u root -p$DB_ROOT_PASSWORD $DB_DATABASE > $BACKUP_DIR\u002Fdb_$DATE.sql\n",[116,3986,3987,3992,3997,4012,4031],{"__ignoreMap":194},[198,3988,3989],{"class":200,"line":201},[198,3990,3991],{"class":739},"# Example backup script\n",[198,3993,3994],{"class":200,"line":212},[198,3995,3996],{"class":739},"#!\u002Fbin\u002Fbash\n",[198,3998,3999,4002,4005,4007,4010],{"class":200,"line":14},[198,4000,4001],{"class":918},"BACKUP_DIR",[198,4003,4004],{"class":925},"=",[198,4006,922],{"class":856},[198,4008,4009],{"class":284},"\u002Fbackups\u002Fmysql",[198,4011,863],{"class":856},[198,4013,4014,4017,4019,4022,4025,4028],{"class":200,"line":227},[198,4015,4016],{"class":918},"DATE",[198,4018,4004],{"class":925},[198,4020,4021],{"class":208},"$(",[198,4023,4024],{"class":764},"date",[198,4026,4027],{"class":284}," +%Y%m%d_%H%M%S",[198,4029,4030],{"class":208},")\n",[198,4032,4033,4036,4039,4042,4045,4048,4051,4053,4056,4059,4062,4065,4068,4071],{"class":200,"line":235},[198,4034,4035],{"class":764},"docker",[198,4037,4038],{"class":284}," exec",[198,4040,4041],{"class":284}," mysql-production",[198,4043,4044],{"class":284}," mysqldump",[198,4046,4047],{"class":749}," -u",[198,4049,4050],{"class":284}," root",[198,4052,768],{"class":749},[198,4054,4055],{"class":918},"$DB_ROOT_PASSWORD",[198,4057,4058],{"class":918}," $DB_DATABASE ",[198,4060,4061],{"class":925},">",[198,4063,4064],{"class":918}," $BACKUP_DIR",[198,4066,4067],{"class":284},"\u002Fdb_",[198,4069,4070],{"class":918},"$DATE",[198,4072,4073],{"class":284},".sql\n",[121,4075,4077],{"id":4076},"log-management","Log Management",[102,4079,4080],{},"Docker Compose services generate logs continuously. Set up log rotation to prevent disk exhaustion:",[189,4082,4084],{"className":191,"code":4083,"language":193,"meta":194,"style":194},"services:\n  backend-production:\n    logging:\n      driver: \"json-file\"\n      options:\n        max-size: \"10m\"\n        max-file: \"3\"\n",[116,4085,4086,4092,4098,4105,4118,4125,4139],{"__ignoreMap":194},[198,4087,4088,4090],{"class":200,"line":201},[198,4089,1338],{"class":204},[198,4091,209],{"class":208},[198,4093,4094,4096],{"class":200,"line":212},[198,4095,1474],{"class":204},[198,4097,209],{"class":208},[198,4099,4100,4103],{"class":200,"line":14},[198,4101,4102],{"class":204},"    logging",[198,4104,209],{"class":208},[198,4106,4107,4109,4111,4113,4116],{"class":200,"line":227},[198,4108,278],{"class":204},[198,4110,281],{"class":208},[198,4112,857],{"class":856},[198,4114,4115],{"class":284},"json-file",[198,4117,863],{"class":856},[198,4119,4120,4123],{"class":200,"line":235},[198,4121,4122],{"class":204},"      options",[198,4124,209],{"class":208},[198,4126,4127,4130,4132,4134,4137],{"class":200,"line":243},[198,4128,4129],{"class":204},"        max-size",[198,4131,281],{"class":208},[198,4133,857],{"class":856},[198,4135,4136],{"class":284},"10m",[198,4138,863],{"class":856},[198,4140,4141,4144,4146,4148,4151],{"class":200,"line":251},[198,4142,4143],{"class":204},"        max-file",[198,4145,281],{"class":208},[198,4147,857],{"class":856},[198,4149,4150],{"class":284},"3",[198,4152,863],{"class":856},[98,4154,4156],{"id":4155},"traefik-router-configuration-avoiding-acme-and-port-pitfalls","Traefik Router Configuration: Avoiding ACME and Port Pitfalls",[121,4158,4160],{"id":4159},"the-acme-challenge-port-problem","The ACME Challenge Port Problem",[102,4162,4163,4164,4167],{},"Let's Encrypt's ACME HTTP-01 challenge requires port 80 to be reachable. Traefik needs to receive the ",[116,4165,4166],{},".well-known\u002Facme-challenge\u002F"," requests directly, not route them to your application. If Traefik routes these requests to your app container, certificate issuance fails.",[121,4169,4171],{"id":4170},"solution-traefik-router-labels","Solution: Traefik Router Labels",[102,4173,4174],{},"Add explicit Traefik labels to your Nginx service to ensure ACME challenges are handled correctly:",[189,4176,4178],{"className":191,"code":4177,"language":193,"meta":194,"style":194},"services:\n  nginx-production:\n    image: nginx:1.31-alpine\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.nginx.rule=Host(`yourdomain.com`)\"\n      - \"traefik.http.routers.nginx.entrypoints=web,websecure\"\n      - \"traefik.http.routers.nginx.tls.certresolver=letsencrypt\"\n      - \"traefik.http.services.nginx.loadbalancer.server.port=80\"\n    networks:\n      - production-network\n",[116,4179,4180,4186,4192,4200,4207,4217,4228,4239,4250,4261,4267],{"__ignoreMap":194},[198,4181,4182,4184],{"class":200,"line":201},[198,4183,1338],{"class":204},[198,4185,209],{"class":208},[198,4187,4188,4190],{"class":200,"line":212},[198,4189,1345],{"class":204},[198,4191,209],{"class":208},[198,4193,4194,4196,4198],{"class":200,"line":14},[198,4195,1352],{"class":204},[198,4197,281],{"class":208},[198,4199,1357],{"class":284},[198,4201,4202,4205],{"class":200,"line":227},[198,4203,4204],{"class":204},"    labels",[198,4206,209],{"class":208},[198,4208,4209,4211,4213,4215],{"class":200,"line":235},[198,4210,1369],{"class":208},[198,4212,857],{"class":856},[198,4214,3654],{"class":284},[198,4216,863],{"class":856},[198,4218,4219,4221,4223,4226],{"class":200,"line":243},[198,4220,1369],{"class":208},[198,4222,857],{"class":856},[198,4224,4225],{"class":284},"traefik.http.routers.nginx.rule=Host(`yourdomain.com`)",[198,4227,863],{"class":856},[198,4229,4230,4232,4234,4237],{"class":200,"line":251},[198,4231,1369],{"class":208},[198,4233,857],{"class":856},[198,4235,4236],{"class":284},"traefik.http.routers.nginx.entrypoints=web,websecure",[198,4238,863],{"class":856},[198,4240,4241,4243,4245,4248],{"class":200,"line":259},[198,4242,1369],{"class":208},[198,4244,857],{"class":856},[198,4246,4247],{"class":284},"traefik.http.routers.nginx.tls.certresolver=letsencrypt",[198,4249,863],{"class":856},[198,4251,4252,4254,4256,4259],{"class":200,"line":267},[198,4253,1369],{"class":208},[198,4255,857],{"class":856},[198,4257,4258],{"class":284},"traefik.http.services.nginx.loadbalancer.server.port=80",[198,4260,863],{"class":856},[198,4262,4263,4265],{"class":200,"line":275},[198,4264,1415],{"class":204},[198,4266,209],{"class":208},[198,4268,4269,4271],{"class":200,"line":360},[198,4270,1369],{"class":208},[198,4272,1424],{"class":284},[121,4274,4276],{"id":4275},"adding-a-separate-api-router","Adding a Separate API Router",[102,4278,4279],{},"For your backend API, create a separate Traefik router in the same compose file:",[189,4281,4283],{"className":191,"code":4282,"language":193,"meta":194,"style":194},"services:\n  backend-production:\n    build:\n      context: .\u002Fbackend\n      dockerfile: Dockerfile.production\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.api.rule=Host(`api.yourdomain.com`)\"\n      - \"traefik.http.routers.api.entrypoints=web,websecure\"\n      - \"traefik.http.routers.api.tls.certresolver=letsencrypt\"\n      - \"traefik.http.services.api.loadbalancer.server.port=9000\"\n    networks:\n      - production-network\n",[116,4284,4285,4291,4297,4303,4311,4319,4325,4335,4346,4357,4368,4379,4385],{"__ignoreMap":194},[198,4286,4287,4289],{"class":200,"line":201},[198,4288,1338],{"class":204},[198,4290,209],{"class":208},[198,4292,4293,4295],{"class":200,"line":212},[198,4294,1474],{"class":204},[198,4296,209],{"class":208},[198,4298,4299,4301],{"class":200,"line":14},[198,4300,1481],{"class":204},[198,4302,209],{"class":208},[198,4304,4305,4307,4309],{"class":200,"line":227},[198,4306,1488],{"class":204},[198,4308,281],{"class":208},[198,4310,1493],{"class":284},[198,4312,4313,4315,4317],{"class":200,"line":235},[198,4314,1498],{"class":204},[198,4316,281],{"class":208},[198,4318,1503],{"class":284},[198,4320,4321,4323],{"class":200,"line":243},[198,4322,4204],{"class":204},[198,4324,209],{"class":208},[198,4326,4327,4329,4331,4333],{"class":200,"line":251},[198,4328,1369],{"class":208},[198,4330,857],{"class":856},[198,4332,3654],{"class":284},[198,4334,863],{"class":856},[198,4336,4337,4339,4341,4344],{"class":200,"line":259},[198,4338,1369],{"class":208},[198,4340,857],{"class":856},[198,4342,4343],{"class":284},"traefik.http.routers.api.rule=Host(`api.yourdomain.com`)",[198,4345,863],{"class":856},[198,4347,4348,4350,4352,4355],{"class":200,"line":267},[198,4349,1369],{"class":208},[198,4351,857],{"class":856},[198,4353,4354],{"class":284},"traefik.http.routers.api.entrypoints=web,websecure",[198,4356,863],{"class":856},[198,4358,4359,4361,4363,4366],{"class":200,"line":275},[198,4360,1369],{"class":208},[198,4362,857],{"class":856},[198,4364,4365],{"class":284},"traefik.http.routers.api.tls.certresolver=letsencrypt",[198,4367,863],{"class":856},[198,4369,4370,4372,4374,4377],{"class":200,"line":360},[198,4371,1369],{"class":208},[198,4373,857],{"class":856},[198,4375,4376],{"class":284},"traefik.http.services.api.loadbalancer.server.port=9000",[198,4378,863],{"class":856},[198,4380,4381,4383],{"class":200,"line":365},[198,4382,1415],{"class":204},[198,4384,209],{"class":208},[198,4386,4387,4389],{"class":200,"line":27},[198,4388,1369],{"class":208},[198,4390,1424],{"class":284},[121,4392,4394],{"id":4393},"avoiding-common-port-conflicts","Avoiding Common Port Conflicts",[102,4396,4397,4400],{},[135,4398,4399],{},"Problem",": Multiple services trying to bind to port 80 internally, or Traefik routing to the wrong internal port.",[102,4402,4403,4406],{},[135,4404,4405],{},"Solution",": Use Docker Compose's networking. Services communicate via service names on the internal Docker network. Only the Nginx container needs port 80 internally. Other services (PHP-FPM on 9000, Redis on 6379, MySQL on 3306) use their default ports within the Docker network.",[121,4408,4410],{"id":4409},"traefik-dashboard-access","Traefik Dashboard Access",[102,4412,4413],{},"To access the Traefik dashboard, add a dedicated router with basic auth (if exposed externally):",[189,4415,4417],{"className":191,"code":4416,"language":193,"meta":194,"style":194},"labels:\n  - \"traefik.enable=true\"\n  - \"traefik.http.routers.dashboard.rule=Host(`traefik.yourdomain.com`)\"\n  - \"traefik.http.routers.dashboard.entrypoints=websecure\"\n  - \"traefik.http.routers.dashboard.tls.certresolver=letsencrypt\"\n  - \"traefik.http.routers.dashboard.service=api@internal\"\n  - \"traefik.http.routers.dashboard.middlewares=auth\"\n  - \"traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj\u002F\"\n",[116,4418,4419,4425,4435,4446,4457,4468,4479,4490],{"__ignoreMap":194},[198,4420,4421,4423],{"class":200,"line":201},[198,4422,3642],{"class":204},[198,4424,209],{"class":208},[198,4426,4427,4429,4431,4433],{"class":200,"line":212},[198,4428,3649],{"class":208},[198,4430,857],{"class":856},[198,4432,3654],{"class":284},[198,4434,863],{"class":856},[198,4436,4437,4439,4441,4444],{"class":200,"line":14},[198,4438,3649],{"class":208},[198,4440,857],{"class":856},[198,4442,4443],{"class":284},"traefik.http.routers.dashboard.rule=Host(`traefik.yourdomain.com`)",[198,4445,863],{"class":856},[198,4447,4448,4450,4452,4455],{"class":200,"line":227},[198,4449,3649],{"class":208},[198,4451,857],{"class":856},[198,4453,4454],{"class":284},"traefik.http.routers.dashboard.entrypoints=websecure",[198,4456,863],{"class":856},[198,4458,4459,4461,4463,4466],{"class":200,"line":235},[198,4460,3649],{"class":208},[198,4462,857],{"class":856},[198,4464,4465],{"class":284},"traefik.http.routers.dashboard.tls.certresolver=letsencrypt",[198,4467,863],{"class":856},[198,4469,4470,4472,4474,4477],{"class":200,"line":243},[198,4471,3649],{"class":208},[198,4473,857],{"class":856},[198,4475,4476],{"class":284},"traefik.http.routers.dashboard.service=api@internal",[198,4478,863],{"class":856},[198,4480,4481,4483,4485,4488],{"class":200,"line":251},[198,4482,3649],{"class":208},[198,4484,857],{"class":856},[198,4486,4487],{"class":284},"traefik.http.routers.dashboard.middlewares=auth",[198,4489,863],{"class":856},[198,4491,4492,4494,4496,4499],{"class":200,"line":259},[198,4493,3649],{"class":208},[198,4495,857],{"class":856},[198,4497,4498],{"class":284},"traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj\u002F",[198,4500,863],{"class":856},[102,4502,4503,4504,4507],{},"Or enable the dashboard only on an internal port for local debugging by setting ",[116,4505,4506],{},"--api.insecure=true"," in the Dokploy Traefik configuration (not recommended for production).",[98,4509,4511],{"id":4510},"deployment-workflow-with-dokploy","Deployment Workflow with Dokploy",[121,4513,4515],{"id":4514},"step-by-step-process","Step-by-Step Process",[3527,4517,4518,4524,4530,4536,4554,4569,4586,4592],{},[132,4519,4520,4523],{},[135,4521,4522],{},"Push your code"," to a Git repository (GitHub, GitLab, Gitea)",[132,4525,4526,4529],{},[135,4527,4528],{},"Create a new project"," in Dokploy",[132,4531,4532,4535],{},[135,4533,4534],{},"Connect your repository"," and select the branch",[132,4537,4538,209,4541],{},[135,4539,4540],{},"Upload your Docker Compose file",[129,4542,4543,4546,4551],{},[132,4544,4545],{},"In the project settings, go to \"Compose\"",[132,4547,4548,4549],{},"Paste your ",[116,4550,118],{},[132,4552,4553],{},"Dokploy validates and imports it",[132,4555,4556,209,4559],{},[135,4557,4558],{},"Set environment variables",[129,4560,4561,4566],{},[132,4562,4563,4564],{},"Go to \"Environment\" and add all variables from ",[116,4565,3351],{},[132,4567,4568],{},"Or enable \"Use .env file\" and upload it",[132,4570,4571,209,4574],{},[135,4572,4573],{},"Add domains",[129,4575,4576,4581],{},[132,4577,4578,4579],{},"Frontend: ",[116,4580,3602],{},[132,4582,4583,4584],{},"Backend: ",[116,4585,3695],{},[132,4587,4588,4591],{},[135,4589,4590],{},"Enable HTTPS",": Toggle HTTPS on for each domain",[132,4593,4594,4597],{},[135,4595,4596],{},"Deploy",": Click \"Deploy\" and monitor the logs",[121,4599,4601],{"id":4600},"first-deployment","First Deployment",[102,4603,4604],{},"The first deployment takes the longest because Docker must build all images and pull base images. Subsequent deployments are faster because layers are cached.",[121,4606,4608],{"id":4607},"zero-downtime-deploys","Zero-Downtime Deploys",[102,4610,4611],{},"Dokploy handles rolling updates. When you push new code:",[3527,4613,4614,4617,4620,4623],{},[132,4615,4616],{},"New containers are built",[132,4618,4619],{},"Health checks run against new containers",[132,4621,4622],{},"Traffic shifts from old to new containers",[132,4624,4625],{},"Old containers are stopped",[102,4627,4628],{},"To support this, always include health checks in your services.",[121,4630,4632],{"id":4631},"database-migrations","Database Migrations",[102,4634,288,4635,4638,4639,4641],{},[116,4636,4637],{},"RUN_MIGRATIONS=true"," environment variable controls whether migrations run on container start. Set it only on the ",[116,4640,143],{}," service. The entrypoint script runs migrations before starting PHP-FPM.",[102,4643,4644],{},"For large databases or zero-downtime requirements, run migrations manually:",[189,4646,4648],{"className":730,"code":4647,"language":732,"meta":194,"style":194},"docker compose exec backend-production php artisan migrate --force\n",[116,4649,4650],{"__ignoreMap":194},[198,4651,4652,4654,4657,4659,4662,4664,4666,4668],{"class":200,"line":201},[198,4653,4035],{"class":764},[198,4655,4656],{"class":284}," compose",[198,4658,4038],{"class":284},[198,4660,4661],{"class":284}," backend-production",[198,4663,949],{"class":284},[198,4665,952],{"class":284},[198,4667,986],{"class":284},[198,4669,4670],{"class":749}," --force\n",[98,4672,4674],{"id":4673},"troubleshooting-common-issues","Troubleshooting Common Issues",[121,4676,4678],{"id":4677},"acmelets-encrypt-certificate-failures","ACME\u002FLet's Encrypt Certificate Failures",[102,4680,4681,4684],{},[135,4682,4683],{},"Symptoms",": Domains show \"SSL Pending\" or certificate errors in the browser.",[102,4686,4687,281],{},[135,4688,4689],{},"Checks",[129,4691,4692,4698,4704,4707],{},[132,4693,4694,4695],{},"Ensure port 80 is open: ",[116,4696,4697],{},"sudo ufw allow 80\u002Ftcp",[132,4699,4700,4701],{},"Verify DNS is resolved: ",[116,4702,4703],{},"dig yourdomain.com",[132,4705,4706],{},"Check Traefik logs in Dokploy for ACME errors",[132,4708,4709],{},"Ensure no other reverse proxy (Caddy, Nginx on host) is already using port 80",[121,4711,4713],{"id":4712},"traefik-routing-to-wrong-port","Traefik Routing to Wrong Port",[102,4715,4716,4718],{},[135,4717,4683],{},": Getting 404 from your app when accessing the domain.",[102,4720,4721,4724,4725,4728],{},[135,4722,4723],{},"Fix",": Verify the ",[116,4726,4727],{},"loadbalancer.server.port"," label matches the internal port your service listens on. Nginx uses 80, PHP-FPM uses 9000.",[121,4730,4732],{"id":4731},"permissions-errors-on-volumes","Permissions Errors on Volumes",[102,4734,4735,4737,4738,4741,4742,3699],{},[135,4736,4683],{},": Laravel cannot write to ",[116,4739,4740],{},"storage\u002F"," or ",[116,4743,4744],{},"bootstrap\u002Fcache\u002F",[102,4746,4747,4749,4750,4752],{},[135,4748,4723],{},": The entrypoint script runs ",[116,4751,806],{}," at container start. If using Docker Desktop or certain NAS setups, volumes may start owned by root. The script handles this, but ensure the entrypoint is executable:",[189,4754,4756],{"className":730,"code":4755,"language":732,"meta":194,"style":194},"chmod +x docker\u002Fdocker-entrypoint.sh\n",[116,4757,4758],{"__ignoreMap":194},[198,4759,4760,4763,4766],{"class":200,"line":201},[198,4761,4762],{"class":764},"chmod",[198,4764,4765],{"class":284}," +x",[198,4767,4768],{"class":284}," docker\u002Fdocker-entrypoint.sh\n",[121,4770,4772],{"id":4771},"database-connection-refused","Database Connection Refused",[102,4774,4775,4777],{},[135,4776,4683],{},": Laravel cannot connect to MySQL.",[102,4779,4780,281],{},[135,4781,4689],{},[129,4783,4784,4787,4799,4802],{},[132,4785,4786],{},"MySQL health check is passing",[132,4788,4789,4792,4793,4795,4796,4798],{},[116,4790,4791],{},"DB_HOST"," is set to ",[116,4794,155],{}," (not ",[116,4797,2219],{},")",[132,4800,4801],{},"Environment variables are correctly injected",[132,4803,4804,4805,4798],{},"MySQL has finished initializing (check logs with ",[116,4806,4807],{},"docker compose logs mysql-production",[121,4809,4811],{"id":4810},"frontend-cannot-reach-api","Frontend Cannot Reach API",[102,4813,4814,4816],{},[135,4815,4683],{},": Nuxt app loads but API calls fail in the browser.",[102,4818,4819,281],{},[135,4820,4689],{},[129,4822,4823,4833,4839],{},[132,4824,4825,4828,4829,4832],{},[116,4826,4827],{},"NUXT_PUBLIC_LARAVEL_API_URL"," uses ",[116,4830,4831],{},"https:\u002F\u002F"," and the correct API domain",[132,4834,4835,4836],{},"CORS is configured in Laravel's ",[116,4837,4838],{},"config\u002Fcors.php",[132,4840,4841,4842,4845],{},"The API domain is listed in ",[116,4843,4844],{},"APP_URL"," and Laravel's trusted proxies configuration",[98,4847,4849],{"id":4848},"conclusion","Conclusion",[102,4851,4852],{},"Dokploy simplifies the deployment workflow by bundling Docker Compose, Traefik, and Let's Encrypt into a single interface. The key to a smooth setup is getting the Docker Compose file right from the start: define health checks, set resource limits, use the entrypoint pattern for permissions, and configure Traefik routers correctly.",[102,4854,4855],{},"The most common pitfalls are ACME challenges being routed to application containers, missing health checks causing premature traffic routing, and environment variables not being passed correctly to dependent services. The patterns in this guide address all three.",[102,4857,4858],{},"Start with a staging environment to validate the compose file before deploying to production. Once the stack is stable, Dokploy's Git-based deploys make updates straightforward.",[4860,4861,4862],"style",{},"html pre.shiki code .sHsBP, html code.shiki .sHsBP{--shiki-light:#E53935;--shiki-default:#22863A;--shiki-dark:#85E89D;--shiki-sepia:#F92672}html pre.shiki code .swvn1, html code.shiki .swvn1{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sLACW, html code.shiki .sLACW{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}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 .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html pre.shiki code .ss7Ak, html code.shiki .ss7Ak{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit;--shiki-sepia:#88846F;--shiki-sepia-font-style:inherit}html pre.shiki code .sMLJd, html code.shiki .sMLJd{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#66D9EF}html pre.shiki code .sFhLe, html code.shiki .sFhLe{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .sR7ES, html code.shiki .sR7ES{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sQeA1, html code.shiki .sQeA1{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .sRxSC, html code.shiki .sRxSC{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#F92672;--shiki-sepia-font-style:inherit}html pre.shiki code .siCPE, html code.shiki .siCPE{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .ss--_, html code.shiki .ss--_{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sGXK2, html code.shiki .sGXK2{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .sVMSR, html code.shiki .sVMSR{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#005CC5;--shiki-default-font-style:inherit;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit;--shiki-sepia:#FD971F;--shiki-sepia-font-style:italic}html pre.shiki code .sYThS, html code.shiki .sYThS{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}",{"title":194,"searchDepth":212,"depth":212,"links":4864},[4865,4866,4870,4871,4872,4873,4874,4875,4880,4884,4888,4893,4899,4906,4912,4919],{"id":100,"depth":212,"text":90},{"id":110,"depth":212,"text":111,"children":4867},[4868,4869],{"id":123,"depth":14,"text":124},{"id":183,"depth":14,"text":184},{"id":295,"depth":212,"text":296},{"id":440,"depth":212,"text":441},{"id":720,"depth":212,"text":721},{"id":1099,"depth":212,"text":1100},{"id":1308,"depth":212,"text":1309},{"id":3340,"depth":212,"text":3341,"children":4876},[4877,4878,4879],{"id":3344,"depth":14,"text":3345},{"id":3521,"depth":14,"text":3522},{"id":3552,"depth":14,"text":3553},{"id":3573,"depth":212,"text":3574,"children":4881},[4882,4883],{"id":3580,"depth":14,"text":3581},{"id":3623,"depth":14,"text":3624},{"id":3702,"depth":212,"text":3703,"children":4885},[4886,4887],{"id":3709,"depth":14,"text":3710},{"id":3756,"depth":14,"text":3757},{"id":3777,"depth":212,"text":3778,"children":4889},[4890,4891,4892],{"id":3784,"depth":14,"text":3785},{"id":3805,"depth":14,"text":3806},{"id":3812,"depth":14,"text":3813},{"id":3836,"depth":212,"text":3837,"children":4894},[4895,4896,4897,4898],{"id":3840,"depth":14,"text":3841},{"id":3891,"depth":14,"text":3892},{"id":3977,"depth":14,"text":3978},{"id":4076,"depth":14,"text":4077},{"id":4155,"depth":212,"text":4156,"children":4900},[4901,4902,4903,4904,4905],{"id":4159,"depth":14,"text":4160},{"id":4170,"depth":14,"text":4171},{"id":4275,"depth":14,"text":4276},{"id":4393,"depth":14,"text":4394},{"id":4409,"depth":14,"text":4410},{"id":4510,"depth":212,"text":4511,"children":4907},[4908,4909,4910,4911],{"id":4514,"depth":14,"text":4515},{"id":4600,"depth":14,"text":4601},{"id":4607,"depth":14,"text":4608},{"id":4631,"depth":14,"text":4632},{"id":4673,"depth":212,"text":4674,"children":4913},[4914,4915,4916,4917,4918],{"id":4677,"depth":14,"text":4678},{"id":4712,"depth":14,"text":4713},{"id":4731,"depth":14,"text":4732},{"id":4771,"depth":14,"text":4772},{"id":4810,"depth":14,"text":4811},{"id":4848,"depth":212,"text":4849},"2026-07-03","A complete guide to deploying Laravel backend and Nuxt frontend using Dokploy, covering Docker Compose, domains, environment variables, DNS, HTTPS, and Traefik routing.",null,"md",{"Laravel - Nuxt - Dokploy - Docker - Deployment - DevOps - Production - Traefik - Let's Encrypt":4922,"readingTime":4925},"18 min read","\u002Fblog\u002F43-dokploy-deploy-laravel-nuxt",{"title":90,"description":4921},{"src":4929},{"\u002Fimg\u002Fblog\u002F43-dokploy-deploy-laravel-nuxt\u002Fbanner":4930},{"svg mime":4931},{"svg alt":4932,"width":4933,"height":4934},"Dokploy deployment architecture showing Laravel backend and Nuxt frontend services with Traefik proxy and Let's Encrypt SSL",1200,680,"blog\u002F43-dokploy-deploy-laravel-nuxt","ysQAgriObIUua2VtXXTj5darAkB_xqrZXf1VxtlUQ7E",1783073746720]