-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
127 lines (122 loc) · 4.83 KB
/
Copy pathdocker-compose.yml
File metadata and controls
127 lines (122 loc) · 4.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# Full local stack: Postgres + Go control plane + nginx-served frontend.
#
# docker compose up --build
#
# Then browse http://localhost:8080 (the frontend proxies /api to the server).
# The server is also exposed directly on :8081 for debugging.
name: craftling
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: craftling
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d craftling"]
interval: 5s
timeout: 3s
retries: 10
server:
build:
context: .
environment:
PORT: "8080"
APP_ENV: production
DATABASE_URL: postgres://postgres:postgres@db:5432/craftling?sslmode=disable
JWT_SECRET: dev-secret-change-me
ACCESS_TTL: 15m
REFRESH_TTL: 720h
# Seed an admin (operator/fleet-wide view) on first start.
ADMIN_EMAIL: admin@craftling.gg
ADMIN_PASSWORD: adminpassword
ports:
- "8082:8080"
# The gRPC AgentLink listener (default :8090). Published to the host so the
# agent — which runs with host networking for the eBPF NAT dataplane and
# thus can't use compose DNS — can dial it at 127.0.0.1:8090.
- "8090:8090"
depends_on:
db:
condition: service_healthy
restart: unless-stopped
frontend:
build:
context: ./frontend
environment:
API_UPSTREAM: http://server:8080
ports:
- "8081:80"
depends_on:
- server
restart: unless-stopped
# Host agent with the real Firecracker driver — local testing only.
# Needs /dev/kvm and elevated privileges to create TAP devices and load the
# eBPF NAT, so it runs privileged. You must supply a vmlinux kernel under
# ./fc-assets; rootfs images are converted from OCI on demand (see
# FC_IMAGE_REF) and cached under FC_IMAGE_CACHE_DIR. e.g.:
# ./fc-assets/vmlinux
agent:
build:
context: .
dockerfile: Dockerfile.agent
environment:
MODE: agent
APP_ENV: production
# The agent dials this and holds a stream open; the control plane pushes VM
# commands down it. No inbound address is advertised — the control plane
# never dials the agent. With host networking (below) compose DNS is
# unavailable, so reach the server via its host-published gRPC port.
CONTROL_PLANE_GRPC_ADDR: 127.0.0.1:8090
# Player-facing connect host VMs report (override for real connectivity).
ADVERTISE_HOST: 127.0.0.1
AGENT_RUNTIME: firecracker
FC_BINARY: /usr/local/bin/firecracker
FC_KERNEL: /var/lib/craftling/vmlinux
# OCI image converted to a read-only squashfs rootfs per server. A
# "{version}" placeholder is substituted with the server's version; a ref
# without it (as here) is used verbatim. The init binary is injected by
# the converter (baked into the agent image, see Dockerfile.agent).
FC_IMAGE_REF: docker.io/itzg/minecraft-server:java21
# Where converted, content-addressed squashfs rootfs files are cached.
FC_IMAGE_CACHE_DIR: /var/lib/craftling/images
FC_WORK_DIR: /var/lib/craftling/work
# Give each VM a writable ext4 world disk overlaid on the workload's data
# dir (/data for itzg/minecraft-server). Without it the only filesystem is
# the read-only squashfs rootfs, so the server can't even write eula.txt
# and exits, halting the VM. Disk defaults to 4 GiB under FC_WORK_DIR/worlds.
FC_WORLD_PERSIST: "true"
FC_WORLD_STORE_DIR: "/var/lib/craftling/worlds"
# NIC the eBPF NAT dataplane attaches to. Setting it gives each server a
# distinct public host port from the FC_HOST_PORT_MIN–FC_HOST_PORT_MAX
# pool; without it every VM falls back to 25565 and servers on this host
# collide on the same port. Set to the host's real egress interface.
FC_UPLINK: ens16
# Optional NAT overrides (driver defaults shown):
# FC_VM_SUBNET: 10.222.0.0/16
# FC_HOST_PORT_MIN: "30000"
# FC_HOST_PORT_MAX: "40000"
FC_RCON_PORT: "25575"
FC_SNAPSHOT_INTERVAL: "25m"
devices:
# Mount KVM so Firecracker can boot microVMs.
- "/dev/kvm:/dev/kvm"
privileged: true
# The eBPF NAT dataplane attaches TCX programs to the host egress NIC
# (FC_UPLINK, e.g. ens16) and creates TAP devices, all of which must live in
# the host network namespace. On the compose bridge the container only sees
# lo/eth0 and FC_UPLINK resolves to "no such network interface".
network_mode: host
volumes:
- ./fc-assets:/var/lib/craftling
# No published ports: the agent serves no inbound API. It reaches the control
# plane's gRPC link at server:8090 over the compose network.
depends_on:
- server
restart: unless-stopped
volumes:
pgdata: