Optimizing PHP Apps in Dokku
I run all my webapps in a single Digital Ocean (link with referral) droplet (their fancy word for VPS).
When I started I had some issues: with builds requiring more memory and how to monitor a Dokku server to diagnose instabilities.
At some point my server randomly froze (and as such all my apps became suddenly unavailable). This is what I did to fix it.
The Problem
The problem was that my apps were spawning hundreds of PHP processes per app. I have a few of them, so the total number of processes skyrocketed very easily to thousands.
Many more processes than my humble VPS server could handle.
The root cause? you might ask. The Heroku Buildpack for PHP I use automatically calculates the number of php-fpm
workers based on “available resources”.
By default Dokku makes all resources available to any of your apps. So in my case all of the apps thought the whole RAM was available for them so the algorithm added a bunch of processes for each app.
First attempt
After reading on Resource Management for Dokku the straightforward solution was obvious.
I ran dokku resource:limit --memory 250 <the-app>
followed by a restart with dokku ps:restart <the-app>
for each of my apps.
I could confirm that now most of my apps went down from hundreds of php-fpm
workers to just one. Sweet. Plenty of resources available now!
❓ You might be thinking why the
250
? And is1
worker enough? If that’s the case: keep reading.
Understanding the numbers
Doing the above was enough for a while. In general my apps are very modest. The one with the most traffic is probably this blog, and it’s less than a hundred real visitors (not counting bots) per week.
But being honest I didn’t pay too much attention to how everything works. And, as I said, it was fine.
Fast forward a few months (or a year) and suddenly I see something odd on a new project I was working on:
My new app could potentially require attending two requests at the same time.
It was not working, that was because I had only one php-fpm
worker available. I realized I didn’t check how the actual number was calculated so I did.
This calculation is done by dividing the “memory limit” reported by PHP (each app has their own configuration) and the RAM available. If you want to check the actual code it is here.
My app had the memory limit set to 128MB
. And I had added a limit of 250MB
to the app. So that’s where the 1
worker number is coming.
I only needed two workers. And changing the limit from 250
to 256
(128*2
) with dokku resource:limit --memory 256 <the-app>
did the trick.
After that, and a restart of the app (dokku ps:restart <the-app>
). I could successfully process two simultaneous requests at the same time.
Conclusion
Sometimes the shortest path is enough (and the most pragmatic thing you can do). But take a note of that, and be ready to come back and dig deeper to fill the missing gaps.
Learning is always exciting.
Send a comment