@@ -112,17 +112,23 @@ func NewCaddyfileGenerator(
112112func (g * CaddyfileGenerator ) Generate (
113113 ctx context.Context , records []store.ContainerRecord , includeCustom bool ,
114114) (string , error ) {
115+ // Sort records by local machine first, then by service name and creation time. Placing containers on the local
116+ // machine first lets user-defined Caddy configs pair this ordering with the "first" lb_policy to always send
117+ // traffic to the same-host replica (skipping the cross-machine hop) and only fall back to remote upstreams when
118+ // the local one is unhealthy.
119+ // The service name and creation time tiebreakers keep the generated Caddyfile stable across regenerations.
120+ slices .SortStableFunc (records , func (a , b store.ContainerRecord ) int {
121+ return cmp .Or (
122+ g .localMachineRank (a .MachineID )- g .localMachineRank (b .MachineID ),
123+ strings .Compare (a .Container .ServiceName (), b .Container .ServiceName ()),
124+ a .Container .CreatedTime ().Compare (b .Container .CreatedTime ()),
125+ )
126+ })
127+
115128 containers := make ([]api.ServiceContainer , len (records ))
116129 for i , cr := range records {
117130 containers [i ] = cr .Container
118131 }
119- // Sort containers by service name and creation time to generate a stable Caddyfile.
120- slices .SortStableFunc (containers , func (a , b api.ServiceContainer ) int {
121- return cmp .Or (
122- strings .Compare (a .ServiceName (), b .ServiceName ()),
123- a .CreatedTime ().Compare (b .CreatedTime ()),
124- )
125- })
126132
127133 caddyfile , err := g .generateBaseFromPorts (containers )
128134 if err != nil {
@@ -243,6 +249,15 @@ func (g *CaddyfileGenerator) Generate(
243249 return caddyfileHeader + "\n " + caddyfile , nil
244250}
245251
252+ // localMachineRank returns 0 if the given machineID matches the local machine and 1 otherwise.
253+ // Useful for sorting containers running locally first.
254+ func (g * CaddyfileGenerator ) localMachineRank (machineID string ) int {
255+ if g .machineID == machineID {
256+ return 0
257+ }
258+ return 1
259+ }
260+
246261func (g * CaddyfileGenerator ) generateBaseFromPorts (containers []api.ServiceContainer ) (string , error ) {
247262 httpHostUpstreams , httpsHostUpstreams := httpUpstreamsFromPorts (containers )
248263
0 commit comments