Cómo desplegar Ghost (CMS/Blog) en Kubernetes

Ghost en Kubernetes por SREDevOps.Org

Este repositorio implementa Ghost CMS v6.xx.x desde @TryGhost (Oficial) en Kubernetes, usando nuestra imagen personalizada con mejoras significativas diseñadas para su uso en Kubernetes (Dockerfile). Revisa el repositorio en Github para las últimas actualizaciones.

Características

  • Tanto Ghost como MySQL se ejecutan como usuarios non-root en Kubernetes, mejorando considerablemente la seguridad, junto con otras mejoras en la imagen personalizada.
  • Soporte multi-arch (amd64 y arm64).
  • Se usa la imagen oficial Node 22 Jod LTS como entorno de build. Dockerfile.
  • Implementa un multi-stage build, reduciendo el tamaño final de la imagen y mejorando la seguridad al eliminar componentes innecesarios.
  • Usa Distroless Node 22 Debian 12 como entorno de runtime en la imagen final.
  • La imagen oficial de Ghost usaba gosu, pero fue removido en favor de una ejecución nativa sin privilegios dentro del contenedor. Todo corre como usuario non-root (UID/GID 65532) en el contenedor Distroless. Este cambio reduce 6 vulnerabilidades críticas y 34 altas reportadas por Docker Scout en la imagen oficial de Ghost.
  • Nuevo Entrypoint basado en script Node.js ejecutado por el usuario sin privilegios dentro del contenedor Distroless, que actualiza los temas por defecto y lanza la aplicación Ghost.
  • Se usa siempre la última versión de Ghost 6 al momento del build.
GitHub - sredevopsorg/ghost-on-kubernetes: Ghost on Kubernetes by SREDevOps.org - Deploy Ghost v6 on Kubernetes (k8s, k3s, etc) with our hardened distroless non root custom image.
Ghost on Kubernetes by SREDevOps.org - Deploy Ghost v6 on Kubernetes (k8s, k3s, etc) with our hardened distroless non root custom image. - sredevopsorg/ghost-on-kubernetes

Ejemplo de nuestra Imagen Ghost on Kubernetes en Docker Hub

Docker Scout Report - Ghost on Kubernetes Image

Ejemplo de escaneo para la Imagen Oficial de Ghost

Docker Scout Report - Ghost Official Image

Cambios recientes

Actualizaciones clave para mejorar la seguridad y eficiencia de Ghost en Kubernetes:

  • Ghost v6 actualizado: Usamos la nueva versión, revisa la documentación oficial.
  • NodeJS actualizado: Desde Iron LTS (Node v20) a Jod LTS (Node v22).
  • Soporte multi-arch: Imágenes para amd64 y arm64.
  • Imagen Distroless: Basada en @GoogleContainerTools, solo con los componentes necesarios para ejecutar la app.
  • MySQL StatefulSet: Ahora MySQL se ejecuta como StatefulSet, lo que permite almacenamiento persistente y redes estables.
  • Init Container: Nuevo init container que prepara configuraciones, permisos y directorios antes de iniciar Ghost. Ver deploy/06-ghost-deployment.yaml.
  • Entrypoint Script: Script NodeJS que corre como usuario non-root dentro del contenedor Distroless para actualizar temas y lanzar Ghost. entrypoint.js

Instrucciones de instalación

0. Clonar el repositorio

git clone https://github.com/sredevopsorg/ghost-on-kubernetes.git --depth 1 --branch main --single-branch --no-tags
cd ghost-on-kubernetes
git checkout -b my-branch --no-track --detach

1. Revisar configuraciones de ejemplo

Los archivos de ejemplo están en examples:

  • config.development.sample.yaml: Configuración para desarrollo, usa SQLite.
  • config.production.sample.yaml: Configuración para producción, usa MySQL 8. Requiere dominio válido y Ingress configurado.

Más detalles en la documentación oficial de Ghost.

2. Editar valores según tus necesidades

Revisa cada manifiesto dentro de deploy/.

Arquitectura de despliegue Ghost en Kubernetes

Ghost requiere varios recursos Kubernetes:

Namespace

Aisla recursos en ghost-on-kubernetes.

apiVersion: v1
kind: Namespace
metadata:
  name: ghost-on-kubernetes

Secrets

Guarda datos sensibles como contraseñas y certificados TLS.

  • ghost-config-prod
  • ghost-on-kubernetes-mysql-env
  • tls-secret

PersistentVolumeClaims

Permite almacenamiento persistente para contenido Ghost y base de datos MySQL.

Services

Expone Ghost y MySQL dentro del clúster.

StatefulSet

Administra la base de datos MySQL con almacenamiento persistente.

Deployment

Gestiona la aplicación Ghost (stateless).

Ingress

Expone Ghost a Internet mediante dominio.

Despliegue en Kubernetes

Aplica los archivos en orden:

kubectl apply -f deploy/00-namespace.yaml
kubectl apply -f deploy/01-mysql-config.yaml
kubectl apply -f deploy/04-ghost-config.yaml
kubectl apply -f deploy/01-tls.yaml
kubectl apply -f deploy/02-pvc.yaml
kubectl apply -f deploy/03-service.yaml
kubectl apply -f deploy/05-mysql.yaml
kubectl apply -f deploy/06-ghost-deployment.yaml
kubectl apply -f deploy/07-ingress.yaml

Tu blog Ghost está desplegado

Has desplegado Ghost en Kubernetes exitosamente. Personaliza configuraciones según tus necesidades (almacenamiento, recursos, dominio, etc.).

Acceder sin dominio

Para previsualizar Ghost sin dominio:

Configura url y admin url como http://localhost:2368/, reinicia el pod y usa port-forward:

kubectl port-forward -n ghost-on-kubernetes services ghost-on-kubernetes-service 2368:2368

Contribuir

Contribuciones son bienvenidas. Revisa CONTRIBUTING.md.

Licencia y créditos

  • Proyecto bajo MIT License. Ver LICENSE.
  • Ghost CMS está bajo MIT License.
  • Las imágenes base (Node y Distroless) pertenecen a sus respectivos autores.

Historial de estrellas

Star History Chart

Enlaces

GitHub - sredevopsorg/ghost-on-kubernetes: Ghost on Kubernetes by SREDevOps.org - Deploy Ghost v6 on Kubernetes (k8s, k3s, etc) with our hardened distroless non root custom image.
Ghost on Kubernetes by SREDevOps.org - Deploy Ghost v6 on Kubernetes (k8s, k3s, etc) with our hardened distroless non root custom image. - sredevopsorg/ghost-on-kubernetes

Nicolás Georger

Nicolás Georger

Self-taught IT professional driving innovation & social impact with cybernetics, open source (Linux, Kubernetes), AI & ML.