diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..1213a8b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +node_modules +dist +.git +.github +.idea +.claude +*.log diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..d26b91b --- /dev/null +++ b/Caddyfile @@ -0,0 +1,26 @@ +# SITE_ADDRESS is the domain list, e.g. "robotmarkets.ir, www.robotmarkets.ir" (automatic HTTPS), +# or ":80" for plain HTTP behind another proxy or for a local test. +{$SITE_ADDRESS::80} { + root * /srv + encode zstd gzip + + # Hashed build files never change; the page, service worker and manifest must always be revalidated + # so installed copies pick up new versions. + @hashed path /assets/* + header @hashed Cache-Control "public, max-age=31536000, immutable" + @fresh path / /index.html /sw.js /manifest.webmanifest + header @fresh Cache-Control "no-cache" + @manifest path /manifest.webmanifest + header @manifest Content-Type "application/manifest+json" + + header { + X-Content-Type-Options nosniff + Referrer-Policy strict-origin-when-cross-origin + # Real-world mode needs location and the compass; the camera is reserved for the AR phase. + Permissions-Policy "geolocation=(self), camera=(self), accelerometer=(self), gyroscope=(self), magnetometer=(self)" + -Server + } + + try_files {path} /index.html + file_server +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..89082be --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +# Stage 1: run the tests and build the static game with Vite. +FROM node:22-alpine AS build +WORKDIR /app +COPY package.json package-lock.json ./ +RUN npm ci --no-audit --no-fund +COPY . . +RUN node --test tests/*.test.js && npm run build + +# Stage 2: serve dist/ with Caddy, which also obtains and renews the HTTPS certificate. +FROM caddy:2.8.4-alpine +COPY Caddyfile /etc/caddy/Caddyfile +COPY --from=build /app/dist /srv +EXPOSE 80 443 443/udp diff --git a/README.md b/README.md index e24c3d1..8d6a844 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,34 @@ node --test tests/*.test.js - `?quality=low` یا دکمهٔ «گرافیک» سایه‌ها را خاموش می‌کند (پیش‌فرض گوشی‌ها). - `?debug` وضعیت بازی را در `window.game` در دسترس می‌گذارد. +## انتشار روی سرور با Docker + +تصویر Docker دو مرحله دارد: Node تست‌ها را اجرا و بازی را build می‌کند، و بعد Caddy فایل‌ها را سرو می‌کند. Caddy گواهی HTTPS را از Let's Encrypt خودکار می‌گیرد و تمدید می‌کند. HTTPS برای نصب روی گوشی و GPS ضروری است. + +**پیش‌نیاز:** +- رکورد A دامنه‌های `robotmarkets.ir` و `www.robotmarkets.ir` به IP سرور اشاره کند. +- پورت‌های ۸۰ و ۴۴۳ سرور باز و آزاد باشند. + +```sh +git clone git@github.com:hamedAbdollahzade/vending-machine-game.git && cd vending-machine-game +docker compose up -d --build +docker compose logs -f +``` + +- **دامنهٔ دیگر:** `SITE_ADDRESS="example.ir, www.example.ir" docker compose up -d --build` +- **به‌روزرسانی:** `git pull && docker compose up -d --build`. گواهی‌ها در volume `caddy_data` می‌مانند. بازی‌های نصب‌شده روی گوشی پیام نسخهٔ جدید را نشان می‌دهند. +- **اگر روی سرور از قبل Nginx یا پروکسی دیگری روی ۸۰ و ۴۴۳ هست:** در `docker-compose.yml` پورت‌ها را به `"8080:80"` تغییر دهید و `SITE_ADDRESS=":80"` بگذارید. بعد دامنه را در همان پروکسی به `127.0.0.1:8080` بفرستید. در این حالت HTTPS با همان پروکسی است. + +**سرور داخل ایران:** Docker Hub و گاهی npm به IPهای ایران سرویس نمی‌دهند. دو راه وجود دارد: +1. **mirror داخلی برای Docker Hub:** در `/etc/docker/daemon.json` یک mirror تعریف کنید، مثلاً `{"registry-mirrors": ["https://docker.arvancloud.ir"]}`، و بعد `sudo systemctl restart docker`. +2. **ساخت روی کامپیوتر خودتان و انتقال تصویر آماده:** + ```sh + docker compose build + docker save robot-market-game:latest | gzip > robot-market-game.tar.gz + scp robot-market-game.tar.gz docker-compose.yml user@server:~/game/ + ssh user@server 'cd ~/game && gunzip -c robot-market-game.tar.gz | docker load && docker compose up -d --no-build' + ``` + ## ساخت دوبارهٔ دادهٔ نقشه `src/data/mellat.json` و `src/data/iran.json` از خروجی خام OpenStreetMap (Overpass API) و Natural Earth ساخته می‌شوند. کوئری‌ها در ابتدای اسکریپت آمده‌اند: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9ca0588 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +services: + game: + build: . + image: robot-market-game:latest + restart: unless-stopped + ports: + - "80:80" + - "443:443" + - "443:443/udp" + environment: + # Point these domains' DNS A records at the server before the first start. + SITE_ADDRESS: ${SITE_ADDRESS:-robotmarkets.ir, www.robotmarkets.ir} + volumes: + # Keeps the HTTPS certificates across restarts and image updates. + - caddy_data:/data + - caddy_config:/config + +volumes: + caddy_data: + caddy_config: