Docker
Updated Oct 18, 2026
Quizora ships with a ready-to-use Docker setup for local development, staging, or self-hosted production. Docker runs PHP 8.3, Nginx, MySQL 8, Redis, and a queue worker — no manual PHP or Node.js installation required on your machine.
Prefer the web installer?: If you are deploying to shared hosting (cPanel) or a traditional VPS, use the Installation Guide instead. Docker is optional.
Prerequisites
| Requirement | Version |
|---|---|
| Docker | 24+ |
| Docker Compose | v2+ (docker compose command) |
| RAM | 1 GB+ recommended |
| Disk | 2 GB+ free |
What's included
| Service | Role |
|---|---|
app |
PHP-FPM 8.3 — runs Laravel |
web |
Nginx — serves public/ on port 8080 |
mysql |
MySQL 8.0 database |
redis |
Cache, sessions, and queue driver |
queue |
Background jobs (payments, emails, certificates) |
Frontend assets (Vite) are built automatically inside the Docker image — you do not need Node.js on your host.
Step 1 — Extract the files
- Download Quizora from your CodeCanyon account.
- Extract the zip and
cdinto the project root (the folder containingdocker-compose.yml).
Step 2 — Review environment config
Quizora includes a Docker-specific environment file: .env.docker.
It is pre-configured with Docker service hostnames:
| Variable | Value | Why |
|---|---|---|
APP_URL |
http://localhost:8080 |
Matches the Nginx port mapping |
DB_HOST |
mysql |
Docker service name (not 127.0.0.1) |
REDIS_HOST |
redis |
Docker service name |
CACHE_STORE |
redis |
Recommended for Docker |
SESSION_DRIVER |
redis |
Recommended for Docker |
QUEUE_CONNECTION |
redis |
Required for the queue worker |
docker-compose.yml mounts .env.docker into the container as .env (Laravel and Artisan require a file on disk).
.env.dockermust exist: Create it from the template if missing:cp .env.example .env.dockerthen adjust Docker values (DB_HOST=mysql,REDIS_HOST=redis, etc.).
Customising credentials: Database credentials in
.env.dockermust matchdocker-compose.yml:
- Database:
quizora- Username:
quizora- Password:
secretChange both files together if you want different passwords.
Platform settings (OpenAI, payments, storage, Google login, and license) are configured in Admin → Settings after install — not in .env.docker.
Step 3 — Build and start
docker compose build
docker compose up -d
Wait until all services are running:
docker compose ps
You should see 5 containers. Example output:
NAME IMAGE STATUS PORTS
quizora-web nginx:1.27-alpine Up 0.0.0.0:8080->80/tcp
quizora-app quizora-app Up 9000/tcp
quizora-mysql mysql:8.0 Up (healthy) 0.0.0.0:3306->3306/tcp
quizora-redis redis:7-alpine Up 6379/tcp
quizora-queue quizora-queue Up 9000/tcp
| Container | Exposes host port? | Notes |
|---|---|---|
quizora-web |
Yes — 8080 |
Open the app at http://localhost:8080 |
quizora-mysql |
Yes — 3306 |
Optional; for local DB tools only |
quizora-app |
No | PHP-FPM (internal, used by Nginx) |
quizora-redis |
No | Internal cache/queue |
quizora-queue |
No | Background worker |
Docker Desktop shows one row with no ports?: Docker Desktop groups Compose projects into a single stack row named
quizora. Ports and image names appear as-on that parent row — this is normal.
- Click the arrow (›) on the left of the
quizorarow to expand the stack.- You should see all five containers listed individually.
quizora-webshows port 8080:80;quizora-mysqlshows 3306:3306.app,redis, andqueueintentionally have no host ports (they only talk inside the Docker network).Use Containers → search
quizoraor rundocker compose psin the terminal for the clearest view.
After changing docker-compose.yml, apply updates with:
docker compose up -d
Step 4 — First-time setup
Generate an application encryption key (writes APP_KEY into .env.docker on your host):
docker compose exec app php artisan key:generate
file_get_contents(.env): No such file: This means the.envmount is missing or.env.dockerdoes not exist on your host. Ensure.env.dockeris present, then rundocker compose up -dagain so the volume mount is applied.
If you get a permission denied error writing .env, run once as root:
docker compose exec -u root app php artisan key:generate
Then choose one of the following:
Option A — Web installer (recommended)
- Open
http://localhost:8080/install - Follow the wizard (same as a normal install)
- Use these database settings when prompted:
| Field | Value |
|---|---|
| Host | mysql |
| Port | 3306 |
| Database | quizora |
| Username | quizora |
| Password | secret |
Option B — Command line
docker compose exec app php artisan migrate --force
docker compose exec app php artisan db:seed --class=DemoSeeder # optional demo data
Step 5 — Log in
Open http://localhost:8080 and sign in:
| Panel | URL |
|---|---|
| Customer portal | http://localhost:8080 |
| Creator panel | http://localhost:8080/creator |
| Admin panel | http://localhost:8080/admin |
If you used the installer, log in with the admin email and password you set in Step 4.
First login checklist: Go to Admin → Settings and configure your logo, OpenAI key, payment gateways, and email (or keep
MAIL_MAILER=login.env.dockerfor local testing).
Useful commands
# List containers, ports, and status (best way to verify the stack)
docker compose ps
# View logs
docker compose logs -f app
docker compose logs -f web
docker compose logs -f queue
# Run artisan commands
docker compose exec app php artisan migrate
docker compose exec app php artisan cache:clear
# Stop all containers
docker compose down
# Stop and remove database volumes (fresh start)
docker compose down -v
Updating Quizora
- Back up your database and
storage/app/folder. - Pull or replace the application files (keep
.env.docker). - Rebuild and restart:
docker compose build
docker compose up -d
docker compose exec app php artisan migrate --force
Rebuilding frontend assets: If you change CSS or JavaScript, rebuild the image. If the browser still shows old styles, remove the public volume and start fresh:
docker compose down docker volume rm quizora_public_assets # prefix may vary; run `docker volume ls` to check docker compose up -d --build
Production notes
The included docker-compose.yml is optimised for local development. For production:
- Set
APP_ENV=productionandAPP_DEBUG=falsein.env.docker - Put a reverse proxy (Traefik, Caddy, or cloud load balancer) in front of Nginx with HTTPS
- Remove the MySQL
3306port mapping (keep it internal only) - Use strong database passwords
- Add a scheduler container if you use scheduled tasks:
php artisan schedule:work - Persist
storage/app/(uploads, certificates) via a volume or configure S3 in Admin → Settings → Storage
Troubleshooting
| Problem | Solution |
|---|---|
Docker Desktop shows one quizora row, ports are - |
Expand the stack row (›) — see Step 3. Only quizora-web and quizora-mysql expose host ports. |
file_get_contents(.env): No such file |
Create .env.docker, then docker compose up -d (mounts it as .env inside containers). |
Connection refused to database |
Wait for MySQL healthcheck; confirm DB_HOST=mysql in .env.docker |
| Blank page or 500 error | Run docker compose exec app php artisan key:generate |
| Queue jobs not processing | Check docker compose logs queue; confirm Redis is running |
| CSS/JS missing | Rebuild: docker compose build --no-cache |
| Port 8080 already in use | Change "8080:80" in docker-compose.yml and update APP_URL |
| Installer Redis warning | Safe to ignore — Redis is included in the Docker stack |
Changes to docker-compose.yml not applied |
Run docker compose up -d (not just restart from Docker Desktop) |
File reference
| File | Purpose |
|---|---|
Dockerfile |
Multi-stage image (PHP extensions + Composer + Vite build + PHP-FPM) |
docker-compose.yml |
Five services: quizora-app, quizora-web, quizora-mysql, quizora-redis, quizora-queue |
docker/nginx/default.conf |
Nginx config (includes SSE support for AI streaming) |
.env.docker |
Docker environment file — mounted as /var/www/html/.env in app and queue |
.dockerignore |
Excludes vendor/, node_modules/, etc. from the build |
For server requirements without Docker, see Requirements.