diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..991eb54 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,28 @@ +# Docker +Dockerfile +docker-compose.yml +.dockerignore + +# Node +node_modules/ +npm-debug.log* + +# OS +.DS_Store +Thumbs.db + +# Git +.git/ +.gitignore + +# IDE +.vscode/ +.idea/ + +# Logs +logs/ +*.log + +# Cache +.cache/ +.parcel-cache/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b6f0f97 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# Etapa de construcción +FROM node:18-alpine AS builder + +# Establecer el directorio de trabajo +WORKDIR /app + +# Copiar archivos de configuración de package +COPY package*.json ./ + +# Instalar dependencias +RUN npm ci --only=production + +# Copiar archivos del proyecto +COPY . . + +# Construir CSS de Tailwind si es necesario +RUN npm run build || true + +# Etapa de producción +FROM nginx:alpine + +# Instalar el usuario appuser y establecer permisos +RUN addgroup -g 1001 -S appgroup && \ + adduser -S appuser -u 1001 -G appgroup + +# Copiar archivos de construcción estáticos +COPY --from=builder /app /usr/share/nginx/html + +# Copiar configuración personalizada de nginx +COPY nginx.conf /etc/nginx/nginx.conf + +# Establecer permisos correctos +RUN chown -R appuser:appgroup /usr/share/nginx/html && \ + chown -R appuser:appgroup /var/cache/nginx && \ + chown -R appuser:appgroup /var/log/nginx && \ + chown -R appuser:appgroup /etc/nginx/conf.d && \ + touch /var/run/nginx.pid && \ + chown -R appuser:appgroup /var/run/nginx.pid + +# Cambiar al usuario appuser +USER appuser + +# Exponer puerto 8080 en lugar de 80 para evitar conflictos +EXPOSE 8080 + +# Iniciar nginx +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..af8386f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,23 @@ +version: '3.8' + +services: + web: + build: + context: . + dockerfile: Dockerfile + ports: + - "8080:8080" + environment: + - NGINX_PORT=8080 + restart: unless-stopped + security_opt: + - no-new-privileges:true + read_only: true + tmpfs: + - /var/cache/nginx + - /var/run + cap_drop: + - ALL + cap_add: + - CHOWN + - NET_BIND_SERVICE \ No newline at end of file diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..98cde63 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,65 @@ +user appuser; +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; + + # Configuración de seguridad + server_tokens off; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header X-XSS-Protection "1; mode=block" always; + + server { + listen 8080; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + + # Configuración de seguridad adicional + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header X-XSS-Protection "1; mode=block" always; + + # Manejo de archivos estáticos + location ~* \.(css|js|ico|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + } + + # Manejo de HTML + location / { + try_files $uri $uri/ /index.html; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + } + + # Negar acceso a archivos ocultos + location ~ /\. { + deny all; + } + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..44f7e8b --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "noire-landing", + "version": "1.0.0", + "description": "Noiré Collective Landing Page", + "main": "index.js", + "scripts": { + "build": "tailwindcss -i ./css/tailwind.css -o ./css/tailwind-build.css --watch", + "build:prod": "tailwindcss -i ./css/tailwind.css -o ./css/tailwind-build.css --minify" + }, + "devDependencies": { + "tailwindcss": "^3.0.0" + }, + "keywords": ["landing", "marketing", "web"], + "author": "Noiré Collective" +} \ No newline at end of file