DevOps · Laravel · Docker

Classified ads board: Docker deployment and a drop from 15 seconds to 5

We deployed a commercial Laravel script in an isolated Docker stack, localised it into Russian, rebranded it and worked out why the page took fifteen seconds to open.

RoleDeployment and configuration
StackLaravel 12 · PHP 8.2
DatabaseMariaDB 11 · Redis
Result15 s → 5 to 6 s
The problem

Three problems in one project

A purchased classified ads script had to be brought up locally without fighting the other stacks on the same machine (the database, Redis and admin ports were already taken), speak Russian, and open in a reasonable time. At the start the home page was loading in 13 to 15 seconds.

Diagnosis

The database was not to blame

The first suspicion fell on the database queries. We measured: 75 to 88 queries add up to roughly 0.1 seconds, and not one of them is slow. The database is clean and the network has nothing to do with it. So the time is going before the code even starts running.

The real cause lies in the slow file mount from Windows into the container. With default settings PHP checks the modification date of every project file on every request. On a normal file system that goes unnoticed; across the Docker-for-Windows bridge it turns into thousands of slow calls per visit. It was made worse by the compiled file cache limit sitting at 10,000 against 21,359 PHP files in the project: the cache overflowed and recompiled the same things over and over.

Before
15 s
After
5 s
Light pages
~4 s
Home page, local environment; measurements after the changes came out at 5 to 6 seconds. The key change is switching off the file date checks and raising the cache limit above the real number of project files.
Solution

What was done

An isolated Docker stack

Its own project name, network, volumes and ports. The stack does not conflict with the ones already running on the machine. It ships with PHP-FPM, Nginx, MariaDB, Redis and a mail catcher, so that letters do not escape from a test environment.

Installation from the console rather than the wizard

The browser install wizard kept tripping over CSRF, sessions and outbound calls. We went through it deterministically with console commands: migrations, filling the reference tables, the country and 2,658 cities, the super admin, the installation marker file. Repeatable and without surprises.

Russian by default

The language is switched in the database, in the config and for the admin. Browser auto-detection is switched off separately, otherwise an English header from the browser would override the Russian default. There is a trap here too: the default language is cached, and without clearing the cache the change is not visible.

Rebranding of exactly the visible part

We replaced what the user sees: the name, the footer, the service pages. The script's functional identifier was deliberately left alone: the code compares versions by it, and renaming it would break that logic. Checked: no mentions of the original brand are left on public pages.

Cache and sessions in Redis

Switching over exposed a trap: the session config defaulted to the database and brought the application down with a 500. It is fixed by naming the connection explicitly, one of those things that costs half an hour if you know and half a day if you do not.

Result

What came out of it

×3faster home page
2 658cities in the reference table
0conflicts with other stacks
18languages available, Russian by default

We also recorded the route to going below one second: moving the code into a Linux file system instead of mounting it from Windows. That removes the root cause rather than the symptom, but it requires rebuilding the working environment, so the decision was left to the client as a deliberate choice.

Stack

Technologies

Laravel 12PHP 8.2PHP-FPM NginxMariaDB 11Redis Docker Composeopcacheartisan Mailpit
The platform name, the domain and the credentials are not published at the client's request. The measurements come from a local environment; on a production server without a Windows mount the numbers will be better.