diff --git a/backend/Dockerfile b/backend/Dockerfile index f262e0b..3a530b7 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -4,10 +4,12 @@ WORKDIR /app COPY package*.json ./ -RUN npm install --legacy-peer-deps +RUN npm ci --legacy-peer-deps COPY . . +RUN npm run build && npm prune --omit=dev + EXPOSE 5000 -CMD ["npm", "run", "dev"] +CMD ["npm", "run", "start"] diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 778fcb2..e933977 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -39,12 +39,6 @@ services: depends_on: postgres: condition: service_healthy - command: > - sh -c "npm install --legacy-peer-deps && - npm run dev" - volumes: - - ./backend:/app - - ./backend/node_modules:/app/node_modules labels: - traefik.enable=true - traefik.docker.network=${TRAEFIK_NETWORK:-traefik} @@ -59,27 +53,23 @@ services: frontend: build: context: ./frontend - dockerfile: Dockerfile.dev + dockerfile: Dockerfile + args: + VITE_API_BASE_URL: ${VITE_API_BASE_URL:-https://api.arsenal.example.com/api} + VITE_ALLOW_REGISTRATION: ${ALLOW_REGISTRATION:-true} + VITE_ALLOW_DEMO_ACCOUNT: ${ALLOW_DEMO_ACCOUNT:-false} container_name: arsenaliq-frontend environment: - VITE_API_BASE_URL: ${VITE_API_BASE_URL:-https://api.arsenal.example.com/api} - VITE_ALLOW_REGISTRATION: ${ALLOW_REGISTRATION:-true} - VITE_ALLOW_DEMO_ACCOUNT: ${ALLOW_DEMO_ACCOUNT:-false} + CSP_CONNECT_SRC: ${FRONTEND_CSP_CONNECT_SRC:-https://api.arsenal.example.com} depends_on: - backend - command: > - sh -c "npm install --legacy-peer-deps && - npm run dev -- --host" - volumes: - - ./frontend:/app - - ./frontend/node_modules:/app/node_modules labels: - traefik.enable=true - traefik.docker.network=${TRAEFIK_NETWORK:-traefik} - traefik.http.routers.arsenaliq-web.rule=Host(`${TRAEFIK_WEB_HOST:-arsenal.local}`) - traefik.http.routers.arsenaliq-web.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure} - traefik.http.routers.arsenaliq-web.tls=true - - traefik.http.services.arsenaliq-web.loadbalancer.server.port=3000 + - traefik.http.services.arsenaliq-web.loadbalancer.server.port=80 networks: - arsenal_iq - traefik diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..508a38d --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,26 @@ +FROM node:20-alpine AS build + +WORKDIR /app + +ARG VITE_API_BASE_URL=https://api.arsenal.example.com/api +ARG VITE_ALLOW_REGISTRATION=true +ARG VITE_ALLOW_DEMO_ACCOUNT=false + +ENV VITE_API_BASE_URL=${VITE_API_BASE_URL} +ENV VITE_ALLOW_REGISTRATION=${VITE_ALLOW_REGISTRATION} +ENV VITE_ALLOW_DEMO_ACCOUNT=${VITE_ALLOW_DEMO_ACCOUNT} + +COPY package*.json ./ + +RUN npm ci --legacy-peer-deps + +COPY . . + +RUN npm run build + +FROM nginx:1.27-alpine + +COPY nginx/default.conf.template /etc/nginx/templates/default.conf.template +COPY --from=build /app/dist /usr/share/nginx/html + +EXPOSE 80 diff --git a/frontend/nginx/default.conf.template b/frontend/nginx/default.conf.template new file mode 100644 index 0000000..81c4230 --- /dev/null +++ b/frontend/nginx/default.conf.template @@ -0,0 +1,35 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + server_tokens off; + + add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always; + add_header Pragma "no-cache" always; + add_header Expires "0" always; + add_header X-Frame-Options "DENY" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()" always; + add_header Cross-Origin-Embedder-Policy "unsafe-none" always; + add_header Cross-Origin-Opener-Policy "same-origin" always; + add_header Cross-Origin-Resource-Policy "same-origin" always; + add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; connect-src 'self' ${CSP_CONNECT_SRC}; font-src 'self' data:; frame-ancestors 'none'; img-src 'self' data: https:; object-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; form-action 'self'; manifest-src 'self'; upgrade-insecure-requests" always; + + location = /robots.txt { + default_type text/plain; + try_files $uri =404; + } + + location = /sitemap.xml { + default_type application/xml; + try_files $uri =404; + } + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/frontend/public/robots.txt b/frontend/public/robots.txt new file mode 100644 index 0000000..8de4e56 --- /dev/null +++ b/frontend/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://arsenal.blaishome.online/sitemap.xml diff --git a/frontend/public/sitemap.xml b/frontend/public/sitemap.xml new file mode 100644 index 0000000..eb80641 --- /dev/null +++ b/frontend/public/sitemap.xml @@ -0,0 +1,8 @@ + + + + https://arsenal.blaishome.online/ + weekly + 1.0 + +