Skip to content

Commit 947100b

Browse files
committed
Adjust readme
1 parent 705d93d commit 947100b

File tree

1 file changed

+105
-38
lines changed

1 file changed

+105
-38
lines changed

docs/advanced.md

Lines changed: 105 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,21 @@ While this is simple, it has some trade-offs:
88
- No way to test a new version while another is live (blue/green)
99
- No quick rollback once upgraded
1010

11-
When your app is ready for production, you can enable a traffic router to
12-
eliminate these issues.
11+
When your app is ready for production, you can enable a simple **traffic
12+
router** to eliminate these issues.
1313

1414
## 🧭 How It Works
1515

16-
The traffic router is a lightweight proxy project (already included with
17-
SuperStack) that sits in front of your app. Its responsibilities:
16+
The traffic router is a lightweight proxy already included with SuperStack that
17+
sits in front of your app. Its responsibilities:
1818

19-
- Route traffic to the active app stack
19+
- Route traffic to the correct app
2020
- Simplify switching between versions
2121
- Handle TLS termination
2222

2323
```mermaid
2424
flowchart TD
25+
FormerApp["Former App"]
2526
Proxy["Traffic Router"]
2627
Proxy --> LiveApp["Live App"]
2728
NextApp["Next App"]
@@ -30,37 +31,42 @@ flowchart TD
3031
Normally the app exposes ports directly, but in this advanced mode, the **proxy
3132
owns the ports**, and apps connect to its Docker network.
3233

33-
## 🔄 Deployment Flow
34+
## 🔄 Tasks
3435

35-
1. Enable the proxy project (included in the repository).
36-
1. Stop exposing ports in the app — only the proxy will listen on `:80` and
37-
`:443`.
38-
1. For each deployment, bring up a new app stack (e.g. `app/<commit>`),
39-
connected to the proxy’s network.
40-
1. Test the new app while the current one remains live.
41-
1. Flip traffic in the proxy to point to the new app.
42-
1. Tear down the old one when ready.
36+
1. Enable the proxy project (included in SuperStack)
37+
1. Stop exposing ports in the app
38+
1. Instead, connect to the proxy's Docker network
39+
1. The proxy will listen on `:80` and `:443`
4340

44-
## 🧱 1. Start the Proxy
41+
The application still manages api routes, auth, etc.
4542

46-
A `proxy` project already exists in your SuperStack project.
43+
## 🧱 1. Start the Proxy
4744

4845
> For consistent environments, use the proxy in all environments, including
4946
> development.
5047
48+
A `proxy` project already exists in your SuperStack project.
49+
50+
First, stop your app to release the ports:
51+
52+
```sh
53+
cd app
54+
docker compose down
55+
```
56+
5157
Start the proxy:
5258

5359
```sh
54-
cd proxy
60+
cd ../proxy
5561
docker compose up -d
5662
```
5763

5864
## ⚙️ 2. Adjust the Application
5965

60-
**Remove the `ports:` section from the app,** and connect it to the proxy's
61-
network by adding these lines:
66+
**Remove the `ports:` from the app,** and connect it to the proxy's network by
67+
adding these lines:
6268

63-
```yaml title="app/compose.yaml" hl_lines="5-11 13-15"
69+
```yaml title="app/compose.yaml" hl_lines="5-15"
6470
services:
6571
caddy:
6672
build:
@@ -78,30 +84,41 @@ networks:
7884
external: true
7985
```
8086
81-
You should also remove the `ports:` and `CADDY_SITE_ADDRESS` in
87+
Also remove the `ports:` and `CADDY_SITE_ADDRESS` in
8288
`app/compose.override.yaml`.
8389

8490
What's Changed?
8591

86-
1. Exposed ports were removed.
87-
1. `CADDY_SITE_ADDRESS` now listens internally on port `:80`.
88-
1. The app joins the proxy's network so traffic can be routed to it.
92+
1. Exposed ports were removed
93+
1. `CADDY_SITE_ADDRESS` now listens internally on port `:80`
94+
1. The app joins the proxy's network so traffic can be routed to it
8995
1. A container alias (`_caddy`) allows the proxy to target this service
90-
reliably.
96+
reliably
9197

92-
Recreate the app's Caddy container:
98+
Bring up the app:
9399

