“Internal server error” or “404 Page Not Found” after running custom Frappe LMS Docker setup


“Internal server error” or “404 Page Not Found” after running custom Frappe LMS Docker setup

Image

Image


Description:

Hello,

I encountered an issue while setting up my Frappe LMS project using a custom Docker image GitHub - Ph0en1XXX/lms. After running the command:
docker compose -f /root/learning_prod_setup-compose.yml up -d,
the application starts without visible errors. However, when I try to access it via the browser, I get the following error:

404 Page Not Found

Screenshots of the error:
Image 1
Image 2


Steps to Reproduce:

  1. Fork the repository.
  2. use LMS scitp to download frappe/lms config
  3. Edit learning_prod_setup-compose.yml to replace the GitHub image with your own.
  4. Run the command: docker compose -f /root/learning_prod_setup-compose.yml up -d4. Open a browser and navigate to https://<host>:<port>.

Troubleshooting Steps Tried:

  1. Performed a full reinstall using the installation script from Frappe LMS:
    wget https://frappe.io/easy-install.py
    
    python3 ./easy-install.py deploy \
        --project=learning_prod_setup \
        --email=myemail@test.com \
        --image=ghcr.io/ph0en1xxx/lms \
        --version=stable \
        --app=lms \
        --sitename=mysite.com
    
  2. Removed Redis cache:
    docker volume rm learning_prod_setup_redis-cache-data
    
  3. Removed all Docker volumes.
  4. Verified container health using docker ps.

Expected Behavior:

The application should load correctly, displaying the main page.


Actual Behavior:

The browser displays a 404 Page Not Found or Internal server error error instead of loading the application.


Environment:

  • OS: Ubuntu 22.04, 24.04, 24.10
  • Frappe LMS Version: v2.21.0

Configuration Files:

docker-compose.yml (if relevant):

