Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 35 additions & 3 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
.DS_Store
node_modules
npm-debug.log
.astro
.git
.gitignore
README.md
.env
.nyc_output
coverage
.vscode
.env.local
.env.production
.env.staging
dist
README:md
LICENSE
.DS_Store
*.log
logs
*.tgz
.pnpm-debug.log*
.pnpm-store/
.next
out
.cache
.parcel-cache
build
.next
.vercel
netlify.toml
fly.toml
render.yaml
Dockerfile*
docker-compose*
.dockerignore
kubernetes/
k8s/
helm/
charts/
69 changes: 48 additions & 21 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,41 +1,68 @@
FROM node:lts-alpine as builder
# syntax=docker/dockerfile:1
ARG NODE_VERSION=20-alpine
ARG NGINX_VERSION=alpine

# Enable and configure pnpm
FROM node:${NODE_VERSION} AS builder

# Install build dependencies
RUN apk add --no-cache libc6-compat

# Configure pnpm
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
RUN corepack enable

WORKDIR /app
COPY . /app

# Copy dependency files first for better caching
COPY package.json pnpm-lock.yaml ./
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile

# -------------- Project build Stage -----------------
# Copy source code
COPY . .

# Install dependencies and enable cache
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
# Build application with optimizations
RUN pnpm run build && \
# Remove source maps and unnecessary files
find /app/dist -name "*.map" -delete && \
# Remove dev dependencies
pnpm prune --prod

# Production stage
FROM nginx:${NGINX_VERSION} AS runtime

# Build app
RUN pnpm run build
# Install security updates and curl for health check
RUN apk --no-cache upgrade && \
apk --no-cache add curl

# ------------------ NGINX Stage --------------------
FROM nginx:alpine as runtime
# Fix permissions for nginx user
RUN chown -R nginx:nginx /var/cache/nginx && \
chown -R nginx:nginx /var/log/nginx && \
chown -R nginx:nginx /etc/nginx/conf.d && \
touch /var/run/nginx.pid && \
chown -R nginx:nginx /var/run/nginx.pid

# Remove default nginx static assets
RUN rm -rf /usr/share/nginx/html
# Remove default nginx assets
RUN rm -rf /usr/share/nginx/html/*

# Copy built site
COPY --from=builder /app/dist /usr/share/nginx/html
# Copy built application with proper ownership
COPY --from=builder --chown=nginx:nginx /app/dist /usr/share/nginx/html

# Remove default nginx config
RUN rm /etc/nginx/conf.d/default.conf

# Copy custom nginx config
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
# Copy custom nginx config with proper ownership
COPY --chown=nginx:nginx nginx.conf /etc/nginx/conf.d/default.conf

# Expose default Nginx port
EXPOSE 80
# Switch to non-root user
USER nginx

# Start Nginx with global directives and daemon turned off
ENTRYPOINT [ "nginx", "-g", "daemon off;" ]
# Expose port
EXPOSE 8080

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/ || exit 1

# Start nginx
ENTRYPOINT ["nginx", "-g", "daemon off;"]
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,5 @@ La página web usa la herramienta [Astro](https://astro.build/). Para poder usar
2. El contenedor generado es completamente autocontenido y usa un servidor de Nginx para servir los archivos, por tanto sólo queda ejecutar el contenedor:

```bash
docker run -d -p 8080:80 hackiit-website:latest
docker run -d -p 8080:8080 hackiit-website:latest
```


44 changes: 44 additions & 0 deletions nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
server {
listen 8080;
root /usr/share/nginx/html;
index index.html;

# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# 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;

# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}

# Handle client-side routing
location / {
try_files $uri $uri/ /index.html;
}

# Security: deny access to hidden files
location ~ /\. {
deny all;
}
}
Loading