94100
```sh
95-
cd app
96-
docker compose up -d --force-recreate caddy
101+
docker compose up -d
102+
```
103+
104+
Test with:
105+
106+
```sh
107+
$ curl http://localhost:8000/healthcheck
108+
OK
97109
```
98110

99111
Commit these changes – your app is now proxy-ready.
100112

101-
## 🚀 3. Deploying
113+
## 🚀 3. Deploying to a Remote Server
114+
115+
The proxy is deployed once (usually manually). After that, each app version is
116+
deployed separately into its own directory.
102117

103-
The proxy is deployed once (usually manually), and each app is deployed
104-
separately into its own directory.
118+
1. For each deployment, bring up a new app (e.g. `app/<commit>`)
119+
1. Test the new app while the current one remains live
120+
1. Flip traffic in the proxy to point to the new app
121+
1. Tear down the old one when ready
105122

106123
```
107124
proxy/
@@ -115,6 +132,8 @@ app/
115132
.env
116133
```
117134
135+
### 1. Deploy the Proxy
136+
118137
Before deploying, build and push your own proxy image by adding an `image:`
119138
line to the Compose file:
120139
@@ -151,45 +170,93 @@ Start the proxy:
151170
docker compose up -d
152171
```
153172

154-
## 🆕 4. Deploy the New App Stack
173+
### 2. Deploy a new App version
155174

156-
Deploy your app into a new directory (e.g. `b/`):
175+
Deploy your app into a new directory (e.g. `app/b/`):
176+
177+
> Important: Give it a unique directory name every time. Here we use 'b' for
178+
> simplicity, but I recommend using the commit hash.
157179
158180
```sh
159181
mkdir app/b
160182
```
161183

184+
Copy `compose.yaml` (and secrets) there:
185+
162186
```sh
163187
scp compose.yaml yourserver:app/b/
164188
```
165189

166-
Start it on the server:
190+
Start the app on the server:
167191

168192
```sh
169193
cd app/b
170194
docker compose up -d
171195
```
172196

173-
Optionally, verify the new app is healthy before switching traffic:
197+
Verify the new app is healthy before switching traffic:
174198

175199
```sh
176200
$ docker compose exec -T caddy curl -fsS http://caddy:80/healthz
177201
OK
178202
```
179203

180-
## 🔁 5. Flip Traffic
204+
## 🔁 4. Route Traffic
205+
206+
### Option 1: Use the REST API
207+
208+
Caddy's configuration can be adjusted via HTTP using its [REST
209+
API](https://caddyserver.com/docs/api).
210+
211+
Since the app was brought up in a directory named `b`, the app's Caddy service
212+
was given the alias `b_caddy`.
213+
214+
Direct all traffic to `b_caddy`:
181215

182216
```sh
183217
cd proxy
184-
docker compose exec caddy curl -X PATCH -d '"newapp_caddy:80"' \
218+
docker compose exec caddy curl -X PATCH -d '"b_caddy:80"' \
185219
http://localhost:2019/config/apps/http/servers/srv0/routes/0/handle/0/upstreams/0/dial
186220
```
187221

188222
Traffic now points to the new stack.
189223

224+
### Option 2: Mount a Caddyfile
225+
226+
Create a simple Caddyfile on the server, such as:
227+
228+
```caddyfile title="proxy/caddy/Caddyfile"
229+
{$CADDY_SITE_ADDRESS}
230+
231+
reverse_proxy b_caddy:80
232+
```
233+
234+
Mount it into the proxy's Caddy container:
235+
236+
```yaml title="proxy/compose.yaml" hl_lines="4"
237+
services:
238+
caddy:
239+
volumes:
240+
- ./caddy:/etc/caddy
241+
```
242+
243+
Recreate the container:
244+
245+
```sh
246+
cd proxy
247+
docker compose up -d --force-recreate caddy
248+
```
249+
250+
After that, to re-route traffic, simply change the app service name in
251+
`proxy/caddy/Caddyfile` and reload the proxy's configuration:
252+
253+
```sh
254+
docker compose exec caddy caddy reload --config /etc/caddy/Caddyfile
255+
```
256+
190257
## ⚡ GitHub Actions Example
191258

192-
Use this Github Actions Workflow to automate deployments.
259+
Add this Github Actions workflow to automate deployments:
193260

194261
<details>
195262
<summary>Show full workflow</summary>

0 commit comments

Comments
 (0)