<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Akandwanaho Alvin</title>
    <description>The latest articles on DEV Community by Akandwanaho Alvin (@quantumminds).</description>
    <link>https://dev.to/quantumminds</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3965416%2Fd58feef5-0b5a-42af-a732-f8bfaffd6ee2.png</url>
      <title>DEV Community: Akandwanaho Alvin</title>
      <link>https://dev.to/quantumminds</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/quantumminds"/>
    <language>en</language>
    <item>
      <title>How I built a 120MB production Laravel Docker image (and why yours is probably 800MB)</title>
      <dc:creator>Akandwanaho Alvin</dc:creator>
      <pubDate>Wed, 03 Jun 2026 07:04:59 +0000</pubDate>
      <link>https://dev.to/quantumminds/how-i-built-a-120mb-production-laravel-docker-image-and-why-yours-is-probably-800mb-5dhb</link>
      <guid>https://dev.to/quantumminds/how-i-built-a-120mb-production-laravel-docker-image-and-why-yours-is-probably-800mb-5dhb</guid>
      <description>&lt;p&gt;Most Laravel Docker tutorials give you a Dockerfile that produces an 800MB image. Mine is 120MB. Here is exactly how — and why it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with a single-stage Dockerfile
&lt;/h2&gt;

&lt;p&gt;When you install Composer, Node.js, npm, and all your dev dependencies in one layer, every single one of those tools ends up in your production image. Your image carries gigabytes of software that has zero business being on a production server.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution: multi-stage builds
&lt;/h2&gt;

&lt;p&gt;Docker lets you define multiple stages in one Dockerfile. Stage 1 does all the heavy lifting — installing Composer, running npm, compiling your Vite assets. Stage 2 starts completely fresh, copies only the compiled output, and ships nothing else.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stage 1: builder — installs everything, compiles assets&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;php:8.3-cli&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; git nodejs npm &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; curl &lt;span class="nt"&gt;-sS&lt;/span&gt; https://getcomposer.org/installer | php &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mv &lt;/span&gt;composer.phar /usr/local/bin/composer

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; composer.json composer.lock ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-dev&lt;/span&gt; &lt;span class="nt"&gt;--optimize-autoloader&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json package-lock.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run build

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Stage 2: production — starts clean, copies compiled output only&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;php:8.3-fpm-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;production&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; nginx supervisor
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app /var/www/html&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Single-stage&lt;/th&gt;
&lt;th&gt;Multi-stage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Image size&lt;/td&gt;
&lt;td&gt;~800MB&lt;/td&gt;
&lt;td&gt;~120MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build tools in prod&lt;/td&gt;
&lt;td&gt;Yes (security risk)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deploy speed&lt;/td&gt;
&lt;td&gt;Slow&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What goes in each stage
&lt;/h2&gt;

&lt;p&gt;Stage 1 needs: Composer, Node.js, npm, git, dev headers for PHP extensions.&lt;br&gt;
Stage 2 needs: PHP-FPM, Nginx, Supervisor, and the compiled app. Nothing else.&lt;/p&gt;
&lt;h2&gt;
  
  
  The order of COPY matters for caching
&lt;/h2&gt;

&lt;p&gt;Copy composer.json BEFORE the rest of your code. Docker caches each layer — if your PHP files change but composer.json didn't, Docker skips reinstalling all your packages. This alone saves 2–3 minutes per build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; composer.json composer.lock ./   # cached unless deps change&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-dev&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .                              # only this layer re-runs on code changes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;Build once with a naive Dockerfile, then build with the multi-stage version. Run &lt;code&gt;docker images&lt;/code&gt; and compare the sizes. The difference will change how you think about Docker forever.&lt;/p&gt;




&lt;p&gt;I wrote a full 50-page guide covering this entire stack — Docker, GitHub Actions CI/CD, Kubernetes, and SQLite as the production database. Link in my profile if you want the complete setup.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>docker</category>
      <category>laravel</category>
    </item>
    <item>
      <title>Deploying Laravel with Docker, GitHub Actions, and Kubernetes</title>
      <dc:creator>Akandwanaho Alvin</dc:creator>
      <pubDate>Tue, 02 Jun 2026 22:49:36 +0000</pubDate>
      <link>https://dev.to/quantumminds/deploying-laravel-with-docker-github-actions-and-kubernetes-561i</link>
      <guid>https://dev.to/quantumminds/deploying-laravel-with-docker-github-actions-and-kubernetes-561i</guid>
      <description>&lt;p&gt;&lt;strong&gt;Chapter 3: The Dockerfile — Multi-Stage Build&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;3.1 Why Multi-Stage Builds?&lt;/strong&gt;&lt;br&gt;
