{"id":401,"date":"2025-08-27T21:00:22","date_gmt":"2025-08-27T21:00:22","guid":{"rendered":"https:\/\/1v0.net\/blog\/?p=401"},"modified":"2025-08-27T21:00:24","modified_gmt":"2025-08-27T21:00:24","slug":"laravel-and-docker-setting-up-a-scalable-dev-environment","status":"publish","type":"post","link":"https:\/\/1v0.net\/blog\/laravel-and-docker-setting-up-a-scalable-dev-environment\/","title":{"rendered":"Laravel and Docker: Setting Up a Scalable Dev Environment"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\"><strong>Laravel and Docker: Setting Up a Scalable Dev Environment<\/strong><\/h2>\n\n\n\n<p>Docker has become the standard for creating consistent, portable development environments. Instead of &#8220;it works on my machine,&#8221; Docker ensures your Laravel app runs the same way everywhere\u2014on your laptop, staging server, or production cluster. In this guide, we\u2019ll containerize Laravel, configure services like MySQL and Redis, and run the app in a scalable setup.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n\n<h2 class=\"wp-block-heading\"><strong>1 &#8211; Install Docker &amp; Docker Compose<\/strong><\/h2>\n\n\n\n<p>First, ensure you have Docker Engine and Docker Compose installed. Docker Compose lets you run multiple containers (Laravel app, MySQL, Redis, Nginx) together.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># Check Docker<\/span>\ndocker -v\n<span class=\"hljs-comment\"># Check Compose<\/span>\ndocker compose version<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If these commands print version numbers, you\u2019re good to go. Otherwise, download from <a href=\"https:\/\/www.docker.com\/products\/docker-desktop\">Docker Desktop<\/a>.<\/p>\n\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n\n<h2 class=\"wp-block-heading\"><strong>2 &#8211; Create a Dockerfile for Laravel<\/strong><\/h2>\n\n\n\n<p>The Dockerfile defines how the Laravel container is built.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Dockerfile\" data-shcb-language-slug=\"dockerfile\"><span><code class=\"hljs language-dockerfile\"><span class=\"hljs-comment\"># Dockerfile<\/span>\n<span class=\"hljs-keyword\">FROM<\/span> php:<span class=\"hljs-number\">8.3<\/span>-fpm\n\n<span class=\"hljs-comment\"># Install system dependencies<\/span>\n<span class=\"hljs-keyword\">RUN<\/span><span class=\"bash\"> apt-get update &amp;&amp; apt-get install -y \\\n    git curl libpng-dev libonig-dev libxml2-dev zip unzip \\\n    &amp;&amp; docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd<\/span>\n\n<span class=\"hljs-comment\"># Install Composer<\/span>\n<span class=\"hljs-keyword\">COPY<\/span><span class=\"bash\"> --from=composer:2.7 \/usr\/bin\/composer \/usr\/bin\/composer<\/span>\n\n<span class=\"hljs-keyword\">WORKDIR<\/span><span class=\"bash\"> \/var\/www<\/span>\n\n<span class=\"hljs-keyword\">COPY<\/span><span class=\"bash\"> . .<\/span>\n\n<span class=\"hljs-keyword\">RUN<\/span><span class=\"bash\"> composer install --no-dev --optimize-autoloader<\/span>\n\n<span class=\"hljs-keyword\">CMD<\/span><span class=\"bash\"> &#91;<span class=\"hljs-string\">\"php-fpm\"<\/span>]<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Dockerfile<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">dockerfile<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This builds a PHP-FPM container with Composer and required extensions. The app code is copied inside <code>\/var\/www<\/code>, ready to run.<\/p>\n\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3 &#8211; Define docker-compose.yml<\/strong><\/h2>\n\n\n\n<p>Docker Compose orchestrates multiple containers: Laravel (PHP-FPM), MySQL, Redis, and Nginx as a reverse proxy.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"YAML\" data-shcb-language-slug=\"yaml\"><span><code class=\"hljs language-yaml\"><span class=\"hljs-comment\"># docker-compose.yml<\/span>\n<span class=\"hljs-attr\">version:<\/span> <span class=\"hljs-string\">'3.8'<\/span>\n\n<span class=\"hljs-attr\">services:<\/span>\n  <span class=\"hljs-attr\">app:<\/span>\n    <span class=\"hljs-attr\">build:<\/span>\n      <span class=\"hljs-attr\">context:<\/span> <span class=\"hljs-string\">.<\/span>\n      <span class=\"hljs-attr\">dockerfile:<\/span> <span class=\"hljs-string\">Dockerfile<\/span>\n    <span class=\"hljs-attr\">volumes:<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">.:\/var\/www<\/span>\n    <span class=\"hljs-attr\">networks:<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">laravel<\/span>\n    <span class=\"hljs-attr\">depends_on:<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">db<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">redis<\/span>\n\n  <span class=\"hljs-attr\">db:<\/span>\n    <span class=\"hljs-attr\">image:<\/span> <span class=\"hljs-string\">mysql:8.0<\/span>\n    <span class=\"hljs-attr\">environment:<\/span>\n      <span class=\"hljs-attr\">MYSQL_DATABASE:<\/span> <span class=\"hljs-string\">laravel<\/span>\n      <span class=\"hljs-attr\">MYSQL_ROOT_PASSWORD:<\/span> <span class=\"hljs-string\">root<\/span>\n    <span class=\"hljs-attr\">volumes:<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">dbdata:\/var\/lib\/mysql<\/span>\n    <span class=\"hljs-attr\">networks:<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">laravel<\/span>\n\n  <span class=\"hljs-attr\">redis:<\/span>\n    <span class=\"hljs-attr\">image:<\/span> <span class=\"hljs-string\">redis:alpine<\/span>\n    <span class=\"hljs-attr\">networks:<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">laravel<\/span>\n\n  <span class=\"hljs-attr\">nginx:<\/span>\n    <span class=\"hljs-attr\">image:<\/span> <span class=\"hljs-string\">nginx:alpine<\/span>\n    <span class=\"hljs-attr\">volumes:<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">.:\/var\/www<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">.\/nginx.conf:\/etc\/nginx\/conf.d\/default.conf<\/span>\n    <span class=\"hljs-attr\">ports:<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">\"8000:80\"<\/span>\n    <span class=\"hljs-attr\">networks:<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">laravel<\/span>\n    <span class=\"hljs-attr\">depends_on:<\/span>\n      <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-string\">app<\/span>\n\n<span class=\"hljs-attr\">volumes:<\/span>\n  <span class=\"hljs-attr\">dbdata:<\/span>\n\n<span class=\"hljs-attr\">networks:<\/span>\n  <span class=\"hljs-attr\">laravel:<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">YAML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">yaml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This defines four services: <code>app<\/code> (Laravel), <code>db<\/code> (MySQL), <code>redis<\/code>, and <code>nginx<\/code>. The app depends on Redis and DB to start correctly. Nginx proxies requests to the app container.<\/p>\n\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n\n<h2 class=\"wp-block-heading\"><strong>4 &#8211; Configure Nginx<\/strong><\/h2>\n\n\n\n<p>Add an Nginx config to route traffic into the Laravel container.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Nginx\" data-shcb-language-slug=\"nginx\"><span><code class=\"hljs language-nginx\"><span class=\"hljs-comment\"># nginx.conf<\/span>\n<span class=\"hljs-section\">server<\/span> {\n    <span class=\"hljs-attribute\">listen<\/span> <span class=\"hljs-number\">80<\/span>;\n    <span class=\"hljs-attribute\">index<\/span> index.php index.html;\n    <span class=\"hljs-attribute\">root<\/span> \/var\/www\/public;\n\n    <span class=\"hljs-attribute\">location<\/span> \/ {\n        <span class=\"hljs-attribute\">try_files<\/span> <span class=\"hljs-variable\">$uri<\/span> <span class=\"hljs-variable\">$uri<\/span>\/ \/index.php?<span class=\"hljs-variable\">$query_string<\/span>;\n    }\n\n    <span class=\"hljs-attribute\">location<\/span> <span class=\"hljs-regexp\">~ \\.php$<\/span> {\n        <span class=\"hljs-attribute\">fastcgi_pass<\/span> app:<span class=\"hljs-number\">9000<\/span>;\n        <span class=\"hljs-attribute\">include<\/span> fastcgi_params;\n        <span class=\"hljs-attribute\">fastcgi_param<\/span> SCRIPT_FILENAME <span class=\"hljs-variable\">$document_root<\/span><span class=\"hljs-variable\">$fastcgi_script_name<\/span>;\n        <span class=\"hljs-attribute\">fastcgi_index<\/span> index.php;\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Nginx<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">nginx<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This config sends PHP requests to the <code>app<\/code> container (running PHP-FPM) and serves static assets directly. It mirrors production best practices.<\/p>\n\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n\n<h2 class=\"wp-block-heading\"><strong>5 &#8211; Run Containers<\/strong><\/h2>\n\n\n\n<p>Start your Laravel environment with:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">docker compose up -d --build<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This builds containers and runs them in the background. Visit <code>http:\/\/localhost:8000<\/code> to access your Laravel app inside Docker.<\/p>\n\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n\n<h2 class=\"wp-block-heading\"><strong>6 &#8211; Scaling with Docker<\/strong><\/h2>\n\n\n\n<p>One of Docker\u2019s strengths is scaling services horizontally. You can run multiple Laravel containers behind Nginx:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">docker compose up --scale app=3 -d<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This runs three Laravel app containers in parallel, balancing requests through Nginx. Perfect for high-concurrency setups, especially when combined with <a href=\"\/blog\/optimizing-laravel-for-high-concurrency-with-octane\">Octane<\/a>.<\/p>\n\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>You\u2019ve containerized Laravel with Docker, set up MySQL, Redis, and Nginx, and even scaled app containers horizontally. This setup ensures every developer runs the same environment and makes production deployment smoother. For even more scalability, integrate Docker with AWS ECS, Kubernetes, or DigitalOcean Droplets.<\/p>\n\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n\n<h2 class=\"wp-block-heading\">What\u2019s Next<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/blog\/10-proven-ways-to-optimize-laravel-for-high-traffic\">10 Proven Ways to Optimize Laravel for High Traffic<\/a> \u2014 combine Docker scaling with caching and queues.<\/li>\n<li><a href=\"\/blog\/optimizing-laravel-for-high-concurrency-with-octane\">Optimizing Laravel for High Concurrency with Octane<\/a> \u2014 supercharge Dockerized apps with in-memory request handling.<\/li>\n<li><a href=\"\/blog\/optimizing-laravel-for-aws-deployment-step-by-step\">Optimizing Laravel for AWS Deployment (Step-by-Step)<\/a> \u2014 deploy your Dockerized Laravel app in the cloud.<\/li>\n<\/ul>\n\n","protected":false},"excerpt":{"rendered":"<p>Laravel and Docker: Setting Up a Scalable Dev Environment Docker has become the standard for creating consistent, portable development environments. Instead of &#8220;it works on my machine,&#8221; Docker ensures your Laravel app runs the same way everywhere\u2014on your laptop, staging server, or production cluster. In this guide, we\u2019ll containerize Laravel, configure services like MySQL and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":405,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[71,70,64],"class_list":["post-401","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-laravel","tag-devops","tag-docker","tag-scaling"],"_links":{"self":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/401","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/comments?post=401"}],"version-history":[{"count":1,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/401\/revisions"}],"predecessor-version":[{"id":404,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/401\/revisions\/404"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media\/405"}],"wp:attachment":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media?parent=401"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/categories?post=401"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/tags?post=401"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}