mirror of
https://github.com/randyjc/Rahoot.git
synced 2026-03-13 20:15:35 +01:00
feat(docker): update Dockerfile and compose configuration, enhance README for deployment methods
This commit is contained in:
69
.github/workflows/docker-release.yml
vendored
Normal file
69
.github/workflows/docker-release.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
name: Docker Release
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOCKER_PLATFORMS: |
|
||||||
|
linux/amd64
|
||||||
|
linux/arm64
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Extract version and tags
|
||||||
|
run: |
|
||||||
|
if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then
|
||||||
|
VERSION=${GITHUB_REF_NAME#v}
|
||||||
|
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# Extract major.minor (ex: 1.2.3 -> 1.2)
|
||||||
|
MAJOR_MINOR=$(echo $VERSION | cut -d. -f1,2)
|
||||||
|
echo "MAJOR_MINOR=$MAJOR_MINOR" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "VERSION=latest" >> $GITHUB_ENV
|
||||||
|
echo "MAJOR_MINOR=latest" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Extract repository name (lowercase)
|
||||||
|
run: echo "REPO_NAME=$(basename ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
with:
|
||||||
|
platforms: ${{ env.DOCKER_PLATFORMS }}
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
install: true
|
||||||
|
platforms: ${{ env.DOCKER_PLATFORMS }}
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: ${{ env.DOCKER_PLATFORMS }}
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:${{ env.VERSION }}
|
||||||
|
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:${{ env.MAJOR_MINOR }}
|
||||||
|
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:latest
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
build-args: |
|
||||||
|
BUILDKIT_INLINE_CACHE=1
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,2 +1,4 @@
|
|||||||
/node_modules
|
/node_modules
|
||||||
.env
|
.env
|
||||||
|
.secrets
|
||||||
|
release.json
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:24-alpine AS base
|
FROM node:22-alpine AS base
|
||||||
|
|
||||||
# Enable and prepare pnpm via Corepack
|
# Enable and prepare pnpm via Corepack
|
||||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||||
@@ -37,7 +37,7 @@ WORKDIR /app/packages/socket
|
|||||||
RUN if [ -f "tsconfig.json" ]; then pnpm build; fi
|
RUN if [ -f "tsconfig.json" ]; then pnpm build; fi
|
||||||
|
|
||||||
# ----- RUNNER -----
|
# ----- RUNNER -----
|
||||||
FROM node:24-alpine AS runner
|
FROM node:22-alpine AS runner
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Create a non-root user for better security
|
# Create a non-root user for better security
|
||||||
|
|||||||
192
README.md
192
README.md
@@ -1,7 +1,10 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img width="450" height="120" align="center" src="https://raw.githubusercontent.com/Ralex91/Rahoot/main/.github/logo.svg">
|
<img width="450" height="120" align="center" src="https://raw.githubusercontent.com/Ralex91/Rahoot/main/.github/logo.svg">
|
||||||
<br>
|
<br>
|
||||||
<img align="center" src="https://api.visitorbadge.io/api/visitors?path=https://github.com/Ralex91/Rahoot/edit/main/README.md&countColor=%2337d67a">
|
<div align="center">
|
||||||
|
<img alt="Visitor Badge" src="https://api.visitorbadge.io/api/visitors?path=https://github.com/Ralex91/Rahoot/edit/main/README.md&countColor=%2337d67a">
|
||||||
|
<img src="https://img.shields.io/docker/pulls/ralex91/rahoot?style=for-the-badge&logo=docker&color=2496ED" alt="Docker Pulls">
|
||||||
|
</div>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## 🧩 What is this project?
|
## 🧩 What is this project?
|
||||||
@@ -12,93 +15,144 @@ Rahoot is a straightforward and open-source clone of the Kahoot! platform, allow
|
|||||||
|
|
||||||
## ⚙️ Prerequisites
|
## ⚙️ Prerequisites
|
||||||
|
|
||||||
- Node.js version 20 or higher
|
Choose one of the following deployment methods:
|
||||||
|
|
||||||
|
### Without Docker
|
||||||
|
|
||||||
|
- Node.js : version 20 or higher
|
||||||
|
- PNPM : Learn more about [here](https://pnpm.io/)
|
||||||
|
|
||||||
|
### With Docker
|
||||||
|
|
||||||
|
- Docker and Docker Compose
|
||||||
|
|
||||||
## 📖 Getting Started
|
## 📖 Getting Started
|
||||||
|
|
||||||
1. #### Clone the GitHub repository of your project.
|
Choose your deployment method:
|
||||||
```bash
|
|
||||||
git clone https://github.com/Ralex91/Rahoot.git
|
|
||||||
cd ./Rahoot
|
|
||||||
```
|
|
||||||
2. #### Install the dependencies using your preferred package manager
|
|
||||||
|
|
||||||
```bash
|
### 🐳 Using Docker (Recommended)
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
<br>
|
Using Docker Compose (recommended):
|
||||||
<hr>
|
|
||||||
|
|
||||||
## 📦 Running the Application in Production Mode:
|
You can find the docker compose configuration in the repository:
|
||||||
|
[docker-compose.yml](/compose.yml)
|
||||||
1. #### Check websocket connfiguration in [config.mjs](config.mjs)
|
|
||||||
|
|
||||||
If you want the client to connect directly to the websocket server, edit the [config.mjs](config.mjs) file and change the localhost to your public IP address.
|
|
||||||
|
|
||||||
```js
|
|
||||||
export const WEBSOCKET_PUBLIC_URL = "http://1.2.3.4:3100/"
|
|
||||||
export const WEBSOCKET_SERVER_PORT = 3100
|
|
||||||
|
|
||||||
// Rest of the config ...
|
|
||||||
```
|
|
||||||
|
|
||||||
2. #### Start the application
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run all
|
|
||||||
```
|
|
||||||
|
|
||||||
## ⚙️ Running the Application in Development Mode:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run all-dev
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🔧 Configuration
|
Or using Docker directly:
|
||||||
|
|
||||||
Configuration can be found in [config.mjs](config.mjs)
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
-p 3000:3000 \
|
||||||
|
-p 3001:3001 \
|
||||||
|
-v ./config:/app/config \
|
||||||
|
-e WEB_ORIGIN=http://localhost:3000 \
|
||||||
|
-e SOCKET_URL=http://localhost:3001 \
|
||||||
|
ralex91/rahoot:latest
|
||||||
|
```
|
||||||
|
|
||||||
```js
|
The application will be available at:
|
||||||
const QUIZZ_CONFIG = {
|
|
||||||
password: "PASSWORD", // Manager password
|
- Web Interface: http://localhost:3000
|
||||||
subject: "Adobe", // Subject of the quiz
|
- WebSocket Server: ws://localhost:3001
|
||||||
questions: [
|
|
||||||
{ // Example question
|
### 🛠️ Without Docker
|
||||||
question: "What is good answer ?", // Question
|
|
||||||
answers: [ // Possible answers
|
1. Clone the repository:
|
||||||
"No",
|
|
||||||
"Yes",
|
```bash
|
||||||
"No",
|
git clone https://github.com/Ralex91/Rahoot.git
|
||||||
"No",
|
cd ./Rahoot
|
||||||
],
|
```
|
||||||
image:
|
|
||||||
"https://images.unsplash.com/....", // Image URL (optional)
|
2. Install dependencies:
|
||||||
solution: 1, // Index of the correct answer (index starts at 0)
|
|
||||||
cooldown: 5, // Show question cooldown in seconds
|
```bash
|
||||||
time: 15, // Time to answer in seconds
|
pnpm install
|
||||||
},
|
```
|
||||||
...
|
|
||||||
],
|
3. Change the environment variables in the `.env` file
|
||||||
|
|
||||||
|
4. Build and start the application:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Development mode
|
||||||
|
pnpm run dev
|
||||||
|
|
||||||
|
# Production mode
|
||||||
|
pnpm run build
|
||||||
|
pnpm start
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ Configuration
|
||||||
|
|
||||||
|
The configuration is split into two main parts:
|
||||||
|
|
||||||
|
### 1. Game Configuration (`config/game.json`)
|
||||||
|
|
||||||
|
Main game settings:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"managerPassword": "PASSWORD",
|
||||||
|
"music": true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🤔 How to use
|
Options:
|
||||||
|
|
||||||
- Go to [https://localhost:3000/manager](https://localhost:3000/manager) enter manager password.
|
- `managerPassword`: The master password for accessing the manager interface
|
||||||
|
- `music`: Enable/disable game music
|
||||||
|
|
||||||
- Share link [https://localhost:3000/](https://localhost:3000/) and code on manager screen with your friends and get ready to play.
|
### 2. Quiz Configuration (`config/quizz/*.json`)
|
||||||
|
|
||||||
- Once everyone is ready, start the game with button on the top left of the screen of manager.
|
Create your quiz files in the `config/quizz/` directory. You can have multiple quiz files and select which one to use when starting a game.
|
||||||
|
|
||||||
|
Example quiz configuration (`config/quizz/example.json`):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"subject": "Example Quiz",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"question": "What is the correct answer?",
|
||||||
|
"answers": ["No", "Yes", "No", "No"],
|
||||||
|
"image": "https://images.unsplash.com/....",
|
||||||
|
"solution": 1,
|
||||||
|
"cooldown": 5,
|
||||||
|
"time": 15
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Quiz Options:
|
||||||
|
|
||||||
|
- `subject`: Title/topic of the quiz
|
||||||
|
- `questions`: Array of question objects containing:
|
||||||
|
- `question`: The question text
|
||||||
|
- `answers`: Array of possible answers (2-4 options)
|
||||||
|
- `image`: Optional URL for question image
|
||||||
|
- `solution`: Index of correct answer (0-based)
|
||||||
|
- `cooldown`: Time in seconds before showing the question
|
||||||
|
- `time`: Time in seconds allowed to answer
|
||||||
|
|
||||||
|
## 🎮 How to Play
|
||||||
|
|
||||||
|
1. Access the manager interface at http://localhost:3000/manager
|
||||||
|
2. Enter the manager password (defined in quiz config)
|
||||||
|
3. Share the game URL (http://localhost:3000) and room code with participants
|
||||||
|
4. Wait for players to join
|
||||||
|
5. Click the start button to begin the game
|
||||||
|
|
||||||
## 📝 Contributing
|
## 📝 Contributing
|
||||||
|
|
||||||
- Create a fork
|
1. Fork the repository
|
||||||
|
2. Create a new branch (e.g., `feat/my-feature`)
|
||||||
|
3. Make your changes
|
||||||
|
4. Create a pull request
|
||||||
|
5. Wait for review and merge
|
||||||
|
|
||||||
- Create work branch (Example: githubUsername/featureName).
|
For bug reports or feature requests, please [create an issue](https://github.com/Ralex91/Rahoot/issues).
|
||||||
|
|
||||||
- Commit and push your changes in the work branch.
|
|
||||||
|
|
||||||
- Open a pull request.
|
|
||||||
|
|
||||||
- Your pull request would be merged and changes will be reflected in the main repository.
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ version: "3.8"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
rahoot:
|
rahoot:
|
||||||
image: rahoot
|
image: ralex91/rahoot:latest
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
- "3001:3001"
|
- "3001:3001"
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ export default function ManagerGame() {
|
|||||||
useEvent(
|
useEvent(
|
||||||
"manager:successReconnect",
|
"manager:successReconnect",
|
||||||
({ gameId, status, players, currentQuestion }) => {
|
({ gameId, status, players, currentQuestion }) => {
|
||||||
console.log("manager:successReconnect", gameId)
|
|
||||||
setGameId(gameId)
|
setGameId(gameId)
|
||||||
setStatus(status.name, status.data)
|
setStatus(status.name, status.data)
|
||||||
setPlayers(players)
|
setPlayers(players)
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ export default function Podium({ data: { subject, top } }: Props) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(apparition)
|
|
||||||
|
|
||||||
switch (apparition) {
|
switch (apparition) {
|
||||||
case 4:
|
case 4:
|
||||||
sfxRoolStop()
|
sfxRoolStop()
|
||||||
|
|||||||
Reference in New Issue
Block a user