# name: learning_prod_setup
services:
  backend:
    depends_on:
      configurator:
        condition: service_completed_successfully
        required: true
    image: ghcr.io/ph0en1xxx/lms:stable
    networks:
      default: null
    platform: linux/amd64
    pull_policy: missing
    volumes:
      - type: volume
        source: sites
        target: /home/frappe/frappe-bench/sites
        volume: {}
  configurator:
    command:
      - |
        ls -1 apps > sites/apps.txt; bench set-config -g db_host $$DB_HOST; bench set-config -gp db_port $$DB_PORT; bench set-config -g redis_cache "redis://$$REDIS_CACHE"; bench set-config -g redis_queue "redis://$$REDIS_QUEUE"; bench set-config -g redis_socketio "redis://$$REDIS_QUEUE"; bench set-config -gp socketio_port $$SOCKETIO_PORT;
    depends_on:
      db:
        condition: service_healthy
        required: true
      redis-cache:
        condition: service_started
        required: true
      redis-queue:
        condition: service_started
        required: true
    entrypoint:
      - bash
      - -c
    environment:
      DB_HOST: db
      DB_PORT: "3306"
      REDIS_CACHE: redis-cache:6379
      REDIS_QUEUE: redis-queue:6379
      SOCKETIO_PORT: "9000"
    image: ghcr.io/ph0en1xxx/lms:stable
    networks:
      default: null
    platform: linux/amd64
    pull_policy: missing
    volumes:
      - type: volume
        source: sites
        target: /home/frappe/frappe-bench/sites
        volume: {}
  cron:
    command:
      - daemon
      - --docker
    depends_on:
      scheduler:
        condition: service_started
        required: true
    image: mcuadros/ofelia:latest
    networks:
      default: null
    volumes:
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock
        read_only: true
        bind:
          create_host_path: true
  db:
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --skip-character-set-client-handshake
      - --skip-innodb-read-only-compressed
    environment:
      MYSQL_ROOT_PASSWORD:123
    healthcheck:
      test:
        - CMD-SHELL
        - mysqladmin ping -h localhost --password=123
      interval: 1s
      retries: 20
    image: mariadb:10.6
    networks:
      default: null
    volumes:
      - type: volume
        source: db-data
        target: /var/lib/mysql
        volume: {}
  frontend:
    command:
      - nginx-entrypoint.sh
    depends_on:
      backend:
        condition: service_started
        required: true
      websocket:
        condition: service_started
        required: true
    environment:
      BACKEND: backend:8000
      CLIENT_MAX_BODY_SIZE: 50m
      FRAPPE_SITE_NAME_HEADER: $$host
      PROXY_READ_TIMEOUT: "120"
      SOCKETIO: websocket:9000
      UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
      UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
      UPSTREAM_REAL_IP_RECURSIVE: "off"
    image: ghcr.io/ph0en1xxx/lms:stable
    labels:
      traefik.enable: "true"
      traefik.http.routers.frontend-http.entrypoints: websecure
      traefik.http.routers.frontend-http.rule: Host(`enlightrussia.ru`)
      traefik.http.routers.frontend-http.tls.certresolver: main-resolver
      traefik.http.services.frontend.loadbalancer.server.port: "8080"
    networks:
      default: null
    platform: linux/amd64
    pull_policy: missing
    volumes:
      - type: volume
        source: sites
        target: /home/frappe/frappe-bench/sites
        volume: {}
  proxy:
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
      - --entrypoints.websecure.address=:443
      - --certificatesResolvers.main-resolver.acme.httpChallenge=true
      - --certificatesResolvers.main-resolver.acme.httpChallenge.entrypoint=web
      - --certificatesResolvers.main-resolver.acme.email=nik_skorikov@mail.ru
      - --certificatesResolvers.main-resolver.acme.storage=/letsencrypt/acme.json
    image: traefik:v2.11
    networks:
      default: null
    ports:
      - mode: ingress
        target: 80
        published: "80"
        protocol: tcp
      - mode: ingress
        target: 443
        published: "443"
        protocol: tcp
    volumes:
      - type: volume
        source: cert-data
        target: /letsencrypt
        volume: {}
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock
        read_only: true
        bind:
          create_host_path: true
  queue-long:
    command:
      - bench
      - worker
      - --queue
      - long,default,short
    depends_on:
      configurator:
        condition: service_completed_successfully
        required: true
    image: ghcr.io/ph0en1xxx/lms:stable
    networks:
      default: null
    platform: linux/amd64
    pull_policy: missing
    volumes:
      - type: volume
        source: sites
        target: /home/frappe/frappe-bench/sites
        volume: {}
  queue-short:
    command:
      - bench
      - worker
      - --queue
      - short,default
    depends_on:
      configurator:
        condition: service_completed_successfully
        required: true
    image: ghcr.io/ph0en1xxx/lms:stable
    networks:
      default: null
    platform: linux/amd64
    pull_policy: missing
    volumes:
      - type: volume
        source: sites
        target: /home/frappe/frappe-bench/sites
        volume: {}
  redis-cache:
    image: redis:6.2-alpine
    networks:
      default: null
    volumes:
      - type: volume
        source: redis-cache-data
        target: /data
        volume: {}
  redis-queue:
    image: redis:6.2-alpine
    networks:
      default: null
    volumes:
      - type: volume
        source: redis-queue-data
        target: /data
        volume: {}
  scheduler:
    command:
      - bench
      - schedule
    depends_on:
      configurator:
        condition: service_completed_successfully
        required: true
    image: ghcr.io/ph0en1xxx/lms:stable
    labels:
      ofelia.enabled: "true"
      ofelia.job-exec.datecron.command: bench --site all backup
      ofelia.job-exec.datecron.schedule: '@every 6h'
      ofelia.job-exec.datecron.user: frappe
    networks:
      default: null
    platform: linux/amd64
    pull_policy: missing
    volumes:
      - type: volume
        source: sites
        target: /home/frappe/frappe-bench/sites
        volume: {}
  websocket:
    command:
      - node
      - /home/frappe/frappe-bench/apps/frappe/socketio.js
    depends_on:
      configurator:
        condition: service_completed_successfully
        required: true
    image: ghcr.io/ph0en1xxx/lms:stable
    networks:
      default: null
    platform: linux/amd64
    pull_policy: missing
    volumes:
      - type: volume
        source: sites
        target: /home/frappe/frappe-bench/sites
        volume: {}
networks:
  default:
    name: learning_prod_setup_default
volumes:
  cert-data:
    name: learning_prod_setup_cert-data
  db-data:
    name: learning_prod_setup_db-data
  redis-cache-data:
    name: learning_prod_setup_redis-cache-data
  redis-queue-data:
    name: learning_prod_setup_redis-queue-data
  sites:
    name: learning_prod_setup_sites
x-backend-defaults:
  depends_on:
    configurator:
      condition: service_completed_successfully
  image: ghcr.io/ph0en1xxx/lms:stable
  pull_policy: missing
  volumes:
    - sites:/home/frappe/frappe-bench/sites
x-customizable-image:
  image: ghcr.io/ph0en1xxx/lms:stable
  pull_policy: missing
x-depends-on-configurator:
  depends_on:
    configurator:
      condition: service_completed_successfully


Additional Information:

  • The issue occurs both with and without a proxy setup.
  • Containers are running without visible errors (docker ps shows active containers).
  • The idea was to fork lms repository and make own changes