docs: update Docker deployment architecture

This commit is contained in:
Nice Try
2026-06-26 10:03:21 +00:00
parent b6705547ca
commit cc298b3bc9
4 changed files with 106 additions and 85 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
DATABASE_URL="file:./dev.db" DATABASE_URL="file:/app/prisma/data/dev.db"
COURSES_ROOT="./My_Courses" COURSES_ROOT="/app/My_Courses"
NEXT_PUBLIC_APP_URL="http://localhost:6969" NEXT_PUBLIC_APP_URL="http://localhost:6969"
QUIZAPI_KEY="" QUIZAPI_KEY=""
+87 -64
View File
@@ -31,6 +31,7 @@
- [Tech Stack](#tech-stack) - [Tech Stack](#tech-stack)
- [Quick Start: Docker Hub](#quick-start-docker-hub) - [Quick Start: Docker Hub](#quick-start-docker-hub)
- [Other Deployment Options](#other-deployment-options) - [Other Deployment Options](#other-deployment-options)
- [CI/CD Automation](#cicd-automation)
- [Configuration](#configuration) - [Configuration](#configuration)
- [Course Folder Structure](#course-folder-structure) - [Course Folder Structure](#course-folder-structure)
- [Data & Persistence](#data--persistence) - [Data & Persistence](#data--persistence)
@@ -170,7 +171,7 @@ Deploy Docker Hub / Docker Compose recommended; local Node.js supported
Docker is the recommended way to run OfflineAcademy. Docker is the recommended way to run OfflineAcademy.
It avoids local Node.js setup, uses the published image, and keeps your courses/database mounted outside the container. It avoids local Node.js setup, uses the published image, and keeps your courses and database safely mounted outside the container.
### Prerequisites ### Prerequisites
@@ -181,7 +182,7 @@ It avoids local Node.js setup, uses the published image, and keeps your courses/
### 1. Create an app folder ### 1. Create an app folder
```bash ```bash
mkdir -p offlineacademy/My_Courses offlineacademy/prisma mkdir -p offlineacademy/My_Courses offlineacademy/prisma_data
cd offlineacademy cd offlineacademy
``` ```
@@ -192,33 +193,22 @@ curl -fsSL -o docker-compose.yml https://raw.githubusercontent.com/nicetry247/of
curl -fsSL -o .env https://raw.githubusercontent.com/nicetry247/offlineacademy/main/.env.example curl -fsSL -o .env https://raw.githubusercontent.com/nicetry247/offlineacademy/main/.env.example
``` ```
### 3. Create the SQLite database file and set bind-mount permissions ### 3. Start OfflineAcademy
```bash ```bash
touch prisma/dev.db
chmod -R a+rX My_Courses
chmod 664 prisma/dev.db
```
Docker bind mounts keep the host filesystem permissions. Creating `My_Courses` and `prisma/dev.db` before `docker compose up` prevents Docker from creating them as `root`, and the `chmod` commands make the course folder readable by the container.
### 4. Start OfflineAcademy
```bash
docker compose pull
docker compose up -d docker compose up -d
``` ```
Open: Open:
```text ```text
http://localhost:6767 http://localhost:6969
``` ```
For another device on your LAN, replace `localhost` with your server IP: For another device on your LAN, replace `localhost` with your server IP:
```text ```text
http://YOUR_SERVER_IP:6767 http://YOUR_SERVER_IP:6969
``` ```
### Docker Hub Image ### Docker Hub Image
@@ -254,11 +244,26 @@ Use this if you want to modify the app and build your own image locally.
git clone https://github.com/nicetry247/offlineacademy.git git clone https://github.com/nicetry247/offlineacademy.git
cd offlineacademy cd offlineacademy
cp .env.example .env cp .env.example .env
mkdir -p My_Courses prisma mkdir -p My_Courses prisma_data
touch prisma/dev.db
docker compose up --build -d docker compose up --build -d
``` ```
The source-build Compose file uses the same runtime layout as the Docker Hub deployment:
```yaml
ports:
- "6969:6767"
environment:
DATABASE_URL: file:/app/prisma/data/dev.db
COURSES_ROOT: /app/My_Courses
NEXT_PUBLIC_APP_URL: http://localhost:6969
volumes:
- ./My_Courses:/app/My_Courses
- ./prisma_data:/app/prisma/data
```
The `prisma_data` directory safely persists the SQLite database. The container creates and manages `dev.db` inside `/app/prisma/data`, so users do not need to pre-create an empty database file.
### Local Node.js development ### Local Node.js development
Use this for development, debugging, or source-level customization. Use this for development, debugging, or source-level customization.
@@ -285,12 +290,14 @@ cp .env.example .env
Edit `.env` if needed: Edit `.env` if needed:
```env ```env
DATABASE_URL="file:./dev.db" DATABASE_URL="file:/app/prisma/data/dev.db"
COURSES_ROOT="./My_Courses" COURSES_ROOT="/app/My_Courses"
NEXT_PUBLIC_APP_URL="http://localhost:6767" NEXT_PUBLIC_APP_URL="http://localhost:6969"
QUIZAPI_KEY="" QUIZAPI_KEY=""
``` ```
For non-Docker local Node.js development, use paths that exist on your local machine, such as `DATABASE_URL="file:./prisma/dev.db"` and `COURSES_ROOT="./My_Courses"`.
#### 3. Install dependencies #### 3. Install dependencies
```bash ```bash
@@ -316,20 +323,40 @@ Place your course folders inside `My_Courses`.
```bash ```bash
npm run build npm run build
npx next start -p 6767 npx next start -p 6969
``` ```
### Custom Course Folder ### Custom Course Folder, NAS, or USB Drive
You can store courses anywhere on the host. Update your Compose file and map your folder to `/app/My_Courses` inside the container: Courses should live outside the Docker image. Docker maps a host folder into the container using this pattern:
```text
HOST_PATH:CONTAINER_PATH
```
The container path should stay:
```text
/app/My_Courses
```
For the default local folder, use:
```yaml ```yaml
volumes: volumes:
- /path/to/your/courses:/app/My_Courses - ./My_Courses:/app/My_Courses
- ./prisma/dev.db:/app/prisma/dev.db - ./prisma_data:/app/prisma/data
``` ```
Examples: For a NAS, USB datastore, or other external drive, change only the left side of the course mount:
```yaml
volumes:
- /mnt/usb-datastore/courses:/app/My_Courses
- ./prisma_data:/app/prisma/data
```
More examples:
```yaml ```yaml
# Linux # Linux
@@ -342,36 +369,17 @@ Examples:
- C:/Users/you/Videos/Courses:/app/My_Courses - C:/Users/you/Videos/Courses:/app/My_Courses
``` ```
#### Docker bind-mount permissions Keep the app's internal course setting at the container path:
On Linux, Docker bind mounts use the host folder's existing permissions. If the folder does not exist before `docker compose up`, Docker may create it as `root`, which can make course scanning fail or force manual `chown` later. ```text
/app/My_Courses
Recommended setup:
```bash
mkdir -p My_Courses prisma
touch prisma/dev.db
chmod -R a+rX My_Courses
chmod 664 prisma/dev.db
``` ```
If your course files were copied as `root` or live on a restrictive mounted disk, make them readable by the container: This lets Docker handle the host-to-container translation while OfflineAcademy always scans the same internal path.
```bash
chmod -R a+rX /path/to/your/courses
```
If you enable features that write quiz cache files into course folders, the container also needs write access to the mounted course directory. One option is:
```bash
sudo chown -R 1001:1001 /path/to/your/courses
```
For scan-only use, read access is usually enough.
### Publishing to Docker Hub ### Publishing to Docker Hub
Maintainers can publish manually: Maintainers can publish manually if needed:
```bash ```bash
docker login docker login
@@ -381,14 +389,29 @@ docker push nicetry247/offlineacademy:latest
docker push nicetry247/offlineacademy:1.0.0 docker push nicetry247/offlineacademy:1.0.0
``` ```
You can also automate Docker Hub publishing later with GitHub Actions. To do that, add repository secrets for: ---
## CI/CD Automation
OfflineAcademy includes a GitHub Actions workflow for automated Docker publishing:
```text ```text
DOCKERHUB_USERNAME .github/workflows/docker-build.yml
DOCKERHUB_TOKEN
``` ```
Then add a workflow that builds and pushes `nicetry247/offlineacademy:latest` on pushes to `main` and version tags like `v1.0.0`. When changes are pushed to the `main` branch, the workflow builds the standalone Next.js Docker image and pushes it directly to Docker Hub:
```text
nicetry247/offlineacademy
```
Version tags are supported too. Cutting a tag such as:
```text
v1.0.0
```
publishes the matching Docker image tag alongside `latest`. This keeps the public Docker Hub image aligned with the source repository without requiring manual release builds.
--- ---
@@ -396,9 +419,9 @@ Then add a workflow that builds and pushes `nicetry247/offlineacademy:latest` on
| Variable | Required | Purpose | Example | | Variable | Required | Purpose | Example |
|---|---:|---|---| |---|---:|---|---|
| `DATABASE_URL` | Yes | SQLite database path | `file:./dev.db` | | `DATABASE_URL` | Yes | SQLite database path inside the container | `file:/app/prisma/data/dev.db` |
| `COURSES_ROOT` | Yes | Course folder path inside the app/container | `./My_Courses` | | `COURSES_ROOT` | Yes | Course folder path inside the container | `/app/My_Courses` |
| `NEXT_PUBLIC_APP_URL` | Recommended | Public app URL used by metadata and links | `http://localhost:6767` | | `NEXT_PUBLIC_APP_URL` | Recommended | Public app URL used by metadata and links | `http://localhost:6969` |
| `QUIZAPI_KEY` | Optional | QuizAPI key for quiz generation | `qa_...` | | `QUIZAPI_KEY` | Optional | QuizAPI key for quiz generation | `qa_...` |
Settings can also be managed inside the app at: Settings can also be managed inside the app at:
@@ -434,10 +457,10 @@ Supported video extensions include common browser-playable formats such as `.mp4
OfflineAcademy stores app data locally. OfflineAcademy stores app data locally.
```text ```text
SQLite database prisma/dev.db SQLite database prisma_data/dev.db
Course files My_Courses/ or your configured course mount Course files My_Courses/ or your configured host course mount
Environment .env Environment .env
Quiz cache Course/module folders where generated Quiz cache Course/module folders when generated
``` ```
Important user data: Important user data:
@@ -462,7 +485,7 @@ npm ci
npx prisma generate npx prisma generate
npx prisma db push npx prisma db push
npm run build npm run build
npx next start -p 6767 npx next start -p 6969
``` ```
### Docker ### Docker
@@ -479,12 +502,12 @@ docker compose up --build -d
Back up these items regularly: Back up these items regularly:
```text ```text
prisma/dev.db Main SQLite database prisma_data/dev.db Main SQLite database
.env Local configuration and optional API key .env Local configuration and optional API key
My_Courses/ Your source course library, if not backed up elsewhere My_Courses/ Your source course library, if not backed up elsewhere
``` ```
A simple backup can be as easy as copying `prisma/dev.db` somewhere safe before updates. A simple backup can be as easy as copying `prisma_data/dev.db` somewhere safe before updates.
--- ---
+8 -8
View File
@@ -4,20 +4,20 @@ services:
container_name: offlineacademy container_name: offlineacademy
restart: unless-stopped restart: unless-stopped
ports: ports:
- "6767:6767" # Host:Container
- "6969:6767"
env_file: env_file:
- .env - .env
environment: environment:
NODE_ENV: production NODE_ENV: production
PORT: 6767 PORT: 6767
HOSTNAME: 0.0.0.0 HOSTNAME: 0.0.0.0
DATABASE_URL: file:./dev.db DATABASE_URL: file:/app/prisma/data/dev.db
COURSES_ROOT: ./My_Courses COURSES_ROOT: /app/My_Courses
NEXT_PUBLIC_APP_URL: http://localhost:6767 NEXT_PUBLIC_APP_URL: http://localhost:6969
volumes: volumes:
# Put your course folders wherever you want on the host, # Course folders stay on the host and are mounted into the container.
# then map that folder to /app/My_Courses inside the container.
- ./My_Courses:/app/My_Courses - ./My_Courses:/app/My_Courses
# Persist the SQLite database outside the image. # Directory-based database persistence. The container creates dev.db inside this folder.
- ./prisma/dev.db:/app/prisma/dev.db - ./prisma_data:/app/prisma/data
+8 -10
View File
@@ -7,21 +7,19 @@ services:
restart: unless-stopped restart: unless-stopped
ports: ports:
# Host:Container # Host:Container
- "6969:6969" - "6969:6767"
env_file: env_file:
- .env - .env
environment: environment:
NODE_ENV: production NODE_ENV: production
PORT: 6969 PORT: 6767
HOSTNAME: 0.0.0.0 HOSTNAME: 0.0.0.0
# Points exactly to where the volume is mounted inside the container DATABASE_URL: file:/app/prisma/data/dev.db
DATABASE_URL: file:/app/prisma/dev.db
COURSES_ROOT: /app/My_Courses COURSES_ROOT: /app/My_Courses
# Matches the port mapped to your host machine
NEXT_PUBLIC_APP_URL: http://localhost:6969 NEXT_PUBLIC_APP_URL: http://localhost:6969
volumes: volumes:
# Automatically creates ./My_Courses on the host if it doesn't exist # Course folders stay on the host and are mounted into the container.
- /mnt/usb-datastore/courses:/app/My_Courses - ./My_Courses:/app/My_Courses
# Automatically creates ./prisma_data on the host to hold dev.db safely # Directory-based database persistence. The container creates dev.db inside this folder.
- ./prisma_data:/app/prisma/data - ./prisma_data:/app/prisma/data