|
461 | 461 |
|
462 | 462 | </li> |
463 | 463 |
|
464 | | - <li class="md-nav__item"> |
465 | | - <a href="#bluegreen-deployments" class="md-nav__link"> |
466 | | - <span class="md-ellipsis"> |
467 | | - Blue/Green Deployments |
468 | | - </span> |
469 | | - </a> |
| 464 | + </ul> |
470 | 465 |
|
471 | | - <nav class="md-nav" aria-label="Blue/Green Deployments"> |
472 | | - <ul class="md-nav__list"> |
473 | | - |
474 | | - <li class="md-nav__item"> |
475 | | - <a href="#1-caddyfile" class="md-nav__link"> |
476 | | - <span class="md-ellipsis"> |
477 | | - 1. Caddyfile |
478 | | - </span> |
479 | | - </a> |
| 466 | +</nav> |
| 467 | + |
| 468 | + </li> |
480 | 469 |
|
481 | | -</li> |
482 | | - |
483 | | - <li class="md-nav__item"> |
484 | | - <a href="#2-start-two-stacks" class="md-nav__link"> |
485 | | - <span class="md-ellipsis"> |
486 | | - 2. Start two Stacks |
487 | | - </span> |
488 | | - </a> |
| 470 | + |
| 471 | + |
| 472 | + |
| 473 | + |
489 | 474 |
|
490 | | -</li> |
491 | | - |
492 | | - <li class="md-nav__item"> |
493 | | - <a href="#3-front-proxy" class="md-nav__link"> |
494 | | - <span class="md-ellipsis"> |
495 | | - 3. Front Proxy |
496 | | - </span> |
497 | | - </a> |
498 | 475 |
|
499 | | -</li> |
500 | | - |
501 | | - <li class="md-nav__item"> |
502 | | - <a href="#4-deploying" class="md-nav__link"> |
503 | | - <span class="md-ellipsis"> |
504 | | - 4. Deploying |
505 | | - </span> |
506 | | - </a> |
507 | 476 |
|
508 | | -</li> |
| 477 | + |
| 478 | + <li class="md-nav__item"> |
| 479 | + <a href="../bluegreen.md" class="md-nav__link"> |
509 | 480 |
|
510 | | - </ul> |
511 | | - </nav> |
512 | 481 |
|
513 | | -</li> |
514 | | - |
515 | | - </ul> |
516 | 482 |
|
517 | | -</nav> |
518 | | - |
| 483 | + <span class="md-ellipsis"> |
| 484 | + Blue/Green Deployments |
| 485 | + |
| 486 | + </span> |
| 487 | + |
| 488 | + |
| 489 | + </a> |
519 | 490 | </li> |
520 | 491 |
|
521 | 492 |
|
|
602 | 573 | </span> |
603 | 574 | </a> |
604 | 575 |
|
605 | | -</li> |
606 | | - |
607 | | - <li class="md-nav__item"> |
608 | | - <a href="#bluegreen-deployments" class="md-nav__link"> |
609 | | - <span class="md-ellipsis"> |
610 | | - Blue/Green Deployments |
611 | | - </span> |
612 | | - </a> |
613 | | - |
614 | | - <nav class="md-nav" aria-label="Blue/Green Deployments"> |
615 | | - <ul class="md-nav__list"> |
616 | | - |
617 | | - <li class="md-nav__item"> |
618 | | - <a href="#1-caddyfile" class="md-nav__link"> |
619 | | - <span class="md-ellipsis"> |
620 | | - 1. Caddyfile |
621 | | - </span> |
622 | | - </a> |
623 | | - |
624 | | -</li> |
625 | | - |
626 | | - <li class="md-nav__item"> |
627 | | - <a href="#2-start-two-stacks" class="md-nav__link"> |
628 | | - <span class="md-ellipsis"> |
629 | | - 2. Start two Stacks |
630 | | - </span> |
631 | | - </a> |
632 | | - |
633 | | -</li> |
634 | | - |
635 | | - <li class="md-nav__item"> |
636 | | - <a href="#3-front-proxy" class="md-nav__link"> |
637 | | - <span class="md-ellipsis"> |
638 | | - 3. Front Proxy |
639 | | - </span> |
640 | | - </a> |
641 | | - |
642 | | -</li> |
643 | | - |
644 | | - <li class="md-nav__item"> |
645 | | - <a href="#4-deploying" class="md-nav__link"> |
646 | | - <span class="md-ellipsis"> |
647 | | - 4. Deploying |
648 | | - </span> |
649 | | - </a> |
650 | | - |
651 | | -</li> |
652 | | - |
653 | | - </ul> |
654 | | - </nav> |
655 | | - |
656 | 576 | </li> |
657 | 577 |
|
658 | 578 | </ul> |
@@ -724,71 +644,6 @@ <h2 id="4-launch-your-stack">🚀 4. Launch your Stack</h2> |
724 | 644 | docker<span class="w"> </span>compose<span class="w"> </span>up<span class="w"> </span>-d |
725 | 645 | docker<span class="w"> </span>compose<span class="w"> </span><span class="nb">exec</span><span class="w"> </span>postgres<span class="w"> </span>migrate |
726 | 646 | </code></pre></div> |
727 | | -<h2 id="bluegreen-deployments">Blue/Green Deployments</h2> |
728 | | -<p>This is a deployment method where two complete stacks are running side-by-side. |
729 | | -One is serving production traffic, while the other is idle. You deploy to the |
730 | | -idle stack, test it, and when you’re ready you swap roles — the idle stack |
731 | | -becomes production instantly, and the old production becomes idle. This |
732 | | -provides near-zero downtime and an easy rollback path.</p> |
733 | | -<p>We’ll bring up two stacks, <code>blue</code> and <code>green</code>, with no ports exposed. A |
734 | | -separate lightweight front proxy binds to <code>:80</code> and <code>:443</code> and routes traffic |
735 | | -to whichever stack is active.</p> |
736 | | -<h3 id="1-caddyfile">1. Caddyfile</h3> |
737 | | -<p>Remove the exposed ports from the Caddy service. Also set <code>CADDY_SITE_ADDRESS</code> |
738 | | -to only <code>:80</code> (leaving TLS termination to the front proxy):</p> |
739 | | -<div class="highlight"><span class="filename">compose.yaml</span><pre><span></span><code><span class="nt">caddy</span><span class="p">:</span> |
740 | | -<span class="w"> </span><span class="nt">environment</span><span class="p">:</span> |
741 | | -<span class="w"> </span><span class="nt">CADDY_SITE_ADDRESS</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">:80</span> |
742 | | -</code></pre></div> |
743 | | -<p>To share data between the two stacks (database, uploads, etc.), give volumes |
744 | | -explicit names:</p> |
745 | | -<div class="highlight"><span class="filename">compose.yaml</span><pre><span></span><code><span class="nt">volumes</span><span class="p">:</span> |
746 | | -<span class="w"> </span><span class="nt">postgres_data</span><span class="p">:</span> |
747 | | -<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">postgres-data</span> |
748 | | -<span class="w"> </span><span class="nt">user_data</span><span class="p">:</span> |
749 | | -<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">user-data</span> |
750 | | -</code></pre></div> |
751 | | -<h3 id="2-start-two-stacks">2. Start two Stacks</h3> |
752 | | -<p>On the server, bring up two stacks, <code>blue</code> and <code>green</code>:</p> |
753 | | -<div class="highlight"><pre><span></span><code>docker<span class="w"> </span>compose<span class="w"> </span>-p<span class="w"> </span>blue<span class="w"> </span>up<span class="w"> </span>-d |
754 | | -docker<span class="w"> </span>compose<span class="w"> </span>-p<span class="w"> </span>green<span class="w"> </span>up<span class="w"> </span>-d |
755 | | -</code></pre></div> |
756 | | -<h3 id="3-front-proxy">3. Front Proxy</h3> |
757 | | -<p>The front proxy is a single Caddy container that binds <code>:80</code> and <code>:443</code> on the |
758 | | -server and routes requests into either the Blue or Green stack.</p> |
759 | | -<p>On the server, create a simple <code>Caddyfile</code>:</p> |
760 | | -<div class="highlight"><span class="filename">Caddyfile</span><pre><span></span><code>api.myapp.com reverse_proxy blue_caddy:80 |
761 | | - |
762 | | -# Optionally point a second hostname to the idle stack for testing |
763 | | -next.myapp.com reverse_proxy blue_caddy:80 |
764 | | -</code></pre></div> |
765 | | -<p>The front proxy manages TLS, so give it a persistent volume for certificates:</p> |
766 | | -<div class="highlight"><pre><span></span><code>docker<span class="w"> </span>volume<span class="w"> </span>create<span class="w"> </span>caddy_data |
767 | | -</code></pre></div> |
768 | | -<p>Start the proxy and attach it to both networks:</p> |
769 | | -<div class="highlight"><pre><span></span><code>docker<span class="w"> </span>run<span class="w"> </span>-d<span class="w"> </span><span class="se">\</span> |
770 | | -<span class="w"> </span>--name<span class="w"> </span>front-proxy<span class="w"> </span><span class="se">\</span> |
771 | | -<span class="w"> </span>-p<span class="w"> </span><span class="m">80</span>:80<span class="w"> </span>-p<span class="w"> </span><span class="m">443</span>:443<span class="w"> </span><span class="se">\</span> |
772 | | -<span class="w"> </span>-v<span class="w"> </span>./Caddyfile:/etc/caddy/Caddyfile<span class="w"> </span><span class="se">\</span> |
773 | | -<span class="w"> </span>-v<span class="w"> </span>caddy_data:/data<span class="w"> </span><span class="se">\</span> |
774 | | -<span class="w"> </span>--network<span class="w"> </span>blue_default<span class="w"> </span><span class="se">\</span> |
775 | | -<span class="w"> </span>--network<span class="w"> </span>green_default<span class="w"> </span><span class="se">\</span> |
776 | | -<span class="w"> </span>caddy:2 |
777 | | -</code></pre></div> |
778 | | -<h3 id="4-deploying">4. Deploying</h3> |
779 | | -<p>Update the idle stack:</p> |
780 | | -<div class="highlight"><pre><span></span><code>docker<span class="w"> </span>compose<span class="w"> </span>pull |
781 | | -docker<span class="w"> </span>compose<span class="w"> </span>-p<span class="w"> </span>green<span class="w"> </span>up<span class="w"> </span>-d |
782 | | -</code></pre></div> |
783 | | -<p>Edit the front proxy's config to flip traffic:</p> |
784 | | -<div class="highlight"><span class="filename">Caddyfile</span><pre><span></span><code>api.myapp.com reverse_proxy green_caddy:80 |
785 | | -next.myapp.com reverse_proxy blue_caddy:80 |
786 | | -</code></pre></div> |
787 | | -<p>Restart Caddy:</p> |
788 | | -<div class="highlight"><pre><span></span><code>docker<span class="w"> </span><span class="nb">exec</span><span class="w"> </span>front-proxy<span class="w"> </span>caddy<span class="w"> </span>reload |
789 | | -</code></pre></div> |
790 | | -<p>Cutover is instant. Green is now live, and Blue is the idle stack.</p> |
791 | | -<p>And rollback is simple: flip the <code>Caddyfile</code> back and <code>caddy reload</code>.</p> |
792 | 647 |
|
793 | 648 |
|
794 | 649 |
|
|
0 commit comments