This tutorial guides you through setting up a multi-user container-based architecture using:
- Laravel (running on Apache via XAMPP in Ubuntu VM)
- Docker (to spawn a container for each user)
- Apache (as a reverse proxy)
- Domain:
wizbrand.com
Weβll configure Apache to dynamically proxy subdomains like user123.wizbrand.com
to each userβs container (e.g., port 9123
).
1. Environment Setup
1.1. Prerequisites
- Ubuntu VM
- XAMPP (with Apache)
- Docker installed
- Laravel app running in XAMPP (
htdocs/myapp
)
2. Laravel: Container Creation Endpoint
Create a route and controller in Laravel to spawn a Docker container and generate a proxy URL.
Example Laravel Controller
public function createUserContainer()
{
$user = auth()->user();
$containerName = 'user-' . $user->id;
$port = 9000 + $user->id;
// Start Docker container with mapped port
shell_exec("docker run -d -p $port:80 --name $containerName my-image");
// Create Apache virtualhost config
$vhost = "
<VirtualHost *:80>
ServerName $containerName.wizbrand.com
ProxyPreserveHost On
ProxyPass / http://localhost:$port/
ProxyPassReverse / http://localhost:$port/
</VirtualHost>
";
file_put_contents("/opt/lampp/etc/extra/vhosts/$containerName.conf", $vhost);
// Append hosts file (for local dev only)
file_put_contents("/etc/hosts", "\n127.0.0.1 $containerName.wizbrand.com", FILE_APPEND);
// Reload Apache
shell_exec("sudo /opt/lampp/lampp reloadapache");
return response()->json(['url' => "http://$containerName.wizbrand.com"]);
}
Replace
my-image
with your actual Docker image name
3. Apache Configuration
3.1 Enable Apache Modules
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo systemctl restart apache2 # or /opt/lampp/lampp restart
3.2 Main Apache Config File
Ensure it includes:
# In httpd.conf or extra/httpd-vhosts.conf
IncludeOptional etc/extra/vhosts/*.conf
Create folder:
sudo mkdir /opt/lampp/etc/extra/vhosts
4. Domain & Local Setup
4.1 Production DNS Setup
- Add one wildcard DNS record:
*.wizbrand.com β your_server_ip
4.2 Local Development Setup
- Edit
/etc/hosts
on host system (your laptop):
127.0.0.1 user-123.wizbrand.com
127.0.0.1 user-456.wizbrand.com
5. Laravel Route (routes/web.php)
Route::get('/create-container', [ContainerController::class, 'createUserContainer'])->middleware('auth');
6. Workflow Summary
- User logs into Laravel app
- Clicks button to create container
- Laravel creates Docker container on a unique port
- Laravel generates Apache virtualhost config
- Apache proxies
userXYZ.wizbrand.com
β userβs container - User accesses the unique subdomain URL
Optional Enhancements
- Use Laravel queue to create containers async
- Setup SSL (Letβs Encrypt + wildcard)
- Add container expiry/auto-deletion scheduler
- Store container info in DB
Caveats
- Apache config reload is needed for each new subdomain (downtime may be noticeable)
- Traefik/Nginx are more scalable but not used here as per your request
- Ensure ports are not reused across containers
Tools Used
- Laravel (PHP Backend)
- Docker (User environment containers)
- Apache (Reverse proxy)
- XAMPP (AMP stack)
Conclusion
This setup allows you to offer per-user container environments with unique URLs, using Apache as a reverse proxy without requiring manual DNS records for each user. Itβs great for development, testing, or isolated workspaces.
Youβre absolutely right β the solution I gave does involve creating a new Apache VirtualHost config per container, which works but is not scalable for hundreds of users.
Since youβre looking for a better, scalable approach using Apache only (no Traefik or Nginx), hereβs the optimized solution youβre likely aiming for:
Improved Approach: One Wildcard VirtualHost + Rewrite Rules
Instead of generating a new VirtualHost
file for every container/user, weβll use one single wildcard-based VirtualHost that dynamically reverse-proxies based on the subdomain.
Concept
Assume:
- Each user gets a subdomain like
user123.wizbrand.com
- Each container listens on a unique port like
91XXX
(e.g., 9123 for user 123)
Weβll use mod_rewrite
and mod_proxy
to extract the subdomain and map it to the corresponding port dynamically.
Step-by-Step: Dynamic Apache Reverse Proxy Using Subdomains
1. Enable Required Apache Modules
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod rewrite
sudo systemctl restart apache2
2. Single Wildcard VirtualHost Configuration
Edit your Apache config (XAMPP: /opt/lampp/etc/extra/httpd-vhosts.conf
or Ubuntu default: /etc/apache2/sites-available/000-default.conf
):
<VirtualHost *:80>
ServerName wizbrand.com
ServerAlias *.wizbrand.com
ProxyPreserveHost On
RewriteEngine On
# Extract username from subdomain (user123)
RewriteCond %{HTTP_HOST} ^user([0-9]+)\.wizbrand\.com$ [NC]
RewriteRule ^/(.*)$ http://127.0.0.1:9%1/\ [P,L]
ProxyPassReverse / http://127.0.0.1/
</VirtualHost>
This does the magic:
- Matches
user123.wizbrand.com
- Extracts
123
from the subdomain - Proxies to
localhost:9123
3. Docker Container Port Strategy
Each container should expose port 80
to a host port like 9123
.
Example command from Laravel:
$containerName = "user-{$user->id}";
$hostPort = 9000 + $user->id;
shell_exec("docker run -d -p {$hostPort}:80 --name {$containerName} my-image");
4. DNS Setup (Production)
In your domain DNS provider (for wizbrand.com
), create:
Type | Name | Value |
---|---|---|
A | * | your_server_ip |
This allows
*.wizbrand.com
to point to your server automatically.
5. Local Development (/etc/hosts
)
For testing on your local machine or VM:
127.0.0.1 user123.wizbrand.com
127.0.0.1 user456.wizbrand.com
Or use dynamic wildcard resolution services like:
nip.io
:user123.127.0.0.1.nip.io
sslip.io
:user123.127.0.0.1.sslip.io
Summary: Why This is Better
Feature | Previous Method | Improved Method |
---|---|---|
VHost per user | Yes | No |
Apache reload for each user | Yes | No |
Scalable for 100+ users | Not practical | Fully scalable |
Performance-friendly | No | Yes |
Maintains Apache-only setup | Yes | Yes |
Laravel Integration Recap
$port = 9000 + $user->id;
shell_exec("docker run -d -p {$port}:80 --name user-{$user->id} my-image");
return response()->json([
'url' => "http://user{$user->id}.wizbrand.com"
]);
Iβm a DevOps/SRE/DevSecOps/Cloud Expert passionate about sharing knowledge and experiences. I am working at Cotocus. I blog tech insights at DevOps School, travel stories at Holiday Landmark, stock market tips at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at I reviewed , and SEO strategies at Wizbrand.
Please find my social handles as below;
Rajesh Kumar Personal Website
Rajesh Kumar at YOUTUBE
Rajesh Kumar at INSTAGRAM
Rajesh Kumar at X
Rajesh Kumar at FACEBOOK
Rajesh Kumar at LINKEDIN
Rajesh Kumar at PINTEREST
Rajesh Kumar at QUORA
Rajesh Kumar at WIZBRAND