{"id":49074,"date":"2025-04-11T13:34:39","date_gmt":"2025-04-11T13:34:39","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=49074"},"modified":"2025-04-11T13:36:37","modified_gmt":"2025-04-11T13:36:37","slug":"step-by-step-tutorial-dynamic-container-url-routing-using-apache-xampp-for-multi-user-laravel-app","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/step-by-step-tutorial-dynamic-container-url-routing-using-apache-xampp-for-multi-user-laravel-app\/","title":{"rendered":"Step-by-Step Tutorial: Dynamic Container URL Routing using Apache (XAMPP) for Multi-User Laravel App"},"content":{"rendered":"\n<p>This tutorial guides you through setting up a <strong>multi-user container-based architecture<\/strong> using:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Laravel (running on Apache via XAMPP in Ubuntu VM)<\/li>\n\n\n\n<li>Docker (to spawn a container for each user)<\/li>\n\n\n\n<li>Apache (as a reverse proxy)<\/li>\n\n\n\n<li>Domain: <code>wizbrand.com<\/code><\/li>\n<\/ul>\n\n\n\n<p>We&#8217;ll configure Apache to dynamically proxy subdomains like <code>user123.wizbrand.com<\/code> to each user&#8217;s container (e.g., port <code>9123<\/code>).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83c\udfe0 1. Environment Setup<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1.1. Prerequisites<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ubuntu VM<\/li>\n\n\n\n<li>XAMPP (with Apache)<\/li>\n\n\n\n<li>Docker installed<\/li>\n\n\n\n<li>Laravel app running in XAMPP (<code>htdocs\/myapp<\/code>)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd27 2. Laravel: Container Creation Endpoint<\/h2>\n\n\n\n<p>Create a route and controller in Laravel to spawn a Docker container and generate a proxy URL.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Example Laravel Controller<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">createUserContainer<\/span><span class=\"hljs-params\">()<\/span>\n<\/span>{\n    $user = auth()-&gt;user();\n    $containerName = <span class=\"hljs-string\">'user-'<\/span> . $user-&gt;id;\n    $port = <span class=\"hljs-number\">9000<\/span> + $user-&gt;id;\n\n    <span class=\"hljs-comment\">\/\/ Start Docker container with mapped port<\/span>\n    shell_exec(<span class=\"hljs-string\">\"docker run -d -p $port:80 --name $containerName my-image\"<\/span>);\n\n    <span class=\"hljs-comment\">\/\/ Create Apache virtualhost config<\/span>\n    $vhost = <span class=\"hljs-string\">\"\n&lt;VirtualHost *:80&gt;\n    ServerName $containerName.wizbrand.com\n    ProxyPreserveHost On\n    ProxyPass \/ http:\/\/localhost:$port\/\n    ProxyPassReverse \/ http:\/\/localhost:$port\/\n&lt;\/VirtualHost&gt;\n    \"<\/span>;\n\n    file_put_contents(<span class=\"hljs-string\">\"\/opt\/lampp\/etc\/extra\/vhosts\/$containerName.conf\"<\/span>, $vhost);\n    \n    <span class=\"hljs-comment\">\/\/ Append hosts file (for local dev only)<\/span>\n    file_put_contents(<span class=\"hljs-string\">\"\/etc\/hosts\"<\/span>, <span class=\"hljs-string\">\"\\n127.0.0.1 $containerName.wizbrand.com\"<\/span>, FILE_APPEND);\n\n    <span class=\"hljs-comment\">\/\/ Reload Apache<\/span>\n    shell_exec(<span class=\"hljs-string\">\"sudo \/opt\/lampp\/lampp reloadapache\"<\/span>);\n\n    <span class=\"hljs-keyword\">return<\/span> response()-&gt;json(&#91;<span class=\"hljs-string\">'url'<\/span> =&gt; <span class=\"hljs-string\">\"http:\/\/$containerName.wizbrand.com\"<\/span>]);\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Replace <code>my-image<\/code> with your actual Docker image name<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83c\udf10 3. Apache Configuration<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">3.1 Enable Apache Modules<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">sudo a2enmod proxy\nsudo a2enmod proxy_http\nsudo systemctl restart apache2  <span class=\"hljs-comment\"># or \/opt\/lampp\/lampp restart<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">3.2 Main Apache Config File<\/h3>\n\n\n\n<p>Ensure it includes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\"># In httpd.conf or extra\/httpd-vhosts.conf<\/span>\nIncludeOptional etc\/extra\/vhosts<span class=\"hljs-comment\">\/*.conf\n<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Create folder:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">sudo mkdir \/opt\/lampp\/etc\/extra\/vhosts\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83c\udf0e 4. Domain &amp; Local Setup<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">4.1 Production DNS Setup<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Add one wildcard DNS record:<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">*<span class=\"hljs-selector-class\">.wizbrand<\/span><span class=\"hljs-selector-class\">.com<\/span> \u2192 <span class=\"hljs-selector-tag\">your_server_ip<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">4.2 Local Development Setup<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Edit <code>\/etc\/hosts<\/code> on <strong>host system<\/strong> (your laptop):<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">127<span class=\"hljs-selector-class\">.0<\/span><span class=\"hljs-selector-class\">.0<\/span><span class=\"hljs-selector-class\">.1<\/span> <span class=\"hljs-selector-tag\">user-123<\/span><span class=\"hljs-selector-class\">.wizbrand<\/span><span class=\"hljs-selector-class\">.com<\/span>\n127<span class=\"hljs-selector-class\">.0<\/span><span class=\"hljs-selector-class\">.0<\/span><span class=\"hljs-selector-class\">.1<\/span> <span class=\"hljs-selector-tag\">user-456<\/span><span class=\"hljs-selector-class\">.wizbrand<\/span><span class=\"hljs-selector-class\">.com<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\udd16 5. Laravel Route (routes\/web.php)<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">Route::get(<span class=\"hljs-string\">'\/create-container'<\/span>, &#91;ContainerController::class, <span class=\"hljs-string\">'createUserContainer'<\/span>])-&gt;middleware(<span class=\"hljs-string\">'auth'<\/span>);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd04 6. Workflow Summary<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>User logs into Laravel app<\/li>\n\n\n\n<li>Clicks button to create container<\/li>\n\n\n\n<li>Laravel creates Docker container on a unique port<\/li>\n\n\n\n<li>Laravel generates Apache virtualhost config<\/li>\n\n\n\n<li>Apache proxies <code>userXYZ.wizbrand.com<\/code> \u2192 user&#8217;s container<\/li>\n\n\n\n<li>User accesses the unique subdomain URL<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\ude80 Optional Enhancements<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use Laravel queue to create containers async<\/li>\n\n\n\n<li>Setup SSL (Let\u2019s Encrypt + wildcard)<\/li>\n\n\n\n<li>Add container expiry\/auto-deletion scheduler<\/li>\n\n\n\n<li>Store container info in DB<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udea8 Caveats<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Apache config reload is needed for each new subdomain (downtime may be noticeable)<\/li>\n\n\n\n<li>Traefik\/Nginx are more scalable but not used here as per your request<\/li>\n\n\n\n<li>Ensure ports are not reused across containers<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udcca Tools Used<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Laravel (PHP Backend)<\/li>\n\n\n\n<li>Docker (User environment containers)<\/li>\n\n\n\n<li>Apache (Reverse proxy)<\/li>\n\n\n\n<li>XAMPP (AMP stack)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83c\udf93 Conclusion<\/h2>\n\n\n\n<p>This setup allows you to offer per-user container environments with unique URLs, using <strong>Apache as a reverse proxy<\/strong> without requiring manual DNS records for each user. It&#8217;s great for development, testing, or isolated workspaces.<\/p>\n\n\n\n<p>You&#8217;re absolutely right \u2014 the solution I gave <strong>does involve creating a new Apache VirtualHost config per container<\/strong>, which works but is <strong>not scalable<\/strong> for hundreds of users.<\/p>\n\n\n\n<p>Since you\u2019re looking for a <strong>better, scalable approach using Apache<\/strong> only (no Traefik or Nginx), here&#8217;s the <strong>optimized solution<\/strong> you&#8217;re likely aiming for:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u2705 <strong>Improved Approach: One Wildcard VirtualHost + Rewrite Rules<\/strong><\/h2>\n\n\n\n<p>Instead of generating a new <code>VirtualHost<\/code> file for every container\/user, we\u2019ll use <strong>one single wildcard-based VirtualHost<\/strong> that dynamically reverse-proxies based on the subdomain.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\udde0 Concept<\/h3>\n\n\n\n<p>Assume:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Each user gets a subdomain like <code>user123.wizbrand.com<\/code><\/li>\n\n\n\n<li>Each container listens on a unique port like <code>91XXX<\/code> (e.g., 9123 for user 123)<\/li>\n<\/ul>\n\n\n\n<p>We&#8217;ll use <code>mod_rewrite<\/code> and <code>mod_proxy<\/code> to extract the subdomain and map it to the corresponding port dynamically.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd27 Step-by-Step: Dynamic Apache Reverse Proxy Using Subdomains<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 1. Enable Required Apache Modules<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">sudo a2enmod proxy\nsudo a2enmod proxy_http\nsudo a2enmod rewrite\nsudo systemctl restart apache2\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 2. Single Wildcard VirtualHost Configuration<\/h3>\n\n\n\n<p>Edit your Apache config (XAMPP: <code>\/opt\/lampp\/etc\/extra\/httpd-vhosts.conf<\/code> or Ubuntu default: <code>\/etc\/apache2\/sites-available\/000-default.conf<\/code>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;VirtualHost *:<span class=\"hljs-number\">80<\/span>&gt;\n    ServerName wizbrand.com\n    ServerAlias *.wizbrand.com\n\n    ProxyPreserveHost On\n    RewriteEngine On\n\n    <span class=\"hljs-comment\"># Extract username from subdomain (user123)<\/span>\n    RewriteCond %{HTTP_HOST} ^user(&#91;<span class=\"hljs-number\">0<\/span><span class=\"hljs-number\">-9<\/span>]+)\\.wizbrand\\.com$ &#91;NC]\n    RewriteRule ^\/(.*)$ http:<span class=\"hljs-comment\">\/\/127.0.0.1:9%1\/$1 &#91;P,L]<\/span>\n\n    ProxyPassReverse \/ http:<span class=\"hljs-comment\">\/\/127.0.0.1\/<\/span>\n&lt;\/VirtualHost&gt;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>\u2705 This does the magic:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Matches <code>user123.wizbrand.com<\/code><\/li>\n\n\n\n<li>Extracts <code>123<\/code> from the subdomain<\/li>\n\n\n\n<li>Proxies to <code>localhost:9123<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 3. Docker Container Port Strategy<\/h3>\n\n\n\n<p>Each container should expose port <code>80<\/code> to a host port like <code>9123<\/code>.<\/p>\n\n\n\n<p>Example command from Laravel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$containerName = <span class=\"hljs-string\">\"user-{$user-&gt;id}\"<\/span>;\n$hostPort = <span class=\"hljs-number\">9000<\/span> + $user-&gt;id;\n\nshell_exec(<span class=\"hljs-string\">\"docker run -d -p {$hostPort}:80 --name {$containerName} my-image\"<\/span>);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 4. DNS Setup (Production)<\/h3>\n\n\n\n<p>In your domain DNS provider (for <code>wizbrand.com<\/code>), create:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Type<\/th><th>Name<\/th><th>Value<\/th><\/tr><\/thead><tbody><tr><td>A<\/td><td><code>*<\/code><\/td><td><code>your_server_ip<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>This allows <code>*.wizbrand.com<\/code> to point to your server automatically.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2705 5. Local Development (<code>\/etc\/hosts<\/code>)<\/h3>\n\n\n\n<p>For testing on your local machine or VM:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">127<span class=\"hljs-selector-class\">.0<\/span><span class=\"hljs-selector-class\">.0<\/span><span class=\"hljs-selector-class\">.1<\/span> <span class=\"hljs-selector-tag\">user123<\/span><span class=\"hljs-selector-class\">.wizbrand<\/span><span class=\"hljs-selector-class\">.com<\/span>\n127<span class=\"hljs-selector-class\">.0<\/span><span class=\"hljs-selector-class\">.0<\/span><span class=\"hljs-selector-class\">.1<\/span> <span class=\"hljs-selector-tag\">user456<\/span><span class=\"hljs-selector-class\">.wizbrand<\/span><span class=\"hljs-selector-class\">.com<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Or use dynamic wildcard resolution services like:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>nip.io<\/code>: <code>user123.127.0.0.1.nip.io<\/code><\/li>\n\n\n\n<li><code>sslip.io<\/code>: <code>user123.127.0.0.1.sslip.io<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd01 Summary: Why This is Better<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Feature<\/th><th>Previous Method<\/th><th>Improved Method \u2705<\/th><\/tr><\/thead><tbody><tr><td>VHost per user<\/td><td>Yes \u274c<\/td><td>No \u2705<\/td><\/tr><tr><td>Apache reload for each user<\/td><td>Yes \u274c<\/td><td>No \u2705<\/td><\/tr><tr><td>Scalable for 100+ users<\/td><td>Not practical \u274c<\/td><td>Fully scalable \u2705<\/td><\/tr><tr><td>Performance-friendly<\/td><td>No \u274c<\/td><td>Yes \u2705<\/td><\/tr><tr><td>Maintains Apache-only setup<\/td><td>Yes \u2705<\/td><td>Yes \u2705<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udcd8 Laravel Integration Recap<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$port = <span class=\"hljs-number\">9000<\/span> + $user-&gt;id;\nshell_exec(<span class=\"hljs-string\">\"docker run -d -p {$port}:80 --name user-{$user-&gt;id} my-image\"<\/span>);\n\n<span class=\"hljs-keyword\">return<\/span> response()-&gt;json(&#91;\n    <span class=\"hljs-string\">'url'<\/span> =&gt; <span class=\"hljs-string\">\"http:\/\/user{$user-&gt;id}.wizbrand.com\"<\/span>\n]);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial guides you through setting up a multi-user container-based architecture using: We&#8217;ll configure Apache to dynamically proxy subdomains like user123.wizbrand.com to each user&#8217;s container (e.g., port 9123). \ud83c\udfe0 1&#8230;. <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-49074","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49074","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=49074"}],"version-history":[{"count":2,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49074\/revisions"}],"predecessor-version":[{"id":49076,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/49074\/revisions\/49076"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=49074"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=49074"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=49074"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}