A naive Dockerfile installs everything (Composer, Node.js, npm, dev dependencies) in a single layer. The resulting image is hundreds of megabytes larger than it needs to be and may contain security vulnerabilities from build tools that have no business being in production.&lt;br&gt;
Multi-stage builds solve this by separating the build environment from the runtime environment:&lt;br&gt;
• Stage 1 (builder): Has Composer, Node.js, npm, and all dev tooling installed. Installs production PHP dependencies and compiles JavaScript assets.&lt;br&gt;
• Stage 2 (production): Starts from a clean Alpine Linux base. Copies only the compiled output from Stage 1. Contains nothing that is not needed at runtime.&lt;/p&gt;

&lt;p&gt;Metric  Single-Stage vs Multi-Stage&lt;br&gt;
Image size  ~800MB vs ~120MB&lt;br&gt;
Attack surface  High (build tools, dev deps) vs Low (runtime only)&lt;br&gt;
Build caching   Poor vs Excellent (stages cache independently)&lt;br&gt;
Security scanning   Many CVEs from build tools vs Minimal&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.2 The Complete Dockerfile&lt;/strong&gt;&lt;br&gt;
docker/Dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# ─────────────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="c"&gt;# Stage 1: builder&lt;/span&gt;
&lt;span class="c"&gt;# Installs all dependencies and compiles assets.&lt;/span&gt;
&lt;span class="c"&gt;# This stage is NEVER shipped to production.&lt;/span&gt;
&lt;span class="c"&gt;# ─────────────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;php:8.3-cli&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;

&lt;span class="c"&gt;# Install system dependencies needed during the build phase:&lt;/span&gt;
&lt;span class="c"&gt;#   git      - Composer needs this to clone packages from GitHub&lt;/span&gt;
&lt;span class="c"&gt;#   zip/unzip - needed for PHP archive operations&lt;/span&gt;
&lt;span class="c"&gt;#   libpng-dev, libonig-dev, libxml2-dev - headers for PHP extensions&lt;/span&gt;
&lt;span class="c"&gt;#   nodejs, npm - for compiling JS assets with Vite&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    git curl zip unzip &lt;span class="se"&gt;\
&lt;/span&gt;    libpng-dev libonig-dev libxml2-dev &lt;span class="se"&gt;\
&lt;/span&gt;    nodejs npm &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-php-ext-install pdo pdo_sqlite mbstring exif pcntl bcmath gd &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; curl &lt;span class="nt"&gt;-sS&lt;/span&gt; https://getcomposer.org/installer | php &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mv &lt;/span&gt;composer.phar /usr/local/bin/composer &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Copy composer files first to leverage Docker layer caching.&lt;/span&gt;
&lt;span class="c"&gt;# If composer.json and composer.lock have not changed, Docker reuses&lt;/span&gt;
&lt;span class="c"&gt;# the cached layer even if application code has changed.&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; composer.json composer.lock ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nt"&gt;--no-dev&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nt"&gt;--optimize-autoloader&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nt"&gt;--no-interaction&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nt"&gt;--no-scripts&lt;/span&gt;

&lt;span class="c"&gt;# Copy package.json for the same caching benefit&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json package-lock.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci

&lt;span class="c"&gt;# Now copy the rest of the application code&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Run Composer scripts now that the full codebase is present&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;composer run-script post-autoload-dump &lt;span class="nt"&gt;--no-interaction&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="c"&gt;# Compile JavaScript/CSS assets&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build

&lt;span class="c"&gt;# ─────────────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="c"&gt;# Stage 2: production&lt;/span&gt;
&lt;span class="c"&gt;# Lean Alpine-based image. Only runtime dependencies.&lt;/span&gt;
&lt;span class="c"&gt;# ─────────────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;php:8.3-fpm-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;production&lt;/span&gt;

&lt;span class="c"&gt;# Install runtime system packages:&lt;/span&gt;
&lt;span class="c"&gt;#   nginx      - HTTP server to accept incoming requests&lt;/span&gt;
&lt;span class="c"&gt;#   supervisor - process manager to run both nginx and php-fpm&lt;/span&gt;
&lt;span class="c"&gt;#   sqlite     - SQLite runtime libraries&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    nginx &lt;span class="se"&gt;\
&lt;/span&gt;    supervisor &lt;span class="se"&gt;\
&lt;/span&gt;    sqlite &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-php-ext-install pdo pdo_sqlite mbstring exif pcntl bcmath

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /var/www/html&lt;/span&gt;

