First of all please note that I’m not a skilled PHP programmer, even less a Laravel expert. Which is the reason why I’m turning to the community in hope that someone with a clearer understanding of the Laravel mechanics could help me, or at least let me know whether I’m heading in a realistic direction or completely going off-rails.
Here is a description of the situation:
I have a running, Laravel based, web app that is currently running smoothly in a Docker container.
The app itself was conceived (by someone else) for a single user usage, storing user specific data to a mysql database, which itself is running in another Docker container.
As far as my understanding of the code goes, the database that is used by the app is defined as an environment variable specified in the
docker-compose.yml file that is used to spawn the app container:
services: ... app: ... environment: ... - DB_DATABASE1=userdb ...
The application specific configuration file
config/appname.php defines which database to use as follow:
return [ ... 'db' => [ ... 'default' => env('DB_CONNECTION', 'mysql'), ...
This, in turn, refers to the ‘mysql’ value defined in
'connections' => [ ... 'mysql' => [ ... 'database' => env('DB_DATABASE1', 'forge'), ...
So my impression is that (simply) changing the value of
DB_DATABASE1 for each different user would allow the same app code to access different user’s data, am I correct here or am I already missing something?
In case this is correct, one possible way to go would be to deploy a separate Docker container for each client, specifying another
DB_DATABASE1 environment value in each one. Although this seems highly inefficient since the whole application code would get duplicated for each client and many containers would need to be spawned even when no client is accessing the app.
Also upgrading the app code would become tedious since each individual container would need to be upgraded.
Thus it seems that finding a way to dynamically define the
DB_DATABASE1 parameter, based on the client accessing a single app container would be a better solution, but is this possible?
The infrastructure used to host the containers has a Traefik (2) reverse-proxy that can route clients’ requests to the adequate Docker container(s). Once again it would be relatively simple to have it route all traffic for, let’s say,
client1.myapp.com to a Docker container configured with its
DB_DATABASE1 environment variable set to
client1 and so on… but, once again, this would be far from efficient.
What the Traefik reverse-proxy could also do is route all traffic to a single app container but, on the way, adding a custom HTTP Header containing a value identifying the client (based on the requested URL as above). Of course this would require some Laravel (PHP) logic, probably in
config/appname.php (or rather
config/database.php?) , to extract this value and, on the fly, set the appropriate
DB_DATABASE1 value accordingly.
I wonder if this would be possible since I guess that for this to happen some Laravel libraries would need to be loaded and some kind of
HTTP_Request object should be made available. As I see that all
config/___.php files are basically only returning PHP arrays, and the only function I see used there being
env(), I doubt that extracting the value of an HTTP Header could be carried out at this level. Am I right?
Since the Laravel application code is quite complex, and developed by someone else, I would like to find a way to implement what was described above while touching as few files as possible, and certainly not touching the core code of the app, could some generous heart tell me whether this is conceivable?
And if yes would it be possible to give me an example on how to implement this?
I sincerely hope that all this is clear enough to be understood.
Any hint on the subject would be greatly appreciated.
Thank you very much.
Source: Docker Questions