Desplegar proyectos Astro con Dokploy y Nixpacks y habilitar caché para optimizar la velocidad de construcción
I. Configuración de Dokploy
Dokploy es una plataforma de despliegue de código abierto y autoalojable, diseñada como una alternativa gratuita a Heroku, Vercel y Netlify, construida sobre Docker y Traefik.
1. Crear un nuevo proyecto y conectar el repositorio de GitHub
2. Establecer variables de entorno
NIXPACKS_NODE_VERSION=22NIXPACKS_PNPM_STORE_PATH=/root/.local/share/pnpm/store/v3NIXPACKS_INSTALL_CACHE_DIRS=/app/node_modulesNIXPACKS_BUILD_CACHE_DIRS=/app/node_modules/.cache,/app/astro_cache3. Desactivar limpieza de caché
- Servicio del proyecto → Clean Cache: Desactivar
- Servidor web → Daily Docker Cleanup: Desactivar
II. Motor de construcción Nixpacks
Nixpacks es una herramienta de construcción de código abierto lanzada por Railway que construye código fuente en imágenes Docker estándar. Dokploy utiliza Nixpacks como motor de construcción predeterminado y admite la especificación de configuraciones de construcción en archivos nixpacks.toml o nixpacks.json. Cree un archivo nixpacks.toml en el directorio raíz del proyecto y configure los directorios de caché relevantes.
Prioridad de configuración (Baja → Alta):
- Lógica predeterminada del proveedor
nixpacks.toml- Variables de entorno
- Argumentos CLI
Variables de entorno comunes
| Nombre de la variable | Descripción |
|---|---|
NIXPACKS_INSTALL_CMD | Comando de instalación personalizado |
NIXPACKS_BUILD_CMD | Comando de construcción personalizado |
NIXPACKS_START_CMD | Comando de inicio personalizado |
NIXPACKS_PKGS | Instalar paquetes Nix adicionales |
NIXPACKS_APT_PKGS | Instalar paquetes Apt adicionales |
NIXPACKS_INSTALL_CACHE_DIRS | Directorios de caché de la fase de instalación |
NIXPACKS_BUILD_CACHE_DIRS | Directorios de caché de la fase de construcción |
NIXPACKS_NO_CACHE | Desactivar caché (no recomendado) |
NIXPACKS_CONFIG_FILE | Especificar archivo de configuración |
NIXPACKS_DEBIAN | Habilitar imagen base Debian |
III. Configuración del proyecto Astro
Astro es un marco web moderno para sitios de contenido, especialmente adecuado para sitios web estáticos como blogs, páginas de marketing y comercio electrónico. Cuando un sitio web tiene una gran cantidad de imágenes y recursos estáticos, la velocidad de construcción puede verse afectada. Al habilitar los mecanismos de caché, la eficiencia de la construcción se puede mejorar significativamente.
1. Configurar el directorio de artefactos de caché de construcción:
Los proyectos Astro necesitan especificar un directorio de caché en el archivo de configuración para reutilizar artefactos de construcción anteriores en construcciones posteriores. Los archivos en este directorio se utilizarán en construcciones posteriores para acelerar el tiempo de construcción. Este valor puede ser una ruta absoluta o una ruta relativa.
//`astro.config.mjs`export default defineConfig({ cacheDir: "./astro_cache",});2. Archivo de configuración de caché de Nixpacks
Cree un archivo nixpacks.toml en el directorio raíz del proyecto Astro y configure los directorios de caché y los comandos de construcción.
# Usar versiones especificadas de Node.js y pnpm[phases.setup]nixPkgs = ["nodejs_22", "pnpm"]
# Instalar dependencias y habilitar caché de pnpm[phases.install]cmds = ["pnpm install --frozen-lockfile"]cacheDirectories = ["/root/.local/share/pnpm/store/v3"]
# Construir proyecto Astro y almacenar en caché node_modules/.cache y astro_cache[phases.build]cmds = ["pnpm run build"]cacheDirectories = [ "node_modules/.cache", "astro_cache"]
# Comando de inicio (usas NGINX para servir el directorio estático dist, esto es solo un marcador de posición)[start]cmd = "echo 'Construcción completa, por favor acceda al directorio dist a través de NGINX'"3. Optimizar el contexto de construcción de Docker
Agregue .dockerignore al directorio raíz del proyecto Astro:
node_modulesastro_cachedist*.log.DS_Store.vscode.env*IV. Despliegue y verificación
Después del despliegue automático de Dokploy, verifique los registros de construcción para el siguiente contenido para confirmar que el caché es efectivo:
1. El comando de construcción usó caché montado
RUN --mount=type=cache,id=xxxx-node_modules/cache,target=/app/node_modules/.cache \ --mount=type=cache,id=xxxx-astro_cache,target=/app/astro_cache \ pnpm run build2. La construcción de Astro reutilizó entradas de caché (especialmente optimización de imágenes)
▶ /_astro/202409272055577_Z2smeTW.avif (reused cache entry)▶ /_astro/202409272055575_Z2wPyJN.avif (reused cache entry)▶ /_astro/202409272055577_1IgP6g.avif (reused cache entry)✅ Si ve los registros de caché de montaje anteriores y el texto “reused cache entry”, significa que el mecanismo de caché se ha habilitado con éxito y la construcción ha logrado una aceleración incremental.
🎉 Desde la pestaña Deployments del proyecto Dokploy, también puede ver que sin la configuración de caché, la construcción del proyecto tarda 31 minutos, mientras que con la configuración de caché habilitada, solo tarda 3 minutos, lo que reduce en gran medida el tiempo de construcción y ahorra tráfico y ancho de banda.
V. Acelerar el sitio con Tencent EdgeOne
Antecedentes: El “Triángulo Imposible” de la transmisión transfronteriza
Despliegue de servidores en Singapur. Esta solución es rentable y no requiere procesos de registro engorrosos, pero para los usuarios en China continental, la experiencia de acceso a menudo enfrenta enormes desafíos:
- Alta latencia física: El RTT (Round Trip Time) de Singapur a China continental generalmente fluctúa entre 50 ms y 200 ms.
- Pérdida severa de paquetes: Interferido por el firewall GFW, los apretones de manos TCP a menudo expiran, lo que hace que las imágenes se atasquen cargando a la mitad (Pending).
- Retraso de salto: Las aplicaciones de múltiples páginas requieren largas esperas de pantalla blanca al hacer clic en enlaces.
Para resolver este problema, utilizamos Tencent Cloud EdgeOne junto con la configuración refinada de Traefik para crear un “combo”, logrando una experiencia de apertura casi instantánea cercana a los sitios web registrados localmente.
Idea de arquitectura central
Nuestra estrategia de optimización gira en torno a tres palabras clave: Anti-Pérdida de Paquetes, Descarga de Compresión, y Caché por Capas.
- Capa de Protocolo (EdgeOne): Utilizar el protocolo HTTP/3 (QUIC) basado en características UDP para resolver completamente las interrupciones de carga de contenido causadas por la pérdida de paquetes transfronterizos TCP.
- Capa de Transporte (Traefik -> EdgeOne): Desactivar la compresión de origen de Traefik y dejar que los nodos de borde de EdgeOne sean responsables de una compresión inteligente Brotli más eficiente para reducir el volumen de transmisión.
- Capa de Caché (Estrategia): Utilizar
s-maxagepara lograr la separación de “Caché CDN a largo plazo” y “Caché de navegador a corto plazo”, asegurando tanto la tasa de aciertos de CDN como la puntualidad de actualización de contenido.
I. Configuración global de EdgeOne (Habilitar modo “Anti-Pérdida de Paquetes”)
Aunque EdgeOne no puede proporcionar nodos domésticos para dominios no registrados, sus nodos de borde (Hong Kong/Singapur) a las líneas domésticas están optimizados y admiten el protocolo QUIC, que es la clave para resolver el “retraso de red”.
Ingrese a la consola de EdgeOne -> Aceleración del sitio -> Configuración de funciones:
1. Habilitar HTTP/3 (QUIC) ✅
Este es el paso más crítico. En redes transfronterizas con altas tasas de pérdida de paquetes, el protocolo QUIC puede evitar eficazmente el bloqueo de cabeza de línea TCP. Después de habilitar, el fenómeno de imágenes “girando” o “cargando a la mitad” desaparecerá por completo.
2. Habilitar compresión inteligente (Brotli + Gzip) ✅
Se recomienda habilitar tanto Brotli como Gzip. EdgeOne priorizará devolver el formato Brotli (br) a los navegadores compatibles, que tiene una tasa de compresión del 15% al 20% más alta que Gzip. Cuanto menor sea el volumen, más rápido pasará a través del muro.
3. Habilitar pre-actualización de caché (90%) ✅
Establezca la relación de pre-actualización en 90%. Esto significa que en el último 10% del tiempo antes de que expire el caché, el CDN volverá asincrónicamente a la fuente para actualizar. Los usuarios nunca encontrarán retrasos causados por “caducidad de caché que conduce a retorno a la fuente”, logrando una experiencia de acierto del 100%.
II. Optimización de la configuración de Traefik (Estrategia de origen)
Necesitamos modificar el dynamic_conf.yml de Traefik (o las etiquetas de Docker) para hacer dos cosas: Descargar compresión e Inyectar encabezados de caché refinados.
1. Desactivar compresión de origen
Verifique su configuración de Routers y elimine todos los middlewares compress (Gzip).
- Razón: EdgeOne ya es responsable de la compresión Brotli. Hacer Gzip en el origen nuevamente desperdiciará CPU y puede causar problemas de doble compresión.
2. Definir estrategia de caché por capas (Código principal)
Este es el núcleo para resolver la contradicción entre “los usuarios no pueden ver contenido nuevo después de publicar artículos” y “la velocidad de retorno directo a la fuente es demasiado lenta”.
Definimos un middleware específicamente para páginas HTML en Traefik:
http: routers: # Forzar redirección HTTPS idimi-uygy0r-redirect-https: entryPoints: - web rule: Host(`idimi.com`) middlewares: - idimi-uygy0r-to-https service: noop@internal priority: 1000
# Service Worker (Núcleo PWA) - Sin compresión, manejado por EdgeOne idimi-uygy0r-sw: rule: > Host(`idimi.com`) && ( Path(`/service-worker.js`) || Path(`/sw.js`) ) service: idimi-uygy0r-app middlewares: - idimi-uygy0r-no-store - idimi-uygy0r-security-headers entryPoints: - websecure tls: certResolver: letsencrypt priority: 900
# Recursos estáticos principales de Astro (Huella digital Hash) - Sin compresión, manejado por EdgeOne idimi-uygy0r-static-immutable: rule: > Host(`idimi.com`) && ( PathPrefix(`/_astro`) || PathPrefix(`/assets`) ) service: idimi-uygy0r-app middlewares: - idimi-uygy0r-cache-static-immutable - idimi-uygy0r-security-headers entryPoints: - websecure tls: certResolver: letsencrypt priority: 800
# Archivos WASM de Pagefind - Sin compresión, manejado por EdgeOne idimi-uygy0r-pagefind-wasm-ctype: rule: > Host(`idimi.com`) && PathRegexp(`^/pagefind/.*\\.wasm$`) service: idimi-uygy0r-app middlewares: - idimi-uygy0r-set-wasm-ctype - idimi-uygy0r-cache-static-immutable - idimi-uygy0r-security-headers entryPoints: - websecure tls: certResolver: letsencrypt priority: 760
# Archivos de índice de Pagefind - Sin compresión, manejado por EdgeOne idimi-uygy0r-pagefind-immutable: rule: > Host(`idimi.com`) && PathPrefix(`/pagefind`) service: idimi-uygy0r-app middlewares: - idimi-uygy0r-cache-static-immutable - idimi-uygy0r-security-headers entryPoints: - websecure tls: certResolver: letsencrypt priority: 750
# Sitemap / Robots / RSS - Sin compresión, manejado por EdgeOne idimi-uygy0r-meta-short: rule: > Host(`idimi.com`) && ( Path(`/sitemap.xml`) || Path(`/robots.txt`) || Path(`/sitemap-index.xml`) || Path(`/atom.xml`) || Path(`/rss.xml`) || Path(`/feed.xml`) ) service: idimi-uygy0r-app middlewares: - idimi-uygy0r-cache-short - idimi-uygy0r-security-headers entryPoints: - websecure tls: certResolver: letsencrypt priority: 700
# Manifest - Sin compresión, manejado por EdgeOne idimi-uygy0r-manifest: rule: > Host(`idimi.com`) && ( Path(`/manifest.webmanifest`) || Path(`/site.webmanifest`) || Path(`/browserconfig.xml`) ) service: idimi-uygy0r-app middlewares: - idimi-uygy0r-cache-1d - idimi-uygy0r-security-headers entryPoints: - websecure tls: certResolver: letsencrypt priority: 650
# Otros archivos estáticos (Imágenes/Videos, etc.) - Sin compresión, manejado por EdgeOne idimi-uygy0r-public-30d: rule: > Host(`idimi.com`) && PathRegexp(`.+\\..+`) service: idimi-uygy0r-app middlewares: - idimi-uygy0r-cache-30d-swr - idimi-uygy0r-security-headers entryPoints: - websecure tls: certResolver: letsencrypt priority: 600
# Páginas HTML (Regla de respaldo) - Sin compresión, manejado por EdgeOne # Estrategia de separación s-maxage=3600 aplicada idimi-uygy0r-pages: rule: Host(`idimi.com`) service: idimi-uygy0r-app middlewares: - idimi-uygy0r-cache-html - idimi-uygy0r-security-headers entryPoints: - websecure tls: certResolver: letsencrypt priority: 100
services: idimi-uygy0r-app: loadBalancer: servers: - url: http://idimi-idimi-uygy0r:80 passHostHeader: true
middlewares: idimi-uygy0r-to-https: redirectScheme: scheme: https permanent: true
# --- Definición de middleware de compresión retenida pero no llamada (eliminada de Routers) --- idimi-uygy0r-gzip-compress: compress: minResponseBodyBytes: 1024 excludedContentTypes: - "image/png" - "image/jpeg" - "image/gif" - "image/webp" - "image/avif" - "font/*"
idimi-uygy0r-security-headers: headers: addVaryHeader: true stsSeconds: 31536000 stsIncludeSubdomains: true stsPreload: true contentTypeNosniff: true browserXssFilter: true referrerPolicy: "strict-origin-when-cross-origin" permissionsPolicy: "geolocation=(), microphone=(), camera=()" frameDeny: true customResponseHeaders: Timing-Allow-Origin: "*"
idimi-uygy0r-no-store: headers: customResponseHeaders: Cache-Control: "no-cache, no-store, must-revalidate"
idimi-uygy0r-cache-short: headers: customResponseHeaders: Cache-Control: "public, max-age=600, stale-while-revalidate=600" Vary: "Accept-Encoding"
idimi-uygy0r-cache-1d: headers: customResponseHeaders: Cache-Control: "public, max-age=86400, stale-while-revalidate=86400" Vary: "Accept-Encoding"
idimi-uygy0r-cache-30d-swr: headers: customResponseHeaders: Cache-Control: "public, max-age=2592000, stale-while-revalidate=604800" Vary: "Accept-Encoding"
idimi-uygy0r-cache-static-immutable: headers: customResponseHeaders: Cache-Control: "public, max-age=31536000, immutable" Vary: "Accept-Encoding"
# Modificación clave: Estrategia de caché HTML # El navegador almacena en caché durante 5 minutos (300s), el CDN almacena en caché durante 1 hora (3600s) idimi-uygy0r-cache-html: headers: customResponseHeaders: Cache-Control: "public, max-age=300, s-maxage=3600, stale-while-revalidate=600" Vary: "Accept-Encoding"
idimi-uygy0r-set-wasm-ctype: headers: customResponseHeaders: Content-Type: "application/wasm"Explicación de la configuración:
s-maxage=3600: Esta es una directiva escrita específicamente para el CDN. EdgeOne ve esto y almacena en caché la página HTML durante 1 hora.max-age=300: Cuando EdgeOne lo envía al usuario, eliminas-maxage, y el navegador del usuario solo ve 300 segundos (5 minutos).- Efecto: El CDN maneja el tráfico durante 1 hora, mientras que los usuarios solo necesitan esperar 5 minutos para ver los artículos recién publicados.
III. Motor de reglas de EdgeOne
Debido a la estructura de URL de Astro (sin sufijo) y al servicio de imágenes dinámicas (/_image), se necesitan reglas precisas para alcanzar el caché.
En el Motor de reglas de EdgeOne, configure las siguientes reglas estrictamente en orden:
Regla 1: Recursos estáticos principales de Astro (Caché permanente)
Los activos de Astro, los artefactos de construcción y el servicio de imágenes dinámicas, el contenido que nunca cambia o consume mucha CPU, deben almacenarse en caché a la fuerza.
- Condición de coincidencia:
Ruta URL->Coincidencia Regex - Valor de coincidencia:
^/(_astro|assets|pagefind|_image)/ - Nota:
_imagese agrega aquí, optimizando específicamente las imágenes optimizadas dinámicas generadas por el componente<Image />de Astro. - Acción:
- Caché de nodo: 365 días (Forzar)
- Caché del navegador: 365 días
Regla 2: Archivos estáticos regulares
- Condición de coincidencia:
Extensión de archivoigual apng, jpg, jpeg, webp, css, js, etc. - Acción: Caché de nodo 30 días (Forzar).
Regla 3: Service Worker (Núcleo PWA)
- Condición de coincidencia:
Ruta URLigual a/sw.jso/service-worker.js. - Acción: Caché de nodo 1 hora (Forzar).
- Advertencia: No almacene en caché durante demasiado tiempo, de lo contrario, la PWA no se podrá actualizar a tiempo después del lanzamiento.
Regla 4: Regla de respaldo (Páginas HTML)
- Condición de coincidencia: (Sin condición / Coincide con todas las solicitudes restantes)
- Acción:
- Caché de nodo: Seguir origen (es decir, leer
s-maxage=3600de Traefik). - Caché del navegador: Seguir origen (es decir, leer
max-age=300de Traefik).
- Caché de nodo: Seguir origen (es decir, leer
IV. Optimización a nivel de código de Astro (Aceleración percibida)
Para que las transiciones de página sean tan fluidas como las “aplicaciones nativas” y eliminar por completo la espera de pantalla blanca durante los saltos, necesitamos utilizar el Client Router (anteriormente View Transitions) de Astro.
1. Habilitar Client Router
Agregue en el <head> de src/layouts/MainLayout.astro:
import { ClientRouter } from 'astro:transitions';
<head> <!-- Otras etiquetas meta --> <ClientRouter /></head>2. Habilitar precarga (Prefetch)
Configure la estrategia de precarga en astro.config.mjs:
export default defineConfig({ // 'viewport': Descargar cuando el enlace entra en la ventana gráfica (equilibrio de tráfico y velocidad) // 'load': Descargar todos los enlaces inmediatamente después de que se cargue la página (velocidad extrema, pero consume ancho de banda) prefetch: { defaultStrategy: 'viewport', }, // ...});Publicado el: 14 de jul de 2025 · Modificado el: 11 de dic de 2025