DPOS is a multi-company POS application built with Laravel, FrankenPHP, MySQL, Redis, and Vite. The repository is structured to run primarily through Docker Compose for both development and production-style deployments.
- Multi-company POS workflow
- Product, warehouse, and stock management
- Sales, discounts, payments, and receipts
- Role and permission management
- Reporting and export support
- Realtime features through Laravel Reverb
- Laravel 11
- PHP 8.2+ at the application level
- FrankenPHP
php8.4-alpinein Docker - MySQL 8.0
- Redis 7
- Vite 7
- Tailwind via Vite
- Docker Engine
- Docker Compose plugin (
docker compose)
- PHP 8.2+
- Composer
- Node.js 22+
- MySQL 8.0+
- Redis 7+
.
├── application/ # Laravel application
├── build/
│ ├── Dockerfile # Default app image build
│ ├── Dockerfile.multi-pm # App image build with npm/yarn/pnpm lockfile support
│ ├── entrypoint.sh # Container startup logic
│ ├── nginx/default.conf # Nginx reverse proxy config
│ └── php/
│ ├── opcache.dev.ini # Dev PHP cache settings
│ └── opcache.ini # Production PHP cache settings
├── docker-compose.yml # Development stack
├── docker-compose.prod.yml # Production-oriented stack
├── .env.example # Root compose environment template
└── README.md
The root .env file is consumed by Docker Compose.
Create it from .env.example:
cp .env.example .envExample local values:
DB_CONNECTION=mysql
DB_PORT=3306
DB_FORWARD_PORT=3307
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
APP_PATH=
NGINX_APP_PORT=80
APP_PORT=80
REDIS_FORWARD_PORT=6380
REVERB_CONNECTION=app
REVERB_PORT=8001
APP_ENV=localImportant variables:
APP_PORT: host port exposed by NginxDB_FORWARD_PORT: host port exposed by MySQL in developmentREDIS_FORWARD_PORT: host port exposed by Redis in developmentDB_DATABASE,DB_USERNAME,DB_PASSWORD: database credentials used by both app and MySQL services
Start the local stack:
docker compose up -d --buildOpen:
http://127.0.0.1
Development stack behavior in docker-compose.yml:
appis built frombuild/Dockerfileapplication/is bind-mounted into the containervendor,node_modules, andpublic/buildare stored in named volumes- PHP opcache is overridden with
build/php/opcache.dev.iniso PHP file changes are revalidated - MySQL is exposed on
DB_FORWARD_PORT - Redis is exposed on
REDIS_FORWARD_PORT
The app entrypoint in build/entrypoint.sh currently does the following on container start:
- ensures the database exists
- clears Laravel caches
- runs
php artisan migrate:fresh --seedwhenAPP_ENVis notproduction - starts FrankenPHP and Laravel Reverb
This means restarting the app container in development resets the database.
PHP file changes should be reflected without rebuilding because development opcache timestamp validation is enabled.
If changes are not visible:
docker compose up -d --force-recreate app nginx
docker compose exec app frankenphp php-cli artisan optimize:clearVite assets are expected at application/public/build.
Current Docker behavior:
- assets are built into the image during Docker build
- the development stack keeps
public/buildin a named volume - the app container itself is not a Node runtime for day-to-day asset compilation
If the Vite manifest is missing, rebuild the app image:
docker compose up -d --build appThe production-oriented stack is defined in docker-compose.prod.yml.
Start it with a dedicated production env file:
docker compose --env-file .env.production -f docker-compose.prod.yml up -d --buildProduction stack behavior:
appis built frombuild/Dockerfile.multi-pm- no application source bind mount is used
- MySQL and Redis use named volumes only
- only the web port is published
APP_ENV=productionandAPP_DEBUG=falseare forced in Compose- entrypoint runs
php artisan migrate --forcein production
Do not reuse the local .env for production. Use a separate file such as .env.production.
View service status:
docker compose psView logs:
docker compose logs -f
docker compose logs -f app
docker compose logs -f nginxRun Artisan commands:
docker compose exec app frankenphp php-cli artisan about
docker compose exec app frankenphp php-cli artisan optimize:clearOpen a shell in the app container:
docker compose exec app shOpen MySQL:
docker compose exec mysql mysql -u root -pRun tests inside the app container:
docker compose exec app frankenphp php-cli artisan testRun Pint:
docker compose exec app ./vendor/bin/pintCheck that the Vite manifest exists:
docker compose exec app sh -lc 'ls -la /var/www/html/public/build && test -f /var/www/html/public/build/manifest.json && echo ok'If it is missing, rebuild the app image:
docker compose up -d --build appRecreate the app and clear Laravel caches:
docker compose up -d --force-recreate app nginx
docker compose exec app frankenphp php-cli artisan optimize:clearThis is current development behavior. The app entrypoint runs:
php artisan migrate:fresh --seedwhen APP_ENV is not production.
docker compose exec app sh -lc 'tail -f storage/logs/laravel.log'- Use
docker compose, not the legacydocker-composecommand. - The development and production compose files are intentionally different.
- The production stack should use a separate env file and deployment-specific secrets.
This software is licensed under the Academic-Commercial Dual License. See LICENSE for the full terms.
For commercial licensing:
- Email:
ardrah17@gmail.com
- Maintainer: Ardhi Rahmaan MS
- GitHub: https://github.com/ArRahmaan17
- Website: https://dpos.rahmaanms.my.id