Search code examples
rubykubernetessinatrarack

Sinatra On Kubernetes - Moved app to subdirectory, app assets fail to render in production (404) but work locally


My code: https://github.com/nullset2/smbdxfortunes

Hi. My setup is as follows:

  1. Sinatra app
  2. Ruby 2.7
  3. Kubernetes 1.17
  4. Traefik Ingress as "Reverse proxy"

I originally had this application working fine on the root of my server: nullset2.zapto.org (which resolves through DDNS to the IP of my router), and now I wish to move this application so it's served from nullset2.zapto.org/smbdxfortunes.

My sinatra app uses the convention that assets and static files should live in a ./public subdirectory, from where it reads a small landing page and listens to requests for another route, does a small query and returns an erb file.

I have configured the Ingress so it resolves to the correct applications depending on the route and rewritten the application code so it listens on the /smbdxfortunes route. For some reason the application will work perfectly locally, and render a page from public/index.html with all assets --however when I containerize it and deploy it on my kubernetes cluster, the app will work but all static files referenced in public/index.html will return HTTP 400. The website itself will be rendered, but with all broken images and no styles.

Things I've tried to no avail:

  1. Setting set :base_path, '/smbdxfortunes' in my fortune.rb sinatra module.
  2. Setting set :static, true in my fortune.rb.
  3. Modifying the actual paths that the assets are read from in my index.html to account for the subdirectory (e.g. img/vine.png becomes /smbdxfortunes/img/vine.png)
  4. Setting config.ru like this and changing the CMD statement in my dockerfile to use rackup:
require './fortune'
use Rack::Static, :urls => ['/css', '/js', '/img', '/wav'], :root => 'public'
run Sinatra::Application

Any help is appreciated.


Solution

  • Not an answer per-se, but a workaround: I managed to work around this problem by pointing both my / and /smbdxfortunes routes on my ingress to the same service, so all requests for static assets go to the sinatra public subdirectory, and requests to the root otherwise return a 404.

    ---
    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: nullset2-ingress
      annotations:
        kubernetes.io/ingress.class: traefik
        cert-manager.io/cluster-issuer: letsencrypt-prod
        traefik.ingress.kubernetes.io/router.middlewares: default-redirect-https@kubernetescrd
        traefik.frontend.rule.type: PathPrefix
    spec:
      rules:
      - http:
          paths:
          - path: /
            backend:
              serviceName: smbdxfortunes
              servicePort: 80
          - path: /smbdxfortunes
            backend:
              serviceName: smbdxfortunes
              servicePort: 80
          - path: /pixy
            backend:
              serviceName: pixy
              servicePort: 80
      tls:
        - secretName: nullset2-tls
          hosts:
            - ${DOMAIN}