&lt;span class="c"&gt;# Copy the compiled application from the builder stage.&lt;/span&gt;
&lt;span class="c"&gt;# Crucially, we do NOT copy node_modules or dev dependencies.&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app /var/www/html&lt;/span&gt;

&lt;span class="c"&gt;# Copy configuration files&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; docker/nginx.conf      /etc/nginx/nginx.conf&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; docker/php.ini         /usr/local/etc/php/conf.d/custom.ini&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; docker/supervisord.conf /etc/supervisord.conf&lt;/span&gt;

&lt;span class="c"&gt;# Create the SQLite database directory.&lt;/span&gt;
&lt;span class="c"&gt;# The actual .sqlite file will come from a PersistentVolumeClaim in k8s.&lt;/span&gt;
&lt;span class="c"&gt;# Locally it will be mounted via Docker volume.&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/www/html/database

&lt;span class="c"&gt;# Fix storage permissions.&lt;/span&gt;
&lt;span class="c"&gt;# www-data is the nginx/php-fpm user.&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; www-data:www-data &lt;span class="se"&gt;\
&lt;/span&gt;      /var/www/html/storage &lt;span class="se"&gt;\
&lt;/span&gt;      /var/www/html/bootstrap/cache &lt;span class="se"&gt;\
&lt;/span&gt;      /var/www/html/database &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 775 &lt;span class="se"&gt;\
&lt;/span&gt;      /var/www/html/storage &lt;span class="se"&gt;\
&lt;/span&gt;      /var/www/html/bootstrap/cache &lt;span class="se"&gt;\
&lt;/span&gt;      /var/www/html/database

&lt;span class="c"&gt;# Optimise Laravel for production&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;php artisan config:cache &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; php artisan route:cache &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; php artisan view:cache

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;

&lt;span class="c"&gt;# Supervisord starts both nginx and php-fpm&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.3 Nginx Configuration&lt;/strong&gt;&lt;br&gt;
Nginx acts as the front-facing HTTP server inside the container. It serves static assets (CSS, JS, images) directly from disk and proxies all PHP requests to PHP-FPM via FastCGI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;docker/nginx.conf&lt;/span&gt;
&lt;span class="c1"&gt;# We use the events block even though we are not customising it.&lt;/span&gt;
&lt;span class="c1"&gt;# Nginx requires it.&lt;/span&gt;
&lt;span class="s"&gt;events&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;worker_connections&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;include&lt;/span&gt;       &lt;span class="n"&gt;/etc/nginx/mime.types&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;default_type&lt;/span&gt;  &lt;span class="nc"&gt;application/octet-stream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Logging — output to stdout/stderr so kubectl logs works&lt;/span&gt;
    &lt;span class="kn"&gt;access_log&lt;/span&gt;  &lt;span class="n"&gt;/dev/stdout&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;error_log&lt;/span&gt;   &lt;span class="n"&gt;/dev/stderr&lt;/span&gt; &lt;span class="s"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Basic performance settings&lt;/span&gt;
    &lt;span class="kn"&gt;sendfile&lt;/span&gt;           &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;keepalive_timeout&lt;/span&gt;  &lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;gzip&lt;/span&gt;               &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;gzip_types&lt;/span&gt;         &lt;span class="nc"&gt;text/plain&lt;/span&gt; &lt;span class="nc"&gt;application/json&lt;/span&gt; &lt;span class="nc"&gt;application/javascript&lt;/span&gt; &lt;span class="nc"&gt;text/css&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/html/public&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.php&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;# Laravel's try_files pattern:&lt;/span&gt;
        &lt;span class="c1"&gt;# 1. Try to serve the exact file ($uri)&lt;/span&gt;
        &lt;span class="c1"&gt;# 2. Try to serve as a directory ($uri/)&lt;/span&gt;
        &lt;span class="c1"&gt;# 3. Fall back to index.php with the query string&lt;/span&gt;
        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="n"&gt;/index.php?&lt;/span&gt;&lt;span class="nv"&gt;$query_string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;# Send all .php files to PHP-FPM running on port 9000&lt;/span&gt;
        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;\.php$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;fastcgi_pass&lt;/span&gt;  &lt;span class="nf"&gt;127.0.0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;fastcgi_index&lt;/span&gt; &lt;span class="s"&gt;index.php&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;include&lt;/span&gt;       &lt;span class="s"&gt;fastcgi_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;fastcgi_param&lt;/span&gt; &lt;span class="s"&gt;SCRIPT_FILENAME&lt;/span&gt; &lt;span class="nv"&gt;$document_root$fastcgi_script_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;fastcgi_param&lt;/span&gt; &lt;span class="s"&gt;PATH_INFO&lt;/span&gt; &lt;span class="nv"&gt;$fastcgi_path_info&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;fastcgi_read_timeout&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;# Deny access to .htaccess and other hidden files&lt;/span&gt;
        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/\.ht&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;deny&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;# Deny direct access to the SQLite database file&lt;/span&gt;
        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;\.sqlite$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;deny&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.4 PHP Configuration&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;docker/php.ini&lt;/span&gt;
