Back to Aureuserp

AureusERP — Production Docker Image

docker/production/README.md

1.5.012.9 KB
Original Source

AureusERP — Production Docker Image

A single-container, production-ready Docker image for AureusERP. It bundles the application, MySQL, PHP-FPM, Nginx and Supervisor — everything needed to run the ERP with one docker run.

AureusERP is fully installed at build time (migrations, seeders, roles & permissions, admin user), so the container boots ready to use.

This is the production image. For local development use Laravel Sail via the docker-compose.yml at the repository root.

Contents

What's inside

ComponentDetail
Base OSUbuntu 24.04
Web serverNginx (port 80)
PHP8.4 FPM — bcmath, curl, exif, gd, gmp, intl, mbstring, mysql, soap, xml, zip, imagick
DatabaseMySQL 8.0 (internal, pre-installed)
Process managerSupervisor — mysql · php-fpm · nginx · queue worker · scheduler
Application path/var/www/aureuserp

The image runs in one of two database modes:

ModeWhenBehaviour
Internal MySQLDB_HOST unset / 127.0.0.1 / localhost (default)MySQL runs inside the container
External MySQLDB_HOST set to another addressInternal MySQL stays off; the app uses the external server

Repository layout

docker/production/
├── Dockerfile          # single-stage image definition
├── .dockerignore       # build-context exclusions
├── build-install.sh    # build-time install — migrates, seeds, bakes the MySQL data dir
├── entrypoint.sh       # runtime — applies env overrides, refreshes caches, starts Supervisor
├── mysql-init.sql      # creates the internal `aureus` database and user
├── nginx.conf          # virtual host
├── php.ini             # PHP / OPcache tuning
├── php-fpm.conf        # PHP-FPM pool
├── supervisord.conf    # process definitions
└── README.md           # this file

The application source is fetched with git clone during the build, so the image always builds committed code. Releases are automated via .github/workflows/docker_publish.yml on v* tags.

Quick start

Pull and run the published image:

bash
docker pull webkul/aureuserp:latest

docker run -d --name aureuserp -p 80:80 \
  -v aureus-mysql:/var/lib/mysql \
  -v aureus-storage:/var/www/aureuserp/storage \
  webkul/aureuserp:latest

Then open http://localhost. To use a different host port, change -p, e.g. -p 8080:80http://localhost:8080.

Building the image

The build context is the docker/production/ directory. Build from the repository root:

bash
# default — clones aureuserp/aureuserp @ master
docker build -t aureuserp:latest docker/production

# a specific branch or tag
docker build -t aureuserp:1.0.0 \
  --build-arg APP_REF=v1.0.0 \
  docker/production

The build clones the repo, installs Composer dependencies, compiles front-end assets, and installs the ERP — it takes several minutes.

Build arguments

ArgumentDefaultDescription
APP_REFmasterBranch or tag of AureusERP to clone
REPO_URLhttps://github.com/aureuserp/aureuserp.gitRepository to clone
PHP_VERSION8.4PHP version
NODE_VERSION22Node.js version (used only to compile assets)
ADMIN_NAMEAdministratorAdmin account name created at install
ADMIN_EMAIL[email protected]Admin account email created at install
ADMIN_PASSWORDpasswordAdmin account password created at install

Running the container

bash
# basic
docker run -d --name aureuserp -p 80:80 aureuserp:latest

# different host port
docker run -d --name aureuserp -p 8080:80 aureuserp:latest

# foreground (stream logs, no -d)
docker run --name aureuserp -p 80:80 aureuserp:latest

# with environment overrides
docker run -d --name aureuserp -p 80:80 \
  -e APP_URL=https://erp.example.com \
  -e APP_NAME="My Company ERP" \
  -e APP_TIMEZONE=Asia/Kolkata \
  aureuserp:latest

# with persistent named volumes (recommended)
docker run -d --name aureuserp -p 80:80 \
  -v aureus-mysql:/var/lib/mysql \
  -v aureus-storage:/var/www/aureuserp/storage \
  aureuserp:latest

Access & default credentials

Applicationhttp://localhost
Admin panelhttp://localhost/admin
Default admin[email protected] / password

Change the admin password immediately after the first login. Set custom credentials at build time with the ADMIN_* build arguments.

Environment variables

Build arguments

See Build arguments above — APP_REF, REPO_URL, PHP_VERSION, NODE_VERSION, ADMIN_NAME, ADMIN_EMAIL, ADMIN_PASSWORD.

Runtime variables

VariableDefaultDescription
APP_ENVproductionproduction forces URLs to HTTPS; local serves over HTTP — see HTTP vs HTTPS
APP_DEBUGfalseDetailed error pages when true — keep false in production
APP_NAMEAureusERPApplication name
APP_URLhttp://localhostPublic base URL
APP_KEYbakedEncryption key — override to pin a stable key
APP_LOCALEenDefault locale
APP_CURRENCYUSDDefault currency
APP_TIMEZONEUTCApplication timezone
DB_HOST127.0.0.1Database host — see Database modes
DB_PORT3306Database port
DB_DATABASEaureusDatabase name
DB_USERNAMEaureusDatabase user
DB_PASSWORDaureusDatabase password

HTTP vs HTTPS

AureusERP forces every generated URL to https when APP_ENV=production (the default — correct for a live site behind TLS). For local testing over plain HTTP, run with APP_ENV=local:

bash
docker run -d --name aureuserp -p 8080:80 \
  -e APP_ENV=local \
  -e APP_URL=http://localhost:8080 \
  aureuserp:latest

The image has no built-in TLS — terminate HTTPS at a reverse proxy or load balancer in front of the container.

Database modes

Internal MySQL (default)

