492492 </ ul >
493493 </ nav >
494494
495+ </ li >
496+
497+ < li class ="md-nav__item ">
498+ < a href ="#3-bring-up-two-stacks " class ="md-nav__link ">
499+ < span class ="md-ellipsis ">
500+ 3. Bring up two Stacks
501+ </ span >
502+ </ a >
503+
495504</ li >
496505
497506 < li class ="md-nav__item ">
504513</ li >
505514
506515 < li class ="md-nav__item ">
507- < a href ="#4-deployingupgrading " class ="md-nav__link ">
516+ < a href ="#4-upgrading " class ="md-nav__link ">
508517 < span class ="md-ellipsis ">
509- 4. Deploying/ Upgrading
518+ 4. Upgrading
510519 </ span >
511520 </ a >
512521
513- < nav class ="md-nav " aria-label ="4. Deploying/Upgrading ">
514- < ul class ="md-nav__list ">
515-
516- < li class ="md-nav__item ">
522+ </ li >
523+
524+ < li class ="md-nav__item ">
517525 < a href ="#flip-traffic " class ="md-nav__link ">
518526 < span class ="md-ellipsis ">
519527 Flip traffic
520528 </ span >
521529 </ a >
522530
523- </ li >
524-
525- </ ul >
526- </ nav >
527-
528531</ li >
529532
530533 < li class ="md-nav__item ">
639642 </ ul >
640643 </ nav >
641644
645+ </ li >
646+
647+ < li class ="md-nav__item ">
648+ < a href ="#3-bring-up-two-stacks " class ="md-nav__link ">
649+ < span class ="md-ellipsis ">
650+ 3. Bring up two Stacks
651+ </ span >
652+ </ a >
653+
642654</ li >
643655
644656 < li class ="md-nav__item ">
651663</ li >
652664
653665 < li class ="md-nav__item ">
654- < a href ="#4-deployingupgrading " class ="md-nav__link ">
666+ < a href ="#4-upgrading " class ="md-nav__link ">
655667 < span class ="md-ellipsis ">
656- 4. Deploying/ Upgrading
668+ 4. Upgrading
657669 </ span >
658670 </ a >
659671
660- < nav class ="md-nav " aria-label ="4. Deploying/Upgrading ">
661- < ul class ="md-nav__list ">
662-
663- < li class ="md-nav__item ">
672+ </ li >
673+
674+ < li class ="md-nav__item ">
664675 < a href ="#flip-traffic " class ="md-nav__link ">
665676 < span class ="md-ellipsis ">
666677 Flip traffic
667678 </ span >
668679 </ a >
669680
670- </ li >
671-
672- </ ul >
673- </ nav >
674-
675681</ li >
676682
677683 < li class ="md-nav__item ">
@@ -710,9 +716,9 @@ <h1>Blue/Green Deployments</h1>
710716< p > < img alt ="Blue/Green " src ="../assets/bluegreen.png " /> </ p >
711717< h2 id ="1-adjust-the-compose-file "> 1. Adjust the Compose file</ h2 >
712718< h3 id ="remove-exposed-ports "> Remove exposed ports</ h3 >
719+ < p > Remove the < code > caddy</ code > service's < code > ports:</ code > section in < code > compose.yaml</ code > .</ p >
713720< p > We'll no longer expose ports in the stacks, instead a simple "front proxy" will
714- sit in front of the two stacks, exposing ports and proxying to the active
715- stack. So remove the Caddy service's < code > ports:</ code > section in < code > compose.yaml</ code > .</ p >
721+ sit in front of the two stacks, proxying to the active stack.</ p >
716722< h3 id ="set-the-caddy-container-name-explicitly "> Set the Caddy container name explicitly</ h3 >
717723< p > This allows us to switch between the two stacks:</ p >
718724< div class ="highlight "> < span class ="filename "> compose.yaml</ span > < pre > < span > </ span > < code > < span class ="nt "> caddy</ span > < span class ="p "> :</ span >
@@ -734,11 +740,26 @@ <h3 id="share-volumes-between-the-stacks">Share volumes between the stacks</h3>
734740< span class ="w "> </ span > < span class ="nt "> user_data</ span > < span class ="p "> :</ span >
735741< 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 >
736742</ code > </ pre > </ div >
743+ < h2 id ="3-bring-up-two-stacks "> 3. Bring up two Stacks</ h2 >
744+ < p > Deploying is the same as < a href ="../deploying/ "> before</ a > , but now we're deploying the
745+ < em > idle stack</ em > . For this example, < code > green</ code > is idle so that's the one we're
746+ deploying.</ p >
747+ < p > Create < code > blue</ code > and < code > green</ code > directories on the server and copy < code > compose.yaml</ code >
748+ into the idle stack's directory:</ p >
749+ < div class ="highlight "> < pre > < span > </ span > < code > scp< span class ="w "> </ span > compose.yaml< span class ="w "> </ span > youruser@yourserver:green/compose.yaml
750+ </ code > </ pre > </ div >
751+ < p > Shell into the server and bring up the idle stack:</ p >
752+ < div class ="highlight "> < pre > < span > </ span > < code > < span class ="nb "> cd</ span > < span class ="w "> </ span > green
753+ docker< span class ="w "> </ span > compose< span class ="w "> </ span > pull
754+ docker< span class ="w "> </ span > compose< span class ="w "> </ span > up< span class ="w "> </ span > -d
755+ </ code > </ pre > </ div >
756+ < p > Docker will use the directory name < code > green</ code > as the project name, creating
757+ different containers, volumes and networks than the < code > blue</ code > stack.</ p >
737758< h2 id ="3-add-a-front-proxy "> 3. Add a Front Proxy</ h2 >
738759< p > The < em > front proxy</ em > is a single container that binds ports < code > 80</ code > and < code > 443</ code > on the
739760server and routes requests into either the Blue or Green stack.</ p >
740761< p > On the server, create a simple < code > Caddyfile</ code > :</ p >
741- < div class ="highlight "> < span class ="filename "> Caddyfile</ span > < pre > < span > </ span > < code > api.myapp.com {
762+ < div class ="highlight "> < span class ="filename "> caddy/ Caddyfile</ span > < pre > < span > </ span > < code > api.myapp.com {
742763 reverse_proxy blue_caddy:80
743764}
744765</ code > </ pre > </ div >
@@ -751,28 +772,14 @@ <h2 id="3-add-a-front-proxy">3. Add a Front Proxy</h2>
751772< 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 >
752773< span class ="w "> </ span > --name< span class ="w "> </ span > front-proxy< span class ="w "> </ span > < span class ="se "> \</ span >
753774< 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 >
754- < span class ="w "> </ span > -v< span class ="w "> </ span > ./Caddyfile :/etc/caddy/Caddyfile < span class ="w "> </ span > < span class ="se "> \</ span >
775+ < span class ="w "> </ span > -v< span class ="w "> </ span > ./caddy :/etc/caddy< span class ="w "> </ span > < span class ="se "> \</ span >
755776< span class ="w "> </ span > -v< span class ="w "> </ span > caddy_data:/data< span class ="w "> </ span > < span class ="se "> \</ span >
756777< span class ="w "> </ span > --network< span class ="w "> </ span > blue_default< span class ="w "> </ span > < span class ="se "> \</ span >
757778< span class ="w "> </ span > --network< span class ="w "> </ span > green_default< span class ="w "> </ span > < span class ="se "> \</ span >
758779< span class ="w "> </ span > caddy:2
759780</ code > </ pre > </ div >
760- < h2 id ="4-deployingupgrading "> 4. Deploying/Upgrading</ h2 >
761- < p > Deploying is the same as < a href ="../deploying/ "> before</ a > , but now we're deploying the
762- < em > idle stack</ em > . For this example, < code > green</ code > is idle so that's the one we're
763- deploying.</ p >
764- < p > Create < code > blue</ code > and < code > green</ code > directories on the server and copy < code > compose.yaml</ code >
765- into the idle stack's directory:</ p >
766- < div class ="highlight "> < pre > < span > </ span > < code > scp< span class ="w "> </ span > compose.yaml< span class ="w "> </ span > youruser@yourserver:green/compose.yaml
767- </ code > </ pre > </ div >
768- < p > Shell into the server and bring up the idle stack:</ p >
769- < div class ="highlight "> < pre > < span > </ span > < code > < span class ="nb "> cd</ span > < span class ="w "> </ span > green
770- docker< span class ="w "> </ span > compose< span class ="w "> </ span > pull
771- docker< span class ="w "> </ span > compose< span class ="w "> </ span > up< span class ="w "> </ span > -d
772- </ code > </ pre > </ div >
773- < p > Docker will use the directory name < code > green</ code > as the project name, creating
774- different containers, volumes and networks than the < code > blue</ code > stack.</ p >
775- < h3 id ="flip-traffic "> Flip traffic</ h3 >
781+ < h2 id ="4-upgrading "> 4. Upgrading</ h2 >
782+ < h2 id ="flip-traffic "> Flip traffic</ h2 >
776783< p > Point traffic to the < code > green</ code > stack:</ p >
777784< div class ="highlight "> < span class ="filename "> Caddyfile</ span > < pre > < span > </ span > < code > api.myapp.com {
778785 reverse_proxy green_caddy:80
@@ -788,7 +795,7 @@ <h2 id="github-actions">Github Actions</h2>
788795< details >
789796< summary > Click to expand</ summary >
790797
791- < div class ="highlight "> < span class ="filename "> .github/workflows/ci.yaml</ span > < pre > < span > </ span > < code > < span class ="nt "> name</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> Deploy to VPS </ span >
798+ < div class ="highlight "> < span class ="filename "> .github/workflows/ci.yaml</ span > < pre > < span > </ span > < code > < span class ="nt "> name</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> Deploy</ span >
792799
793800< span class ="nt "> on</ span > < span class ="p "> :</ span >
794801< span class ="w "> </ span > < span class ="nt "> push</ span > < span class ="p "> :</ span >
@@ -798,8 +805,6 @@ <h2 id="github-actions">Github Actions</h2>
798805< span class ="nt "> jobs</ span > < span class ="p "> :</ span >
799806< span class ="w "> </ span > < span class ="nt "> deploy</ span > < span class ="p "> :</ span >
800807< span class ="w "> </ span > < span class ="nt "> runs-on</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> ubuntu-latest</ span >
801- < span class ="w "> </ span > < span class ="nt "> environment</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> production</ span >
802-
803808< span class ="w "> </ span > < span class ="nt "> steps</ span > < span class ="p "> :</ span >
804809< span class ="w "> </ span > < span class ="p p-Indicator "> -</ span > < 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 "> Checkout code</ span >
805810< span class ="w "> </ span > < span class ="nt "> uses</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> actions/checkout@v4</ span >
@@ -833,28 +838,22 @@ <h2 id="github-actions">Github Actions</h2>
833838< span class ="w "> </ span > < span class ="nt "> source</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="s "> "compose.yaml"</ span >
834839< span class ="w "> </ span > < span class ="nt "> target</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="s "> "${{</ span > < span class ="nv "> </ span > < span class ="s "> steps.idle.outputs.IDLE</ span > < span class ="nv "> </ span > < span class ="s "> }}/"</ span >
835840
836- < span class ="w "> </ span > < span class ="p p-Indicator "> -</ span > < 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 "> Deploy with Docker Compose </ span >
841+ < span class ="w "> </ span > < span class ="p p-Indicator "> -</ span > < 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 "> Deploy idle stack </ span >
837842< span class ="w "> </ span > < span class ="nt "> uses</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> appleboy/ssh-action@v1.0.3</ span >
838843< span class ="w "> </ span > < span class ="nt "> with</ span > < span class ="p "> :</ span >
839844< span class ="w "> </ span > < span class ="nt "> host</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> ${{ secrets.VPS_HOST }}</ span >
840845< span class ="w "> </ span > < span class ="nt "> username</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> ${{ secrets.VPS_USER }}</ span >
841846< span class ="w "> </ span > < span class ="nt "> key</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> ${{ secrets.VPS_SSH_KEY }}</ span >
842- < span class ="w "> </ span > < span class ="nt "> envs</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> GHCR_PAT,JWT_SECRET,POSTGRES_USER,PGUSER,POSTGRES_PASSWORD,PGPASS,PGRST_AUTHENTICATOR_PASS </ span >
847+ < span class ="w "> </ span > < span class ="nt "> envs</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> GHCR_PAT</ span >
843848< span class ="w "> </ span > < span class ="nt "> script</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="p p-Indicator "> |</ span >
844849< span class ="w "> </ span > < span class ="no "> set -euo pipefail</ span >
845- < span class ="w "> </ span > < span class ="no "> echo $GHCR_PAT | docker login ghcr.io -u $ {{ github.actor }} --password-stdin </ span >
850+ < span class ="w "> </ span > < span class ="no "> echo "$ {{ steps.idle.outputs.ACTIVE }}" > active_stack </ span >
846851< span class ="w "> </ span > < span class ="no "> cd ${{ steps.idle.outputs.IDLE }}</ span >
847- < span class ="w "> </ span > < span class ="no "> docker compose pull -q</ span >
852+ < span class ="w "> </ span > < span class ="no "> echo "$GHCR_PAT" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin</ span >
853+ < span class ="w "> </ span > < span class ="no "> DOCKER_CLIENT_TIMEOUT=300 COMPOSE_HTTP_TIMEOUT=300 docker compose pull -q</ span >
848854< span class ="w "> </ span > < span class ="no "> STACK_NAME=${{ steps.idle.outputs.IDLE }} docker compose up -d</ span >
849- < span class ="w "> </ span > < span class ="no "> echo "${{ steps.idle.outputs.ACTIVE }}" > active_stack</ span >
850855< span class ="w "> </ span > < span class ="nt "> env</ span > < span class ="p "> :</ span >
851856< span class ="w "> </ span > < span class ="nt "> GHCR_PAT</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> ${{ secrets.GHCR_PAT }}</ span >
852- < span class ="w "> </ span > < span class ="nt "> JWT_SECRET</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> ${{ secrets.JWT_SECRET }}</ span >
853- < span class ="w "> </ span > < span class ="nt "> PGRST_AUTHENTICATOR_PASS</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> ${{ secrets.PGRST_AUTHENTICATOR_PASS }}</ span >
854- < span class ="w "> </ span > < span class ="nt "> PGUSER</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> ${{ secrets.PGUSER }}</ span >
855- < span class ="w "> </ span > < span class ="nt "> PGPASS</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> ${{ secrets.PGPASS }}</ span >
856- < span class ="w "> </ span > < span class ="nt "> POSTGRES_USER</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> ${{ secrets.POSTGRES_USER }}</ span >
857- < span class ="w "> </ span > < span class ="nt "> POSTGRES_PASSWORD</ span > < span class ="p "> :</ span > < span class ="w "> </ span > < span class ="l l-Scalar l-Scalar-Plain "> ${{ secrets.POSTGRES_PASSWORD }}</ span >
858857</ code > </ pre > </ div >
859858
860859</ details >
0 commit comments