projectkudu / kudu

Kudu is the engine behind git/hg deployments, WebJobs, and various other features in Azure Web Sites. It can also run outside of Azure.
Apache License 2.0
3.12k stars 655 forks source link

[Linux] Access to php_pdo_pgsql on WebApp but not available to Kudu script #3112

Closed tao closed 4 months ago

tao commented 4 years ago

I am trying to deploy a Laravel 6 application to Linux on Azure with Postgres, and using a Kudu script to run composer install and set up the app. During the Kudu script I want to run php artisan migrate and migrate the new database changes on each new deployment.

The Laravel app works perfectly on the Azure WebApp, so this is specifically a Kudu issue.

If you SSH into the server and run the command php artisan migrate it works fine, but the Kudu script doesn't seem to run on the same PHP settings so it's seems impossible to get it working.

The Web app/SSH reads PHP configs from Configuration File (php.ini) Path: /usr/local/etc/php

While Kudu seems to read the configs from: Configuration File (php.ini) Path: /opt/php/7.3.11/ini

When Kudu runs from opt/php/ it doesn’t have access to the Postgres database driver php_pdo_pgsql which is causing our issue. I have also tried a standard WebApp and a Docker image but they both have the same problem.

I have also tried installing the Postgres database driver php-pgsql manually during the Kudu script in order to activate this but installing packages seems locked down on Kudu. I have tried:

$ sudo apt-get install php-pgsql
$ apt-get install php-pgsql
$ pecl install php-pgsql
$ docker-php-ext-install pgsql

The Azure documentation also has articles on setting up custom php ini configs using .user.ini files or settings.ini files, or even changing PHP_INI_SCAN_DIR but these again seem to work only on the Web App but don’t seem to affect the Kudu environment.

I have created these .user.ini and settings files like this:

# Enable Postgres database
extension=php_pdo_pgsql
extension=php_pgsql

After trying this, it does detect the changes but looks in the wrong directory again for these files:

PHP Warning:  PHP Startup: Unable to load dynamic library 'php_pdo_pgsql' (tried: /opt/php/7.3.11/lib/php/extensions/no-debug-non-zts-20180731/php_pdo_pgsql (/opt/php/7.3.11/lib/php/extensions/no-debug-non-zts-20180731/php_pdo_pgsql: cannot open shared object file: No such file or directory), /opt/php/7.3.11/lib/php/extensions/no-debug-non-zts-20180731/php_pdo_pgsql.so (/opt/php/7.3.11/lib/php/extensions/no-debug-non-zts-20180731/php_pdo_pgsql.so: cannot open shared object file: No such file or directory)) in Unknown on line 0

PHP Warning:  PHP Startup: Unable to load dynamic library 'php_pgsql' (tried: /opt/php/7.3.11/lib/php/extensions/no-debug-non-zts-20180731/php_pgsql (/opt/php/7.3.11/lib/php/extensions/no-debug-non-zts-20180731/php_pgsql: cannot open shared object file: No such file or directory), /opt/php/7.3.11/lib/php/extensions/no-debug-non-zts-20180731/php_pgsql.so (/opt/php/7.3.11/lib/php/extensions/no-debug-non-zts-20180731/php_pgsql.so: cannot open shared object file: No such file or directory)) in Unknown on line 0

If you look at the PHP ini configs enabled during the Kudu script with php -m it shows these:

PHP 7.3.11 (cli) (built: Nov  5 2019 13:59:44) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.11, Copyright (c) 1998-2018 Zend Technologies
Configuration File (php.ini) Path: /opt/php/7.3.11/ini
Loaded Configuration File:         /opt/php/7.3.11/ini/php.ini
Scan for additional .ini files in: /opt/php/7.3.11/ini/conf.d
Additional .ini files parsed:      /opt/php/7.3.11/ini/conf.d/docker-php-ext-sodium.ini

While the WebApp itself has access to all the correct ini settings:

