Skip to content

Commit 86e5136

Browse files
Improve Docker setup
- Add better explanation on how to run the signaling server yourself. - Improve temporary postgres setup
1 parent 421e0ef commit 86e5136

4 files changed

Lines changed: 52 additions & 11 deletions

File tree

README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,21 @@ UDP Transport
122122

123123
While Poki provides hosted STUN/TURN and signaling services for free, you can also self-host these components:
124124

125-
1. Set up your own signaling server using the provided Docker image
126-
2. Configure your own STUN/TURN servers
127-
3. Initialize the network with custom endpoints:
125+
1. Set up your own signaling server
126+
127+
Using the provided Docker image:
128+
```sh
129+
$ docker build -t netlib .
130+
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 -e ENV=local netlib
131+
```
132+
Or by running the signaling server binary directly:
133+
```sh
134+
$ go build -o signaling cmd/signaling/main.go
135+
$ ENV=local ./signaling
136+
```
137+
2. For persistent storage remove `ENV=local` and set `DATABASE_URL` to your PostgreSQL database URL.
138+
3. Configure your own STUN/TURN servers.
139+
4. Initialize the network with custom endpoints:
128140
```js
129141
const network = new Network('<game-id>', {
130142
signalingServer: 'wss://your-server.com',

cmd/signaling/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/poki/netlib/internal/util"
1919
"github.com/rs/cors"
2020
"go.uber.org/zap"
21+
"go.uber.org/zap/zapcore"
2122
)
2223

2324
func main() {
@@ -32,7 +33,9 @@ func main() {
3233

3334
store, flushed, err := stores.FromEnv(ctx)
3435
if err != nil {
35-
logger.Panic("failed setup store", zap.Error(err))
36+
// Don't print a stacktrace here, it's confusing for users.
37+
logger.WithOptions(zap.AddStacktrace(zapcore.InvalidLevel)).Error("failed to setup store", zap.Error(err))
38+
return
3639
}
3740

3841
if os.Getenv("ENV") == "local" || os.Getenv("ENV") == "test" {

internal/signaling/stores/postgres.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -624,10 +624,7 @@ func (s *PostgresStore) DoLeaderElection(ctx context.Context, gameID, lobbyCode
624624
return nil, err
625625
}
626626

627-
needNewLeader := false
628-
if currentLeader == "" {
629-
needNewLeader = true
630-
}
627+
needNewLeader := currentLeader == ""
631628

632629
if !needNewLeader {
633630
found := slices.Contains(peers, currentLeader)

internal/signaling/stores/setup.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package stores
22

33
import (
4+
"bytes"
45
"context"
56
"fmt"
7+
"net"
68
"os"
9+
"strings"
710
"time"
811

912
"github.com/jackc/pgx/v5/pgxpool"
@@ -31,7 +34,7 @@ func FromEnv(ctx context.Context) (Store, chan struct{}, error) {
3134
}
3235
return store, nil, nil
3336

34-
} else if _, hasDocker := os.LookupEnv("DOCKER_HOST"); hasDocker {
37+
} else if os.Getenv("ENV") == "local" || os.Getenv("ENV") == "test" {
3538
pool, err := dockertest.NewPool("")
3639
if err != nil {
3740
return nil, nil, err
@@ -66,7 +69,17 @@ func FromEnv(ctx context.Context) (Store, chan struct{}, error) {
6669
return nil, nil, err
6770
}
6871
}
69-
databaseUrl := fmt.Sprintf("postgres://test:test@%s/test?sslmode=disable", resource.GetHostPort("5432/tcp"))
72+
73+
hostPort := resource.GetHostPort("5432/tcp")
74+
75+
// If we are running in Docker, we need to replace localhost with host.docker.internal.
76+
// This allows us to connect to the postgres dockertest just started inside our container.
77+
// localhost will not work in this case as it refers to the container itself.
78+
if runningInDocker() {
79+
hostPort = strings.ReplaceAll(hostPort, "localhost", "host.docker.internal")
80+
}
81+
82+
databaseUrl := fmt.Sprintf("postgres://test:test@%s/test?sslmode=disable", hostPort)
7083

7184
// This log message is used by the test suite to pass the database URL to the testproxy.
7285
logger.Info("using database", zap.String("url", databaseUrl))
@@ -95,5 +108,21 @@ func FromEnv(ctx context.Context) (Store, chan struct{}, error) {
95108
}
96109
return store, flushed, nil
97110
}
98-
return nil, nil, fmt.Errorf("no database configured export DATABASE_URL or DOCKER_HOST to run locally")
111+
return nil, nil, fmt.Errorf("no database configured, set DATABASE_URL in production, or ENV=local to automatically start a temporary database")
112+
}
113+
114+
// runningInDocker returns true if the code is running inside a Docker container.
115+
func runningInDocker() bool {
116+
if _, err := os.Stat("/.dockerenv"); err == nil {
117+
return true
118+
}
119+
120+
if b, err := os.ReadFile("/proc/1/cgroup"); err == nil {
121+
return bytes.Contains(b, []byte("docker")) ||
122+
bytes.Contains(b, []byte("kubepods")) ||
123+
bytes.Contains(b, []byte("containerd"))
124+
}
125+
126+
_, err := net.LookupHost("host.docker.internal")
127+
return err == nil
99128
}

0 commit comments

Comments
 (0)