This updated guide explains how to implement a scalable, production-ready setup where each user gets a Docker container and unique subdomain like user123.wizbrand.com
, without creating new Apache VirtualHosts for each.
1. Apache Configuration (Dynamic Reverse Proxy)
Apache Modules (Enable Once)
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod rewrite
sudo systemctl restart apache2
Apache Wildcard VirtualHost (Single File)
Edit /opt/lampp/etc/extra/httpd-vhosts.conf
or /etc/apache2/sites-available/000-default.conf
:
<VirtualHost *:80>
ServerName wizbrand.com
ServerAlias *.wizbrand.com
ProxyPreserveHost On
RewriteEngine On
# Extract user ID from subdomain (e.g., 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>
Restart Apache:
sudo systemctl restart apache2
2. Laravel Controller to Spawn Container and Return URL
Create ContainerController.php
:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class ContainerController extends Controller
{
public function createUserContainer(Request $request)
{
$user = Auth::user();
$containerName = 'user-' . $user->id;
$port = 9000 + $user->id;
// Start Docker container mapped to unique port
shell_exec("docker run -d -p {$port}:80 --name {$containerName} my-image");
// Return container's unique URL
return response()->json([
'url' => "http://user{$user->id}.wizbrand.com"
]);
}
}
Add Laravel Route (routes/web.php
)
Route::get('/create-container', [ContainerController::class, 'createUserContainer'])->middleware('auth');
3. Domain Setup (Production)
In your domain provider’s DNS (e.g., GoDaddy, Cloudflare), add:
Type | Name | Value |
---|---|---|
A | * | your_server_ip |
This wildcard allows user123.wizbrand.com
→ your server.
4. Local Testing Setup
Add to /etc/hosts
(on dev machine)
127.0.0.1 user123.wizbrand.com
127.0.0.1 user456.wizbrand.com
Or use:
nip.io
:user123.127.0.0.1.nip.io
sslip.io
:user123.127.0.0.1.sslip.io
5. Docker Image Assumptions
- Exposes port
80
- Named
my-image
or configured dynamically
Example container:
docker run -d -p 9123:80 --name user-123 my-image
6. Test Script (Optional Bash)
#!/bin/bash
USER_ID=$1
PORT=$((9000 + USER_ID))
CONTAINER="user-${USER_ID}"
# Launch container
sudo docker run -d -p ${PORT}:80 --name ${CONTAINER} my-image
# Access URL
echo "Container for user ${USER_ID} available at: http://user${USER_ID}.wizbrand.com"
Usage:
./create-container.sh 123
Summary
Component | Role |
---|---|
Apache (Wildcard) | Dynamic proxy via subdomain-to-port |
Laravel | Container creator & subdomain router |
Docker | User-specific environments |
DNS (Wildcard) | Resolves all subdomains to one IP |
This approach is clean, scalable, reload-free, and requires just one Apache config regardless of user count. Let me know if you’d like to add Let’s Encrypt SSL automation, container auto-cleanup, or database tracking next.
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