&lt;span class="c"&gt;; Production PHP settings for a Laravel API
&lt;/span&gt;
&lt;span class="c"&gt;; Memory limit — increase for large Eloquent operations
&lt;/span&gt;&lt;span class="py"&gt;memory_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;256M&lt;/span&gt;

&lt;span class="c"&gt;; Maximum execution time in seconds
&lt;/span&gt;&lt;span class="py"&gt;max_execution_time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;60&lt;/span&gt;

&lt;span class="c"&gt;; Maximum POST body size (for file uploads via API)
&lt;/span&gt;&lt;span class="py"&gt;post_max_size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;20M&lt;/span&gt;
&lt;span class="py"&gt;upload_max_filesize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;20M&lt;/span&gt;

&lt;span class="c"&gt;; Hide PHP version from response headers (security)
&lt;/span&gt;&lt;span class="py"&gt;expose_php&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Off&lt;/span&gt;

&lt;span class="c"&gt;; Disable error display in responses; log to stderr instead
&lt;/span&gt;&lt;span class="py"&gt;display_errors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Off&lt;/span&gt;
&lt;span class="py"&gt;log_errors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;On&lt;/span&gt;
&lt;span class="py"&gt;error_log&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/dev/stderr&lt;/span&gt;


&lt;span class="c"&gt;; OPcache — dramatically speeds up PHP by caching compiled bytecode
&lt;/span&gt;&lt;span class="py"&gt;opcache.enable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1&lt;/span&gt;
&lt;span class="py"&gt;opcache.memory_consumption&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;128&lt;/span&gt;
&lt;span class="py"&gt;opcache.interned_strings_buffer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;8&lt;/span&gt;
&lt;span class="py"&gt;opcache.max_accelerated_files&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;10000&lt;/span&gt;
&lt;span class="py"&gt;opcache.revalidate_freq&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;0    ; never recheck files in production&lt;/span&gt;
&lt;span class="py"&gt;opcache.validate_timestamps&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.5 Supervisord Configuration&lt;/strong&gt;&lt;br&gt;
Kubernetes expects each container to run a single foreground process. Since we need both Nginx and PHP-FPM running, we use Supervisord as a process manager to start and monitor both.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;docker/supervisord.conf&lt;/span&gt;
&lt;span class="nn"&gt;[supervisord]&lt;/span&gt;
&lt;span class="c"&gt;; Run in the foreground so Docker can track the process
&lt;/span&gt;&lt;span class="py"&gt;nodaemon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;logfile&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/dev/null&lt;/span&gt;
&lt;span class="py"&gt;logfile_maxbytes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;

&lt;span class="nn"&gt;[program:php-fpm]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/sbin/php-fpm --nodaemonize&lt;/span&gt;
&lt;span class="py"&gt;autostart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;autorestart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;stdout_logfile&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/dev/stdout&lt;/span&gt;
&lt;span class="py"&gt;stdout_logfile_maxbytes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;
&lt;span class="py"&gt;stderr_logfile&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/dev/stderr&lt;/span&gt;
&lt;span class="py"&gt;stderr_logfile_maxbytes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;

&lt;span class="nn"&gt;[program:nginx]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/sbin/nginx -g "daemon off;"&lt;/span&gt;
&lt;span class="py"&gt;autostart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;autorestart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;stdout_logfile&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/dev/stdout&lt;/span&gt;
&lt;span class="py"&gt;stdout_logfile_maxbytes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;
&lt;span class="py"&gt;stderr_logfile&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/dev/stderr&lt;/span&gt;
&lt;span class="py"&gt;stderr_logfile_maxbytes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;#laravel13  #DEVOPS #Kubernetes #laravelDeployment #fullstackdevelopment&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>php</category>
      <category>docker</category>
      <category>laravel</category>
    </item>
  </channel>
</rss>
