diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f3acda8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +node_modules +npm-debug.log +Dockerfile* +docker-compose* +.git +.gitignore +README.md +.env +.nyc_output +coverage +.vscode +.idea +.DS_Store +.cache +dist diff --git a/DOCKER_README.md b/DOCKER_README.md new file mode 100644 index 0000000..ee79ca4 --- /dev/null +++ b/DOCKER_README.md @@ -0,0 +1,47 @@ +# Docker Setup для Alma-vid + +## Сборка и запуск контейнера + +### Простой запуск с docker-compose (рекомендуется): + +```bash +docker-compose up --build +``` + +### Или вручную: + +1. Сборка образа: + +```bash +docker build -t alma-vid . +``` + +2. Запуск контейнера: + +```bash +docker run -p 80:80 alma-vid +``` + +## Структура Docker файлов + +- `Dockerfile` - Многоэтапная сборка React приложения с nginx +- `docker-compose.yml` - Конфигурация для запуска с docker-compose +- `.dockerignore` - Исключения файлов при сборке +- `nginx.conf` - Кастомная конфигурация nginx с оптимизациями + +## Особенности + +- Использует Node.js 18 Alpine для сборки +- Nginx Alpine для продакшена +- Gzip сжатие +- Кеширование статических файлов +- Поддержка React Router +- Безопасность заголовков + +## Доступ к приложению + +После запуска приложение будет доступно по адресу: http://localhost + +## Логи + +Логи nginx сохраняются в папке `./logs` (при использовании docker-compose) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dae0aea --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM node:18-alpine AS build +ARG BUILD_CONFIGURATION=production +WORKDIR /app + +COPY package*.json ./ + +RUN npm ci --only=production + +COPY . . + +RUN npm run build + +FROM nginx:alpine AS final +WORKDIR /usr/share/nginx/html + +RUN rm -rf ./* + +COPY --from=build /app/build . + +COPY nginx.conf /etc/nginx/nginx.conf + +EXPOSE 80 + +ENTRYPOINT ["nginx", "-g", "daemon off;"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..34d066e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,19 @@ +version: "3.8" + +services: + alma-vid: + build: + context: . + dockerfile: Dockerfile + args: + BUILD_CONFIGURATION: production + ports: + - "80:80" + container_name: alma-vid-app + restart: unless-stopped + environment: + - NODE_ENV=production + volumes: + # Optional: mount custom nginx config + # - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./logs:/var/log/nginx diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..2727613 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,70 @@ +user nginx; +worker_processes auto; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_proxied any; + gzip_comp_level 6; + gzip_types + text/plain + text/css + text/xml + text/javascript + application/json + application/javascript + application/xml+rss + application/atom+xml + image/svg+xml; + + server { + listen 80; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; + + # Static files cache + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Handle React Router + location / { + try_files $uri $uri/ /index.html; + } + + # Error pages + error_page 404 /index.html; + } +}