Configuration File (php.ini) Path: /usr/local/etc/php
Loaded Configuration File:         (none)
Scan for additional .ini files in: /usr/local/etc/php/conf.d/
Additional .ini files parsed:      /usr/local/etc/php/conf.d/20-sqlsrv.ini,
/usr/local/etc/php/conf.d/30-pdo_sqlsrv.ini,
/usr/local/etc/php/conf.d/docker-php-ext-bcmath.ini,
/usr/local/etc/php/conf.d/docker-php-ext-calendar.ini,
/usr/local/etc/php/conf.d/docker-php-ext-exif.ini,
/usr/local/etc/php/conf.d/docker-php-ext-gd.ini,
/usr/local/etc/php/conf.d/docker-php-ext-gettext.ini,
/usr/local/etc/php/conf.d/docker-php-ext-gmp.ini,
/usr/local/etc/php/conf.d/docker-php-ext-imagick.ini,
/usr/local/etc/php/conf.d/docker-php-ext-imap.ini,
/usr/local/etc/php/conf.d/docker-php-ext-intl.ini,
/usr/local/etc/php/conf.d/docker-php-ext-ldap.ini,
/usr/local/etc/php/conf.d/docker-php-ext-mysqli.ini,
/usr/local/etc/php/conf.d/docker-php-ext-odbc.ini,
/usr/local/etc/php/conf.d/docker-php-ext-opcache.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pcntl.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pdo_odbc.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pdo_pgsql.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pgsql.ini,
/usr/local/etc/php/conf.d/docker-php-ext-shmop.ini,
/usr/local/etc/php/conf.d/docker-php-ext-soap.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sockets.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sodium.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sysvmsg.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sysvsem.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sysvshm.ini,
/usr/local/etc/php/conf.d/docker-php-ext-tidy.ini,
/usr/local/etc/php/conf.d/docker-php-ext-wddx.ini,
/usr/local/etc/php/conf.d/docker-php-ext-xmlrpc.ini,
/usr/local/etc/php/conf.d/docker-php-ext-xsl.ini,
/usr/local/etc/php/conf.d/docker-php-ext-zip.ini,
/usr/local/etc/php/conf.d/opcache-recommended.ini,
/usr/local/etc/php/conf.d/php.ini

The docker-php-ext-pdo_pgsql.ini and docker-php-ext-pgsql.ini modules do exist on the server, so I've also tried setting PHP_INI_SCAN_DIR in the app config to /usr/local/etc/php/conf.d/ but that doesn't change the ini settings on the Kudu script either.

I have even tried a post deployment script using POST_DEPLOYMENT_ACTION on the app configuration, which runs the script /home/site/deployments/tools/post-deploy.sh:

echo Post Deployment Script
php --ini
php -m
php artisan migrate --force -vvv
echo Success

That script runs afterwards and scans for additional ini files but still fails with the same errors:

Post Deployment Script
Configuration File (php.ini) Path: /opt/php/7.3.11/ini
Loaded Configuration File:         /opt/php/7.3.11/ini/php.ini
Scan for additional .ini files in: /usr/local/etc/php/conf.d/
Additional .ini files parsed:      (none)

The actual error that occurs each time is:

In Connection.php line 669:                                                                              
[Illuminate\Database\QueryException]                                         
could not find driver (SQL: select * from information_schema.tables where table_schema = public and table_name = migrations and table_type = 'BASE TABLE')                                                                         
Exception trace:
at /home/site/wwwroot/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669

...

In Connector.php line 70:
[PDOException] could not find driver  
Exception trace: at /home/site/wwwroot/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70
PDO->__construct() at /home/site/wwwroot/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70

I have an example Laravel 6 repository available here: tao/kudu-laravel6

Is there something I'm missing in how this works? How could we get access to the Postgres database driver during the Kudu script or if that's not possible how else can I run my database migrations for Laravel?

suwatch commented 4 years ago

@sanchitmehta please advise.

sanchitmehta commented 4 years ago

@kichalla @arroyc Could you please help us with this ?

kichalla commented 4 years ago

We currently do not install database drivers in build image and only do in runtime images.

kichalla commented 4 years ago

@suwatch @sanchitmehta Could you create a new label Oryx and tag issues which you see are related to my team.

tao commented 4 years ago

Could you suggest alternative solutions to run a database migration for a Laravel app hosted on Azure?

kichalla commented 4 years ago

Typically I have seen articles talking about running migration from your development machine against the prod database. https://docs.microsoft.com/en-us/azure/app-service/containers/tutorial-php-mysql-app

tao commented 4 years ago

I don't believe that's good practice because it's very likely that I or someone else on the team will forget, and I would rather keep the database credentials on Azure.

garimpeirodouniverso commented 4 years ago

@kichalla I am facing the same issue with SQL Server. My "php -m" on the Web App shows "sqlsrv" and "pdo_sqlsrv" as PHP modules, although "php -m" on the Kudu side does not.

As @tao commented, it does not sound like a good practice to leave it to the dev to migrate Production databaseS (in our case, we have several Production resource groups, hence several Production databases to be migrated).

It is only natural to think that the deployment script should be able to execute the migration as part of the CI/CD pipeline. IDK how people are deploying laravel applications without performing "migrate" as part of the process to be honest...

kichalla commented 4 years ago

Thanks @tao and @garimpeirodouniverso ...we will look into this and get back to you

MartinGF commented 4 years ago

¿Any news with this issue?

jvano commented 4 months ago

Hi

If the problem persists and is related to running it on Azure App Service, please open a support incident in Azure: https://learn.microsoft.com/en-us/azure/azure-portal/supportability/how-to-create-azure-support-request

This way we can better track and assist you on this case

Thanks,

Joaquin Vano Azure App Service