1- The standard SuperStack has a single app, and it's upgraded in place.
1+ # ⚙️ Advanced Deployments
22
3- - There's potentially some downtime while upgrading.
4- - Once an app is upgraded, you can't rollback.
5- - You can't test one app while another is live (blue/green)
3+ By default, SuperStack runs as a ** single project** that's upgraded in place.
64
7- When your app is ready for production, consider adding a traffic-switcher in
8- front of your app.
5+ While this is simple, it has some trade-offs:
96
10- Here's how it works:
7+ - Some downtime during upgrades
8+ - No way to test a new version while another is live (blue/green)
9+ - No quick rollback once upgraded
1110
12- - We stop exposing ports in the ` app ` project.
13- - A new ` proxy ` service is added with ports open.
14- - It's purpose is to direct traffic to the right application. (it also takes
15- over TLS termination)
16- - Rather than upgrading the single app, new apps containers are brought up,
17- separate to the live one, and they connect to the proxy's network.
18- - Test the new app before it goes live.
19- - Finally traffic is flipped to the new app.
11+ When your app is ready for production, consider adding a ** traffic-switcher**
12+ in front it.
2013
21- This way, environments are _ ephemeral, immutable and idempotent_ .
14+ ## 🧭 How It Works
15+
16+ Instead of directly exposing ports from the app, you add a small proxy project
17+ that sits in front of it.
18+
19+ The proxy’s job is to:
20+
21+ - Route incoming traffic to the active app stack
22+ - Make it easy to flip traffic between app versions
23+ - Terminate TLS
2224
2325``` mermaid
2426flowchart TD
25- Proxy["<b>Proxy</b><br><i>Used for traffic shifting</i> "]
26- Proxy --> App["<b>Application</b><br><i>API Gateway, Auth, APIs, Messaging, Workers, etc.</i> "]
27- App --> Database["<b>Database</b><br><i>Optional</i> "]
27+ Proxy["Traffic Router "]
28+ Proxy --> LiveApp["Live App "]
29+ NextApp["Next App "]
2830```
2931
32+ ## 🔄 Deployment Flow
33+
34+ 1 . Stop exposing ports in the app project — only the proxy will listen on :80 and :443.
35+ 2 . Add a proxy project that runs Caddy (or another gateway).
36+ 3 . Each time you deploy, bring up a new app stack, connected to the proxy’s
37+ network.
38+ 4 . Test the new stack while the old one is still live.
39+ 5 . Flip traffic in the proxy to point to the new stack.
40+ 6 . Tear down the old one when ready.
41+
42+ Ok, we need to make some changes to the repository.
43+
3044## 1. Adjust the Application
3145
3246Remove the app's exposed ports, and connect to the proxy's network:
3347
34- ``` yaml title="app/compose.yaml" hl_lines="6 -11, 13-15"
48+ ``` yaml title="app/compose.yaml" hl_lines="5 -11 13-15"
3549services :
3650 caddy :
3751 build :
@@ -51,26 +65,26 @@ networks:
5165
5266What's changed?
5367
54- 1. The exposed ` ports` were removed.
55- 2 . Caddy's site address has changed to `:80` (The application layer no longer
68+ 1. The exposed ports were removed.
69+ 1 . Caddy's site address has changed to ` :80` (The application layer no longer
5670 handles TLS).
57- 3 . We connect to the proxy's network, so the proxy can direct traffic to the
71+ 1 . We connect to the proxy's network, so the proxy can direct traffic to the
5872 app.
59- 4 . A container alias was added. This alias allows the proxy to target this
73+ 1 . A container alias was added. This alias allows the proxy to target this
6074 container, while still allowing Docker to manage the container name.
6175
62- Additionally, the `CADDY_SITE_ADDRESS` env var can be removed from the
63- development override file.
76+ The `CADDY_SITE_ADDRESS` environment variable can be removed from the override
77+ file.
6478
65- # # 2. Create a new `proxy` project
79+ # # 2. Start a new `proxy` project
6680
6781From the root of the repository, create a new `proxy` project :
6882
6983` ` ` sh
7084mkdir proxy
7185` ` `
7286
73- Add a compose file :
87+ Give it a Compose file :
7488
7589` ` ` yaml title="proxy/compose.yaml"
7690services:
@@ -87,9 +101,11 @@ services:
87101
88102volumes:
89103 caddy_data:
90- name: caddy-data # The proxy manages TLS, so give it a persistent volume for certificates
104+ name: caddy-data # Persistent volume for certificates
91105` ` `
92106
107+ Add development overrides :
108+
93109` ` ` yaml title="proxy/compose.override.yaml"
94110# Development overrides
95111
@@ -101,15 +117,36 @@ services:
101117 CADDY_SITE_ADDRESS: :80
102118` ` `
103119
120+ Configure Caddy :
121+
122+ ` ` ` sh
123+ mkdir proxy/caddy
124+ ` ` `
125+
104126` ` ` yaml title="proxy/caddy/Caddyfile"
105127{$CADDY_SITE_ADDRESS}
106128
107129reverse_proxy app_caddy:80
108130` ` `
109131
110- # # Deployment
132+ Add a Dockerfile :
133+
134+ ` ` ` dockerfile title="proxy/caddy/Dockerfile"
135+ FROM caddy:2
136+
137+ COPY Caddyfile /etc/caddy/Caddyfile
138+ ` ` `
139+
140+ # # Start the services
111141
112- The directory structure looks like :
142+ Start the proxy first, then the app which connects to its network.
143+
144+ ` ` ` yaml
145+ cd proxy && docker compose up -d
146+ cd ../app && docker compose up -d
147+ ` ` `
148+
149+ # # Deploying
113150
114151```
115152proxy/
@@ -123,17 +160,15 @@ app/
123160 .env
124161```
125162
126- # # Deploy the Proxy
127-
128- The proxy is only deployed once.
163+ The proxy is deployed once.
129164
130165On the server, create a proxy directory:
131166
132167```sh
133168mkdir proxy
134169```
135170
136- Back on local, copy your Compose file to the server :
171+ Copy your Compose file to the server:
137172
138173``` sh
139174scp proxy/compose.yaml app-backend:proxy/
@@ -147,7 +182,7 @@ scp proxy/compose.yaml app-backend:proxy/
147182docker compose up -d
148183```
149184
150- # # Flip traffic
185+ ### Flip traffic
151186
152187``` sh
153188cd proxy
0 commit comments