empiricompany / harbor
Docker-based local development environment and CLI for Maho Commerce applications, orchestrating development runtimes and services.
Package info
github.com/empiricompany/harbor
Language:Shell
Type:maho-module
pkg:composer/empiricompany/harbor
Requires
None
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Harbor is a Docker-based local development environment for Maho Commerce. It provides a small Bash CLI around Docker Compose and convenient commands for the Maho containers.
Harbor is for local development only. It is not a production deployment or hardening solution.
Requirements
- Docker with the Compose plugin;
- a Maho project checkout;
- Composer only to install or update the package.
All commands must be run from the Maho project root.
Install and start
composer require --dev empiricompany/harbor ./vendor/bin/harbor init ./vendor/bin/harbor up -d ./vendor/bin/harbor doctor
Harbor is a local-development tool, so --dev keeps it out of production
installations.
init creates the local .harbor configuration. Review
.harbor/.env before starting the stack. Do not commit .harbor/.env.
The first application image build may take several minutes:
./vendor/bin/harbor up -d --build
Daily commands
Stack lifecycle
./vendor/bin/harbor up -d ./vendor/bin/harbor up -d --build ./vendor/bin/harbor ps ./vendor/bin/harbor logs ./vendor/bin/harbor logs cron ./vendor/bin/harbor logs -f app ./vendor/bin/harbor stop ./vendor/bin/harbor restart ./vendor/bin/harbor down
down removes containers and the network but keeps volumes. To remove volumes
as well, use:
./vendor/bin/harbor down -v
Warning: this permanently removes local database data. Harbor asks for confirmation and refuses this operation in non-interactive mode.
Commands in the app container
./vendor/bin/harbor php --version
./vendor/bin/harbor composer install
./vendor/bin/harbor maho cache:flush
./vendor/bin/harbor bin phpunit
./vendor/bin/harbor mysql --execute='SELECT 1'
./vendor/bin/harbor redis --raw ping
Shell access
./vendor/bin/harbor shell ./vendor/bin/harbor shell --service db ./vendor/bin/harbor root-shell
shell opens Bash in app by default. Use --service or -s to select a
different running service. root-shell opens Bash as root in app.
Generic container commands
Use exec when no dedicated wrapper exists:
./vendor/bin/harbor exec --service app php -v ./vendor/bin/harbor exec --service app --user root bash ./vendor/bin/harbor exec --service app --no-tty php script.php
Options before the command:
--service/-sselects the Compose service;--user/-uselects the container user;--no-ttydisables TTY allocation.
Compose customization
Harbor keeps the generated base configuration in .harbor/compose.yaml and
loads these optional project-owned layers in order:
.harbor/compose.yaml
.harbor/docker.override.yaml
.harbor/docker.install.yaml
Do not edit the generated base file. Put local or persistent customizations in
.harbor/docker.override.yaml; use .harbor/docker.install.yaml for services
or settings needed during installation. Both files are optional and can be
created manually.
Example: enable Xdebug and add a Node service:
services: app: environment: XDEBUG_MODE: develop,debug extra_hosts: - host.docker.internal:host-gateway node: image: node:22 working_dir: /app volumes: - ../:/app networks: - harbor
Start the service and use it with exec:
./vendor/bin/harbor up -d
./vendor/bin/harbor exec --service node node --version
Xdebug
Xdebug is included in the default app image. Configure your IDE to listen for
PHP debug connections on port 9003, then enable the debug environment in
.harbor/docker.override.yaml:
services: app: environment: XDEBUG_MODE: develop,debug XDEBUG_CONFIG: client_host=host.docker.internal client_port=9003 extra_hosts: - host.docker.internal:host-gateway
The XDEBUG_CONFIG value makes the app container connect back to the host IDE.
Rebuild the app image after adding or changing this configuration:
./vendor/bin/harbor up -d --build
./vendor/bin/harbor debug -r 'echo "debug\n";'
Use harbor debug for requests that should start an Xdebug session. It enables
xdebug.start_with_request=yes for that PHP invocation; regular php and
maho commands do not force a debug session.
Inspect the Compose layers with:
./vendor/bin/harbor config
Keep secrets in .harbor/.env or environment variables, not in committed
override files.
Scheduled Maho jobs
The stack runs the built-in Maho cron groups through Ofelia:
always: every minute;default: every five minutes.
Add custom jobs to the app service in .harbor/docker.override.yaml:
services: app: labels: ofelia.job-exec.catalog-reindex.schedule: "@every 10m" ofelia.job-exec.catalog-reindex.command: "sh -c 'cd /app && ./maho indexer:reindex catalog_product_flat'" ofelia.job-exec.catalog-reindex.user: maho ofelia.job-exec.catalog-reindex.no-overlap: "true"
Use a unique job name, recreate the application container, and inspect the cron logs:
./vendor/bin/harbor up -d ./vendor/bin/harbor logs cron
Maho installation
Harbor does not create or modify app/etc/local.xml. The Maho installer owns
that file.
For the web installer, open:
https://localhost:8443/
Use these internal database values:
| Setting | Value |
|---|---|
| Database host | db |
| Database port | 3306 |
| Database name | value from .harbor/.env |
| Database user | value from .harbor/.env |
| Database password | value from .harbor/.env |
| Database engine | mysql |
| HTTPS URL | https://localhost:8443/ |
For the CLI installer, run the Maho command in the app container:
./vendor/bin/harbor maho install \ --license_agreement_accepted yes \ --db_host db --db_name maho --db_user maho \ --db_pass '<database password>' --db_engine mysql \ --url https://localhost:8443/ --use_secure 1 \ --secure_base_url https://localhost:8443/ \ --admin_firstname Admin --admin_lastname User \ --admin_email admin@example.test --admin_username admin \ --admin_password '<admin password>'
Database backup and restore
Export with the Maho database command:
./vendor/bin/harbor maho db:export var/backups/backup.sql.gz --compression=gzip
Restore a backup only when you intend to replace the local database:
./vendor/bin/harbor down -v ./vendor/bin/harbor up -d ./vendor/bin/harbor maho db:import \ /app/var/backups/backup.sql.gz \ --compression=gzip --drop-tables
Warning: the down -v step permanently deletes the current database volume.
Optional services and URLs
Mailpit is included by default:
Web UI: http://localhost:8025
SMTP: mailpit:1025 from containers
Optional services are controlled through Compose profiles. List available services and profiles with:
./vendor/bin/harbor services
Enable profiles through .harbor/.env or an override layer using
HARBOR_PROFILES, for example:
HARBOR_PROFILES=redis,adminer
Adminer and phpMyAdmin use the default local URLs when enabled:
Adminer: http://localhost:8082
phpMyAdmin: http://localhost:8081
Diagnostics and convenience commands
./vendor/bin/harbor doctor ./vendor/bin/harbor config ./vendor/bin/harbor open ./vendor/bin/harbor open admin ./vendor/bin/harbor open mailpit
doctor checks Docker, Compose, configuration, and running services. config
renders the merged Compose configuration. open accepts app, admin, or
mailpit and defaults to app.
Dev Containers
With VS Code and the Dev Containers extension installed:
./vendor/bin/harbor up -d ./vendor/bin/harbor devcontainer
Reopen the project in the generated container. Use --force to replace an
existing configuration:
./vendor/bin/harbor devcontainer --force
Contributing
See CONTRIBUTING.md for the development workflow and
quality checks.
License
Harbor is released under the MIT License. See LICENSE.