How to convert this Nginx config to Kubernetes Nginx Ingress?

I have a django application which is served as wsgi with gunicorn.

gunicorn --workers=4 --bind :8000 backend.wsgi

In my local development environment I used docker-compose to setup an Nginx reverse-proxy in front of it to serve static files, like the following (I've omitted env files and other irrelevant stuff). I'm setting DJANGO_ROOT_URL to use a custom path (e.g. "/be/") in front of the requests. The WORKDIR for every Django files is /backend on the Docker container and collecting the static files during build time they're placed as expected inside /backend/static.

  backend:
    image: backend-image
    volumes:
      - ./data/backend/static:/backend/static
    ports:
      - "9999:8000"
    environment:
      - DJANGO_ROOT_URL=/be/

  nginx:
    image: nginx
    volumes:
      - ./django/nginx.conf:/etc/nginx/templates/default.conf.template
      - ./data/backend/static:/static
    ports:
      - "8000:80"
    environment:
      - DJANGO_ROOT_URL=/be/
      # To show Nginx logs
      - ACCESS_LOG=${ACCESS_LOG:-off}
    depends_on:
      - backend

And this is the configuration:

upstream django {
    server backend:8000;
}

server {

    listen 80;

    # Max upload size
    client_max_body_size 100M;

    # Suppress log (on/off)
    access_log ${ACCESS_LOG};

    location ${DJANGO_ROOT_URL} {
        rewrite ${DJANGO_ROOT_URL}(.*) /$1  break;

        proxy_pass http://django;
        proxy_redirect off;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host; # to add port to DRF resources and allow CSRF
        proxy_set_header Connection "";
    }

    location ${DJANGO_ROOT_URL}static {
        rewrite ${DJANGO_ROOT_URL}(.*) /$1  break;

        root /;
    }
}

This works as expected, when going for instance to http://localhost:8000/be/admin I see that the static files are correctly served.

Now, I need to put this together on a Kubernetes environment. Since I've already set up the Nginx Ingress Controller, I thought it would be unnecessary to put another nginx instance inside the pod since I can use directly an Ingress resource. This is my k8s script which should deploy the Django app:

apiVersion: v1
kind: ConfigMap
metadata:
  name: backend-config
data:
  DJANGO_ROOT_URL: "/be/"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  labels:
    app: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      serviceAccountName: cluster-manager
      containers:
        - name: backend
          image: backend-test
          imagePullPolicy: "Always"
          envFrom:
            - configMapRef:
                name: backend-config
---
apiVersion: v1
kind: Service
metadata:
  name: backend
  labels:
    app: backend
spec:
  type: LoadBalancer
  ports:
    - name: http
      port: 8000
      protocol: TCP
      targetPort: 8000
  selector:
    app: backend
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: backend
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/app-root: /backend
spec:
  tls:
    - hosts:
        - backend.192.168.49.2.nip.io
  rules:
    - host: backend.192.168.49.2.nip.io
      http:
        paths:
          - path: /be(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: backend
                port:
                  number: 8000
          - path: /be/static(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: backend
                port:
                  number: 8000

This works but static files are not served at all and cannot be found. Is there a better/correct way to convert the docker-compose setup on Kubernetes?

Back to Top