From 366847e1bd916aee945d566d305a85396dd0f55c Mon Sep 17 00:00:00 2001 From: Thibaud Date: Thu, 19 Feb 2026 13:02:50 +0100 Subject: [PATCH] feat: containerize server with Docker --- .github/workflows/main.yml | 1 + .gitignore | 1 + Dockerfile | 15 +++++++++++++++ client.ts | 13 ++++++++----- config.js | 4 ++++ docker-compose.yml | 8 ++++++++ index.html | 1 + nginx.conf.example | 37 +++++++++++++++++++++++++++++++++++++ 8 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 Dockerfile create mode 100644 config.js create mode 100644 docker-compose.yml create mode 100644 nginx.conf.example diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 443436e..b7bc74e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,6 +19,7 @@ jobs: mkdir dist mv *.js dist/ mv *.html dist/ + mv config.js dist/ - name: Setup Pages id: pages uses: actions/configure-pages@v5 diff --git a/.gitignore b/.gitignore index f5f2ba6..c2bcba8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ *.js +!config.js diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c562a26 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM node:20-alpine AS builder +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npx tsc + +FROM node:20-alpine +WORKDIR /app +COPY --from=builder /app/package*.json ./ +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/server.js ./ +COPY --from=builder /app/common.js ./ +EXPOSE 1234 +CMD ["node", "server.js"] diff --git a/client.ts b/client.ts index f7d919b..5534569 100644 --- a/client.ts +++ b/client.ts @@ -1,13 +1,16 @@ import type { Click, Update, Message, Hello, EndGame, Spectate } from "common.js"; -const ANIMATE_DURATION = 500; // ms +declare global { + interface Window { + TIC_TAC_TOE_CONFIG?: { WS_URL?: string }; + } +} + +const ANIMATE_DURATION = 500; const GRID_PADDING = 10; const MESSAGE_PADDING = 20; -let address = "ws://localhost:1234"; -if (window.location.hostname !== "localhost") { - address = "wss://tic-tac-toe-ws-production.up.railway.app"; -} +const address = window.TIC_TAC_TOE_CONFIG?.WS_URL || "ws://localhost:1234"; const ws = new WebSocket(address); interface Point { diff --git a/config.js b/config.js new file mode 100644 index 0000000..5bf7b0f --- /dev/null +++ b/config.js @@ -0,0 +1,4 @@ +window.TIC_TAC_TOE_CONFIG = { + // Set WS_URL to your production WebSocket URL, e.g.: + // WS_URL: "wss://your-domain.com/ws" +}; diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b9a86bd --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +services: + server: + build: . + restart: unless-stopped + ports: + - "127.0.0.1:1234:1234" + environment: + - NODE_ENV=production diff --git a/index.html b/index.html index 0522e81..003716c 100644 --- a/index.html +++ b/index.html @@ -8,5 +8,6 @@ + diff --git a/nginx.conf.example b/nginx.conf.example new file mode 100644 index 0000000..cec9caf --- /dev/null +++ b/nginx.conf.example @@ -0,0 +1,37 @@ +# Example nginx configuration for WebSocket reverse proxy with HTTPS +# Place this in /etc/nginx/sites-available/your-domain.com +# Then symlink to /etc/nginx/sites-enabled/ + +server { + listen 443 ssl http2; + server_name your-domain.com; + + # SSL certificates (Let's Encrypt) + ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; + + # SSL settings + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; + + # WebSocket endpoint + location /ws { + proxy_pass http://127.0.0.1:1234; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 86400; + } +} + +# Redirect HTTP to HTTPS +server { + listen 80; + server_name your-domain.com; + return 301 https://$server_name$request_uri; +}