Nakama/Docker Path Issues

Trying to set up a Dockerfile, docker-compose.yml, and configuration file to use the JavaScript runtime. I was able to get this set up manually however when I tried to move to Dockerfile/docker-compose the server_nakama container is unable to find files moved by the Dockerfile container.
Namely:

  • When I bind the /nakama/data relative path to ./data in the docker-compose file, neither the configuration file nor index.js can be located. The only way I found to resolve this is by manually placing the configuration file in the /data directory but this defeats the purpose of the Dockerfile instructions.
  • When I bind the /nakama/data relative path to ./ in the docker-compose file, the configuration file is found but the built index.js file is not.

I have verified through several means that both files are in fact being populated in the container during the build process but once the server_nakama container spins up they cannot be found. I’ve tried pretty much every path I could think of so I figure I must be missing something.

  1. Versions: Nakama 3.12, Linux binary or Docker
  2. Server Framework Runtime language (If relevant) TS/JS

Nakama Error

{"level":"fatal","ts":"2022-06-18T16:00:15.355Z","caller":"server/config.go:292","msg":"JavaScript entrypoint must be a valid path","error":"stat data/modules/build/index.js: no such file or directory"}

Dockerfile

FROM node:alpine AS node-builder

WORKDIR /backend

COPY package*.json ./
RUN npm install
COPY tsconfig.json ./
COPY src/*.ts ./
RUN npx tsc

FROM heroiclabs/nakama:3.12.0
COPY --from=node-builder /backend/build/*.js /nakama/data/modules/build/
COPY project-x.yml /nakama/data/

docker-compose.yml

version: '3'
services:
  cockroachdb:
    image: cockroachdb/cockroach:latest-v20.2
    command: start-single-node --insecure --store=attrs=ssd,path=/var/lib/cockroach/
    restart: "no"
    volumes:
      - data:/var/lib/cockroach
    expose:
      - "8080"
      - "26257"
    ports:
      - "26257:26257"
      - "8080:8080"
  nakama:
    build: .
    entrypoint:
      - "/bin/sh"
      - "-ecx"
      - >
        /nakama/nakama migrate up --database.address root@cockroachdb:26257 &&
        /nakama/nakama --config /nakama/data/project-x.yml        
    restart: "no"
    links:
      - "cockroachdb:db"
    depends_on:
      - cockroachdb
      - prometheus
    volumes:
      - ./:/nakama/data
    expose:
      - "7349"
      - "7350"
      - "7351"
      - "9100"
    ports:
      - "7349:7349"
      - "7350:7350"
      - "7351:7351"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7350/"]
      interval: 10s
      timeout: 5s
      retries: 5
  prometheus:
    image: prom/prometheus
    entrypoint: /bin/sh -c
    command: |
      'sh -s <<EOF
        cat > ./prometheus.yml <<EON
      global:
        scrape_interval:     15s
        evaluation_interval: 15s
      scrape_configs:
        - job_name: prometheus
          static_configs:
          - targets: ['localhost:9090']
        - job_name: nakama
          metrics_path: /
          static_configs:
          - targets: ['nakama:9100']
      EON
      prometheus --config.file=./prometheus.yml
      EOF'      
    ports:
      - '9090:9090'
volumes:
  data: 

project-x.yml

name: project-x-node-1
data_dir: "./data"

logger:
  stdout: true
  level: "debug"
  file: "./data/logs/server.log"

metrics:
  reporting_freq_sec: 60
  namespace: ""
  prometheus_port: 0

database:
  address:
  - "root@localhost:26257"
  conn_max_lifetime_ms: 0
  max_open_conns: 0
  max_idle_conns: 100

runtime:
  http_key: "defaulthttpkey"
  js_entrypoint: "build/index.js"
socket:
  server_key: "defaultserverkey"
  port: 7350
  max_message_size_bytes: 4096 # bytes
  read_timeout_ms: 10000
  write_timeout_ms: 10000
  idle_timeout_ms: 60000
  write_wait_ms: 5000
  pong_wait_ms: 10000
  ping_period_ms: 8000 # Must be less than pong_wait_ms
  outgoing_queue_size: 16

session:
  encryption_key: "definitelynotadefaultencryptionkey"
  token_expiry_sec: 60
  refresh_encryption_key: "itcouldntbeadefaultrefreshkey"
  refresh_token_expiry_sec: 3600

console:
  port: 7351
  username: "admin"
  password: "password"

cluster:
  join:
  - "10.0.0.2:7352"
  - "10.0.0.3:7352"
  gossip_bindaddr: "0.0.0.0"
  gossip_bindport: 7352
  rpc_port: 7353

matchmaker:
  max_tickets: 2
  interval_sec: 15
  max_intervals: 3

you should replace this with COPY --from=node-builder /backend/*.js /nakama/data/modules/

1 Like

Hello @khamarr3524,

I think the issue is that the assumption of the current working directory is wrong and you’re setting data_dir as a relative path.

Try the following Dockerfile:

FROM node:alpine AS node-builder

WORKDIR /backend

COPY package*.json ./
RUN npm install
COPY tsconfig.json ./
COPY src/*.ts ./
RUN npx tsc

FROM heroiclabs/nakama:3.12.0
WORKDIR /nakama
COPY --from=node-builder /backend/build/*.js /nakama/data/modules/build/
COPY project-x.yml /nakama/data/

No luck, Nakama is still unable to find the js entry point.

@khamarr3524 what operating system are you using Docker on?

@sesposito The server is running on Ubuntu 20.04.

Here is the updated files I’m using and corresponding error

Dockerfile

FROM node:alpine AS node-builder

WORKDIR /backend

COPY package*.json ./
RUN npm install
COPY tsconfig.json ./
COPY src/*.ts ./
RUN npx tsc

FROM heroiclabs/nakama:3.12.0
WORKDIR /nakama
RUN mkdir /nakama/data/modules/build/
COPY --from=node-builder /backend/build/*.js /nakama/data/modules/build/
COPY project-x.yml /nakama/data/

docker-compose.yml

version: '3'
services:
  cockroachdb:
    image: cockroachdb/cockroach:latest-v20.2
    command: start-single-node --insecure --store=attrs=ssd,path=/var/lib/cockroach/
    restart: "no"
    volumes:
      - data:/var/lib/cockroach
    expose:
      - "8080"
      - "26257"
    ports:
      - "26257:26257"
      - "8080:8080"
  nakama:
    #image: heroiclabs/nakama:3.12.0
    build: .
    entrypoint:
      - "/bin/sh"
      - "-ecx"
      - >
        /nakama/nakama migrate up --database.address root@cockroachdb:26257 &&
        /nakama/nakama --config /nakama/data/project-x.yml 
    restart: unless-stopped
    links:
      - "cockroachdb:db"
    depends_on:
      - cockroachdb
      - prometheus
    volumes:
      - ./:/nakama/data
    expose:
      - "7349"
      - "7350"
      - "7351"
      - "9100"
    ports:
      - "7349:7349"
      - "7350:7350"
      - "7351:7351"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7350/"]
      interval: 10s
      timeout: 5s
      retries: 5
  prometheus:
    image: prom/prometheus
    entrypoint: /bin/sh -c
    command: |
      'sh -s <<EOF
        cat > ./prometheus.yml <<EON
      global:
        scrape_interval:     15s
        evaluation_interval: 15s
      scrape_configs:
        - job_name: prometheus
          static_configs:
          - targets: ['localhost:9090']
        - job_name: nakama
          metrics_path: /
          static_configs:
          - targets: ['nakama:9100']
      EON
      prometheus --config.file=./prometheus.yml
      EOF'      
    ports:
      - '9090:9090'
volumes:
  data:

project-x.yml

name: project-x-node-1
#data_dir: "./data"

logger:
  stdout: true
  level: "warn"
  file: "./data/logs/server.log"

metrics:
  reporting_freq_sec: 60
  namespace: ""
  prometheus_port: 0

database:
  address:
  - "root@localhost:26257"
  conn_max_lifetime_ms: 0
  max_open_conns: 0
  max_idle_conns: 100

runtime:
  js_entrypoint: "build/index.js"

socket:
  server_key: "defaultserverkey"
  port: 7350
  max_message_size_bytes: 4096 # bytes
  read_timeout_ms: 10000
  write_timeout_ms: 10000
  idle_timeout_ms: 60000
  write_wait_ms: 5000
  pong_wait_ms: 10000
  ping_period_ms: 8000 # Must be less than pong_wait_ms
  outgoing_queue_size: 16

session:
  encryption_key: "definitelynotadefaultencryptionkey"
  token_expiry_sec: 60
  refresh_encryption_key: "itcouldntbeadefaultrefreshkey"
  refresh_token_expiry_sec: 3600

console:
  port: 7351
  username: "admin"
  password: "password"

cluster:
  join:
  - "10.0.0.2:7352"
  - "10.0.0.3:7352"
  gossip_bindaddr: "0.0.0.0"
  gossip_bindport: 7352
  rpc_port: 7353

matchmaker:
  max_tickets: 2
  interval_sec: 15
  max_intervals: 3

Nakama Output

nakama_1       | {"level":"info","ts":"2022-06-24T02:57:27.753Z","caller":"migrate/migrate.go:195","msg":"Database information","version":"CockroachDB CCL v20.2.19 (x86_64-unknown-linux-gnu, built 2022/02/09 18:48:48, go1.13.14)"}
nakama_1       | {"level":"info","ts":"2022-06-24T02:57:27.757Z","caller":"migrate/migrate.go:218","msg":"Successfully applied migration","count":0}
nakama_1       | + /nakama/nakama --config /nakama/data/project-x.yml
nakama_1       | {"level":"info","ts":"2022-06-24T02:57:27.773Z","caller":"server/config.go:86","msg":"Successfully loaded config file","path":"/nakama/data/project-x.yml"}
nakama_1       | {"level":"fatal","ts":"2022-06-24T02:57:27.775Z","caller":"server/config.go:292","msg":"JavaScript entrypoint must be a valid path","error":"stat /nakama/data/modules/build/index.js: no such file or directory"}
server_nakama_1 exited with code 1

The problem should be:

volumes:
      - ./:/nakama/data

in your docker-compose file. It is mounting your local directory at /nakama/data which is probably overwriting the files copied over from the multi-stage build. Remove the line and you should get it working.