MySQL runs inside the container against a data directory baked at build time. Nothing to configure — just run the image.

External MySQL

Set DB_HOST to a non-local address; the internal MySQL then stays off and the entrypoint waits up to 60 s for the external server.

bash
docker run -d --name aureuserp -p 80:80 \
  -v aureus-storage:/var/www/aureuserp/storage \
  -e DB_HOST=db.example.com \
  -e DB_PORT=3306 \
  -e DB_DATABASE=aureus \
  -e DB_USERNAME=aureus \
  -e DB_PASSWORD=a-strong-password \
  -e APP_URL=https://erp.example.com \
  aureuserp:latest

Create the database and user on the external server first:

sql
CREATE DATABASE aureus CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'aureus'@'%' IDENTIFIED BY 'a-strong-password';
GRANT ALL PRIVILEGES ON aureus.* TO 'aureus'@'%';
FLUSH PRIVILEGES;

An external database is not pre-installed. Run the installer against it once (APP_ENV is overridden so the production guard does not block the migrations):

bash
docker exec -e APP_ENV=local aureuserp \
  php artisan erp:install --force --no-interaction \
  --admin-name=Administrator \
  [email protected] \
  --admin-password=password

Persistence

The image declares no VOLUME directives — persistence is opt-in. Use named volumes (named volumes receive a copy of the image's baked content on first run; bind mounts do not, and an empty bind mount would shadow the installed data).

VolumeContainer pathPurpose
aureus-mysql/var/lib/mysqlDatabase files
aureus-storage/var/www/aureuserp/storageUploads, logs, sessions, app state

Without volumes the container is ephemeral — all data is lost on docker rm.

How it works

Build time (build-install.sh): MySQL is started temporarily, the database and user are created, php artisan erp:install runs migrations + seeders + roles + the admin user, then MySQL is shut down. The populated /var/lib/mysql is baked into the image, so the container boots instantly with no setup.

Run time (entrypoint.sh):

  1. Detects internal vs. external database mode from DB_HOST.
  2. Applies environment overrides (APP_*, DB_*) to .env.
  3. In external mode, waits for the external database.
  4. Caches config and views; leaves routes dynamic (AureusERP registers plugin routes from the database, so route caching is intentionally not used).
  5. Hands off to Supervisor, which starts mysql, php-fpm, nginx, the queue worker and the scheduler.

Multi-architecture

The image runs on both amd64 and arm64 — every base image and package source supports both. Published images on Docker Hub (webkul/aureuserp) are multi-arch, so docker pull / docker run selects the right architecture automatically.

To build a multi-arch image yourself:

bash
docker buildx build --platform linux/amd64,linux/arm64 \
  -t webkul/aureuserp:latest --push docker/production

A multi-arch image must be pushed to a registry — the local Docker daemon cannot hold both architectures under one tag.

Upgrading

The image is immutable (opcache.validate_timestamps=0), so a new version means a new image:

bash
docker pull webkul/aureuserp:latest        # or rebuild locally
docker stop aureuserp && docker rm aureuserp
docker run -d --name aureuserp -p 80:80 \
  -v aureus-mysql:/var/lib/mysql \
  -v aureus-storage:/var/www/aureuserp/storage \
  webkul/aureuserp:latest

When the aureus-mysql volume is reused, apply any new migrations:

bash
docker exec aureuserp php artisan migrate --force

Back up the database volume before upgrading:

bash
docker run --rm -v aureus-mysql:/data -v "$(pwd)":/backup alpine \
  tar czf /backup/aureus-mysql-backup.tar.gz /data

Common commands

bash
# logs
docker logs aureuserp
docker logs -f --tail 100 aureuserp

# shell
docker exec -it aureuserp bash

# service status / restart
docker exec aureuserp supervisorctl status
docker exec aureuserp supervisorctl restart nginx

# artisan
docker exec aureuserp php artisan about
docker exec aureuserp php artisan migrate --force

# stop / remove
docker stop aureuserp
docker rm aureuserp

# wipe persistent data
docker volume rm aureus-mysql aureus-storage

Health check

GET /health returns 200 OK; Docker's built-in HEALTHCHECK polls it. Check status with docker ps or docker inspect.

Troubleshooting

SymptomCause & fix
Port 80 already in useRun with -p 8080:80; find the conflict with sudo lsof -i :80
Container exits / MySQL won't startA corrupt aureus-mysql volume — recreate it: docker volume rm aureus-mysql
404 on a .js/asset that should work, "from disk cache"A stale browser cache — hard-reload (Ctrl/Cmd+Shift+R) or use a private window
HTTPS redirect on local HTTPRun with -e APP_ENV=local — see HTTP vs HTTPS
External DB connection failsVerify the server is reachable and the database/user exist; for a DB on the host use host.docker.internal
Services not runningdocker exec aureuserp supervisorctl status; restart with supervisorctl restart <name>
Queue worker restarts at cold startExpected for a few seconds until MySQL is ready — Supervisor retries automatically
mysqld fails to initialise during buildSome hosts enforce AppArmor on mysqld; build on a host without that restriction

Notes & limitations

Configurable at runtime (environment variables): database connection, APP_ENV, APP_DEBUG, app URL, name, locale, currency, timezone, encryption key.

Set at build time (build arguments): AureusERP ref, repository, PHP version, Node version, admin account. Service configs (nginx.conf, php.ini, php-fpm.conf, supervisord.conf) are baked — mount a replacement file over the target path to change one.

  • All services log to stdout/stderr — view with docker logs.
  • The image is roughly 1.3–2 GB (bundled MySQL, PHP extensions, the application, and dependencies).
  • No built-in TLS — put a reverse proxy in front for HTTPS.
  • Never expose MySQL port 3306 publicly.

Support