CYTam-5228 avatar image
2 Votes"
CYTam-5228 asked YauhenZenkoSolvy-8085 published

Resolving slowiness of built-in Apache+PHP contanier due to files served from network storage, and first time responsiveness of custom Docker image

I have an application which I'd like to move to Azure. This is a standard web application written in PHP, developed using the Symfony framework. Since I am new to Azure, I looked for the most straightforward solution first. App Service (Linux) + Web App for PHP seems to be a good fit for this kind of application, so I followed the quick start/tutorials and created an App Service (in Linux) and a PHP Web App and deployed the code to the cloud via Git. The deployment is smooth and the application runs fine, but there is one catch - the response time is too slow. It takes around 6 to 10 seconds for the web server to complete a request, sometimes even worse. This is simply unacceptable. It is still slow as hell after I switched the service plan to the P1V2 tier, so the problem should be elsewhere.

After some investigations, I concluded that this is probably caused by the fact that the app service is serving my web application code (i.e. /home/site/wwwroot) through a network storage (cifs?). So I first tried configuring Opcache to use a more aggressive approach, and the response time drops to ~2-4 seconds. Not bad but still far from satisfactory. Then as an experiment I copied the app code to the local disk, tweaked Apache to serve files from it. Now the response time drops to below 400ms. So my speculation seems true. The problem of course is that "data outside '/home' is not persisted", so this is not a viable deployment flow, and I probably need to look elsewhere.

Then I went further and tried deploying the application using a Docker image (via Azure Container Registry) to avoid the CIFS stuff. It also works fine, and the response time is the same as serving files from a local disk, but there is also a catch - the app is responsive except for the client who is the first to visit the website. As stated in the tutorial ( "The first time you access the app, it may take some time because App Service needs to pull the entire image". The docker image of my app is around 1.5GB, and in my experience the first user will have to wait for about 5 minutes until the request timeout (and the user needs to refresh the page 1 or 2 times to see a working page). No matter how I strive for trimming down the size of the docker image, this is still a bad user experience.

And hence my questions:

(1) Is there any way to improve the performance of the PHP web app instance? The cause is probably due to files are served via network attached storage. The performance is worse for modern PHP applications where a project contains a significant number of files (Opcache
preloading in PHP 7.4 isn't seem stable enough for me, also Azure currently offers up to PHP 7.3 only). One possible solution is to run a script to copy the files to the local disk whenever a container is started or created. But this doesn't seem possible? Or is there a better way?

(2) For custom Docker image deployment, is it possible to configure App Service to pull the image before serving client requests? This may not be as problemetic as the previous issue as this long-wait-until-timeout issue only happens when the app service is restarted/scaled up/scaled down (not sure if this obsevation is correct), but I still feel like this is something that needs to be tackled, and I do feel strange that the tutorial doesn't see it as something that needs to be eventually handled.

I am unable to find a post facing issues similar to that I have, so I try to ask here.

Thank you!

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hello @CYTam-5228
Did you solve this problem and how?
We are experience totally the same issues while trying to run Symfony app on Azure.

0 Votes 0 ·

1 Answer

ajkuma-MSFT avatar image
0 Votes"
ajkuma-MSFT answered ajkuma-MSFT commented

Welcome to Microsoft Q&A! This is good question, thanks for posting here with a detailed description of the problem. It’s highly appreciated.

Apologies for the delayed response here. I completely understand the frustration with the WebApp performance issue.
Kindly take a look at the suggestions mentioned below, that we could try, if those doesn’t help I wish to engage with you offline for a much closer look and provide a quick and specialized assistance, please send an email with subject line “Attn:Ajay” to AzCommunity[at]Microsoft[dot]com referencing this thread, Azure subscription ID, I will follow-up with you.

Apologies for the long answer – I’m sharing all the possible options that we could try to benefit the community.

Having mentioned that, there could several cause for slow performance, in the interim, you may try these options to isolate the issue
(I understand you have tried several things already, if you have haven’t done any of the following, requesting you to review and try:

  1. Firstly for a quick review, kindly check to see if App Service diagnostics provides any pointers, it reduces the chance of trial and error and expedites problem resolution by recommending potential solutions.
    To access App Service diagnostics, navigate to your App Service app in the Azure portal. In the left navigation, click on Diagnose and solve problems – Checkout the tile for “Diagnostic Tools” and “Availability and Performance”.

  2. If you haven’t done this already so, you may enable Always On to keep the app loaded all the time. From the Azure Portal> Navigate to your WebApp > Under Settings blade > Go to “Configuration” > Enable “Always on” feature under ‘Platform settings’.

  3. You can configure the amount of time the platform will wait before it restarts your container. To do so, set the WEBSITES_CONTAINER_START_TIME_LIMIT app setting to the value you want. The default value is 230 seconds, and the maximum value is 1800 seconds.

To do this, from the Azure Portal> Navigate to your WebApp > Under Settings blade > Go to “Configuration” >
Add the above app setting with ‘Name’ with 1800 as ‘Value’ .

· 6
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

4.To highlight further on container start-up process - When your site starts, we run your Docker image and create a Docker container. Your app runs inside of that container, and the file system contains only what is in the Docker image. If your Docker image doesn't install a particular component, it won't be there when your container starts. You can take charge of this by building your own custom image that will install this without manual intervention.

Apps in the same App Service Plan (ASP) all share the same compute resources. If it’s resource intensive app, you can have the app in a separate ASP.

Yes, you can provide an optional startup command that will be run as part of container startup. From “Startup Command” under WebApp “**General setting**s”.

0 Votes 0 ·

5.You can also always inspect the log files from the browser at https://<app-name> (Kudu) and leverage App Service diagnostics to fetch more details on the issue.

6.You do have visibility (via Kudu) on the files persisted on the Azure File share when that App Setting is set to True.

If WEBSITES_ENABLE_APP_SERVICE_STORAGE setting is unspecified or set to true, the /home/ directory will be shared across scale instances, and files written will persist across restarts. Explicitly setting WEBSITES_ENABLE_APP_SERVICE_STORAGE to false will disable the mount.

0 Votes 0 ·

7.Just to highlight further, the first time you use a custom Docker image, we will do a "docker pull" and pull all layers. These layers are stored on disk just as if you were using Docker on-premises. When we do a "docker pull" after a site restart, we will only pull layers that have changed. If there have been no changes, we will simply use existing layers on the local disk.
To isolate the issue, generally you may try and run the image locally or swap/production.
You must choose the right parent image for the framework you want.
Yes, it takes some time to download a parent image during app start-up.
However, you can reduce start-up time by using one of the following parent images (in your case, you have used the parent image) that are already cached in Azure App Service

0 Votes 0 ·
Show more comments