Complete Docker-based development environment for InvoicePlane
A containerized development stack featuring PHP, Nginx, MariaDB, Redis, and more. Built on Laradock and optimized for InvoicePlane development with support for PHP 7.4 through 8.4.
-
Clone the repository
git clone https://github.com/InvoicePlane/InvoicePlane-Docker.git cd InvoicePlane-Docker -
Create your environment file
cp .env.example .env.docker
-
Configure your setup (optional)
# Edit .env.docker to customize: # - PHP version (8.1, 8.2, 8.3, 8.4) # - Database settings # - Port mappings nano .env.docker
-
Build and start containers
./builddmeup.sh
-
Verify installation
docker compose --env-file .env.docker ps
Your development environment is now ready! 🎉
This guide will walk you through setting up InvoicePlane v1 step by step.
First, make sure your projects directory exists. By default, this is ~/projects:
# Create the projects directory if it doesn't exist
mkdir -p ~/projects
# Clone InvoicePlane v1 into your projects directory
cd ~/projects
git clone https://github.com/InvoicePlane/InvoicePlane.git ivplv1
cd ivplv1💡 Note: The folder name
ivplv1will be used in the next steps. You can choose any name you like, but remember to use it consistently.
Open your .env.docker file in the InvoicePlane-Docker directory:
cd /path/to/InvoicePlane-Docker
nano .env.dockerFind the line that says APP_CODE_PATH_HOST and make sure it points to your projects directory:
# This should match where you created your projects folder
APP_CODE_PATH_HOST=~/projects/💡 Tip: If you used a different path for your projects, update this line accordingly. For example, if your projects are in
/home/username/myprojects/, use that path instead.
Now we'll tell Nginx how to serve your InvoicePlane project:
-
Copy the example configuration:
cd /path/to/InvoicePlane-Docker cp sites/copyme.conf.example sites/ivplv1.conf -
Open the configuration file:
nano sites/ivplv1.conf
-
Replace all instances of
copymewithivplv1and remove/publicfrom the root path (there are 4 places to change):- Line 5:
server_name copyme.local;→server_name ivplv1.test; - Line 6:
root /var/www/projects/copyme/public;→root /var/www/projects/ivplv1;(also remove /public) - Line 34:
error_log /var/log/nginx/copyme_error.log;→error_log /var/log/nginx/ivplv1_error.log; - Line 35:
access_log /var/log/nginx/copyme_access.log;→access_log /var/log/nginx/ivplv1_access.log;
💡 Why remove
/public? InvoicePlane v1 doesn't use a public directory like some frameworks. The main files are in the root of the project.💡 Why use
.testinstead of.local? The.testdomain is reserved for testing and won't conflict with real domains. You can use.localif you prefer, just be consistent. - Line 5:
-
Save and close the file (in nano: press
Ctrl+X, thenY, thenEnter)
Tell your computer that ivplv1.test should point to your local Docker environment:
On Linux/Mac:
sudo nano /etc/hostsOn Windows: Open Notepad as Administrator, then open:
C:\Windows\System32\drivers\etc\hosts
Add this line:
127.0.0.1 ivplv1.test
Save and close the file.
Now start your Docker environment:
cd /path/to/InvoicePlane-Docker
./starmeup.sh💡 What's happening? Docker is:
- Building the containers (first time takes 5-10 minutes)
- Starting PHP, Nginx, MariaDB, and other services
- Reading your
ivplv1.conffile to know how to serve your project- Making your project available at
http://ivplv1.test
You'll see lots of output in your terminal. This is normal! Look for messages saying containers are starting.
In a new terminal window (keep Docker running in the first one):
cd /path/to/InvoicePlane-Docker
docker compose --env-file .env.docker psYou should see all services with "Up" status:
NAME STATUS
workspace Up
php-fpm Up
nginx Up
mariadb Up
redis Up
Open your web browser and go to:
http://ivplv1.test
You should see your InvoicePlane installation! 🎉
When you're finished working, stop Docker:
Option 1: Stop from terminal (if Docker is running in foreground)
- Press
Ctrl+Cin the terminal where Docker is running
Option 2: Stop and remove everything
./down.shThis stops all containers and removes them (but keeps your code safe).
When you want to work again, just run:
./starmeup.shThis is much faster than the first build! ⚡
Problem: Can't access http://ivplv1.test
- Solution: Make sure you added
127.0.0.1 ivplv1.testto your hosts file - Solution: Make sure Docker is running (
docker compose ps) - Solution: Try
http://localhostinstead
Problem: "Port already in use"
- Solution: Another service is using port 80. Either stop it, or change the port in
.env.docker:Then restart Docker for the change to take effect:NGINX_HOST_HTTP_PORT=8080
Access your site at./down.sh ./starmeup.sh
http://ivplv1.test:8080
Problem: "Permission denied" errors
- Solution: Check your
PUIDandPGIDin.env.dockermatch your user:id -u # This is your PUID id -g # This is your PGID
Problem: Changes to nginx config not working
- Solution: Restart Docker to reload the configuration:
./down.sh ./starmeup.sh
- PHP-FPM - PHP 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 (configurable)
- Workspace - CLI tools, Composer, Node.js, Git
- Nginx - Web server with optimized configuration
- MariaDB - Database server
- Redis - Caching and session storage
- Beanstalkd - Queue management
- phpMyAdmin - Database management interface
- Redis Web UI - Redis monitoring interface
- ✅ Multiple PHP versions support
- ✅ Xdebug with trigger mode
- ✅ Pre-configured for Laravel and CodeIgniter
- ✅ Helper scripts for common tasks
- ✅ GitHub Actions CI/CD
- ✅ Optimized Docker layer caching
All scripts include error handling and validation to ensure a smooth experience.
Build and start containers:
| Script | Mode | Description |
|---|---|---|
./buildmeup.sh |
Foreground | Build and start with live logs |
./builddmeup.sh |
Background | Build and start in detached mode |
Control existing containers:
| Script | Mode | Description |
|---|---|---|
./starmeup.sh |
Foreground | Start with live logs |
./startmeup.sh |
Background | Start in detached mode |
./down.sh |
- | Stop and remove all containers and volumes |
Enter a running container:
| Script | Container | User | Use Case |
|---|---|---|---|
./workmeup.sh |
workspace | ivpldock | Development tasks, Composer, NPM |
./rootmeup.sh |
workspace | root | System administration |
./phpmeup.sh |
php-fpm | root | PHP-FPM debugging |
./worker.sh |
php-worker | root | Queue worker debugging |
Execute commands inside containers from your host using docker-exec.sh:
Syntax:
./docker-exec.sh <container> <project> <command>Common Examples:
# 📦 Composer Operations
./docker-exec.sh workspace myproject "composer install"
./docker-exec.sh workspace myproject "composer update"
./docker-exec.sh workspace myproject "composer require vendor/package"
# 🎨 Laravel/Artisan Commands
./docker-exec.sh php-fpm invoiceplane "php artisan migrate"
./docker-exec.sh php-fpm invoiceplane "php artisan migrate --force"
./docker-exec.sh workspace invoiceplane "php artisan test"
./docker-exec.sh workspace invoiceplane "php artisan db:seed"
# 📊 Database Operations
./docker-exec.sh workspace invoiceplane "php artisan migrate:fresh --seed"
./docker-exec.sh workspace invoiceplane "php artisan migrate:rollback"
# 🔧 NPM Operations
./docker-exec.sh workspace myapp "npm install"
./docker-exec.sh workspace myapp "npm run build"
./docker-exec.sh workspace myapp "npm run dev"
./docker-exec.sh workspace myapp "npm run watch"
# 🧪 Testing
./docker-exec.sh workspace myproject "php artisan test"
./docker-exec.sh workspace myproject "vendor/bin/phpunit"
./docker-exec.sh workspace myproject "php artisan test --filter UserTest"This repository includes automated GitHub Actions workflows that test Docker builds.
Tested PHP Versions:
- ✅ PHP 8.2
- ✅ PHP 8.3
- ✅ PHP 8.4
CI Pipeline Verifies:
- ✅ All containers build successfully
- ✅ PHP extensions are properly installed (zip, etc.)
- ✅ Services start correctly
- ✅ Basic functionality works
Workflow Triggers:
- Push to main branches
- Pull requests
- Manual dispatch
| Directory | Purpose |
|---|---|
.docker/ |
All Dockerfile definitions for services |
sites/ |
Nginx site configurations |
.github/workflows/ |
GitHub Actions CI/CD pipelines |
*.sh |
Helper scripts for common operations |
Edit .env.docker to customize your environment:
Core Settings:
# PHP Version
PHP_VERSION=8.1 # Options: 7.4, 8.0, 8.1, 8.2, 8.3, 8.4
# Project Path
APP_CODE_PATH_HOST=../projects/
# Database
MARIADB_VERSION=latest
MARIADB_DATABASE=default
MARIADB_USER=default
MARIADB_PASSWORD=secret
# Ports
NGINX_HOST_HTTP_PORT=80
MARIADB_PORT=3306
REDIS_PORT=6379Docker automatically caches build layers to speed up subsequent builds.
How It Works:
- Docker Compose checks if dependent services need building
- Uses cached layers if Dockerfile and context haven't changed
- Only rebuilds layers that have changed
Benefits:
- ⚡ Faster rebuild times
- 💾 Efficient resource usage
- 🔄 Smart dependency management
Tips for Better Caching:
# Docker keeps built images in cache even after stopping containers
docker compose --env-file .env.docker ps
# Force complete rebuild only when necessary
docker compose --env-file .env.docker build --no-cache php-fpm
# Build specific service
docker compose --env-file .env.docker build workspace
# Parallel builds for multiple services
docker compose --env-file .env.docker build --parallelExample Workflow:
# First build (takes longer)
docker compose --env-file .env.docker build php-fpm
# ⏱️ 5 minutes
# Build dependent service (uses cache)
docker compose --env-file .env.docker build beanstalkd
# ⏱️ 30 seconds (php-fpm cached!)Xdebug is configured in trigger mode to prevent connection warnings during builds while maintaining full debugging capability.
1️⃣ Browser Debugging (Web Requests)
Using Browser Extension:
- Install Xdebug Helper for Chrome
- Or Xdebug Helper for Firefox
- Click the extension icon to enable debugging
Using Query Parameter:
http://your-app.local?XDEBUG_TRIGGER=1
Using Cookie:
document.cookie = "XDEBUG_TRIGGER=1; path=/";2️⃣ CLI Debugging (Command Line)
Inside Container:
# Enter workspace
./workmeup.sh
# Run with Xdebug
XDEBUG_TRIGGER=1 php artisan test
XDEBUG_TRIGGER=1 php script.php
XDEBUG_TRIGGER=1 vendor/bin/phpunitFrom Host:
# Single command with Xdebug
./docker-exec.sh workspace myproject "XDEBUG_TRIGGER=1 php artisan test"
# Composer with Xdebug
./docker-exec.sh workspace myproject "XDEBUG_TRIGGER=1 composer install"3️⃣ Persistent Debugging (Environment Variable)
# Inside container
export XDEBUG_TRIGGER=1
php artisan test # Now always uses XdebugPHPStorm Setup:
- Go to
Settings → PHP → Debug - Set port to
9003 - Go to
Settings → PHP → Servers - Add server named
ivpldock - Set path mappings:
- Local:
/path/to/your/project - Remote:
/var/www/projects/yourproject
- Local:
- Click "Start Listening for PHP Debug Connections" (phone icon)
VS Code Setup:
- Install PHP Debug extension
- Create
.vscode/launch.json:{ "version": "0.2.0", "configurations": [ { "name": "Listen for Xdebug", "type": "php", "request": "launch", "port": 9003, "pathMappings": { "/var/www/projects/yourproject": "${workspaceFolder}" } } ] } - Press F5 to start debugging
# Xdebug settings locations
.docker/php-fpm/xdebug.ini # PHP-FPM container
.docker/workspace/xdebug.ini # Workspace containerDefault Port: 9003 (configurable in .env.docker)
# Verify Xdebug is installed
docker compose --env-file .env.docker exec workspace php -v
# Should show: "with Xdebug v3.x.x"
# Check Xdebug configuration
docker compose --env-file .env.docker exec workspace php -i | grep xdebug
# Test Xdebug trigger
docker compose --env-file .env.docker exec workspace bash -c "XDEBUG_TRIGGER=1 php -v"
# View Xdebug logs
docker compose --env-file .env.docker exec workspace cat /tmp/xdebug.logCheck environment file exists:
ls -la .env.dockerView detailed logs:
docker compose --env-file .env.docker logs -f <container_name>
# Examples:
docker compose --env-file .env.docker logs -f workspace
docker compose --env-file .env.docker logs -f php-fpmCheck container status:
docker compose --env-file .env.docker ps
docker compose --env-file .env.docker ps -a # Include stopped containersCheck what's using the port:
# Linux/Mac
sudo lsof -i :80
sudo lsof -i :3306
# Or use netstat
netstat -tlnp | grep :80Solution: Change port in .env.docker:
NGINX_HOST_HTTP_PORT=8080 # Instead of 80
MARIADB_PORT=3307 # Instead of 3306Check and fix PUID/PGID:
# Get your user and group ID
id -u # Your user ID
id -g # Your group ID
# Update .env.docker
WORKSPACE_PUID=1000 # Your user ID
WORKSPACE_PGID=1000 # Your group ID
PHP_FPM_PUID=1000
PHP_FPM_PGID=1000
# Rebuild containers
docker compose --env-file .env.docker build workspace php-fpm
docker compose --env-file .env.docker up -dUse cached volume flag:
# In .env.docker
APP_CODE_CONTAINER_FLAG=:cachedConsider Docker Sync for large projects:
- Significant performance improvement
- See docker-sync documentation
Verify database is running:
docker compose --env-file .env.docker ps mariadbCheck database credentials:
# In .env.docker
MARIADB_DATABASE=default
MARIADB_USER=default
MARIADB_PASSWORD=secret
# In your app's .env
DB_HOST=mariadb # Not localhost!
DB_PORT=3306
DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secretTest connection:
docker compose --env-file .env.docker exec workspace mysql -h mariadb -u default -psecretRemove all containers and volumes:
# WARNING: This deletes all data!
docker compose --env-file .env.docker down -vFull Docker cleanup:
# Remove unused containers, networks, images
docker system prune -a
# Remove all volumes (BE CAREFUL!)
docker volume pruneClear build cache and rebuild:
docker compose --env-file .env.docker build --no-cache --pull <service>Check Docker disk space:
docker system dfCollect diagnostic information:
# Docker version
docker --version
docker compose version
# Container status
docker compose --env-file .env.docker ps
# Recent logs
docker compose --env-file .env.docker logs --tail=50 workspace php-fpm
# System info
docker infoWhen reporting issues, include:
- Steps to reproduce
- Error messages (full output)
- Docker and compose versions
- Operating system
- Relevant configuration from
.env.docker
- Project Guidelines: .junie/guidelines.md - Comprehensive development guidelines
- Copilot Instructions: .github/copilot-instructions.md - AI coding assistant guidelines
- Docker Compatibility: DOCKER_COMPATIBILITY.md - Version compatibility matrix
- Laradock: Original upstream project - github.com/laradock/laradock
- InvoicePlane: Main application - github.com/InvoicePlane/InvoicePlane
- Docker Documentation: docs.docker.com
- Docker Compose Documentation: docs.docker.com/compose
- Issues: GitHub Issues - Report bugs and request features
- Discussions: GitHub Discussions - Ask questions and share ideas
- Pull Requests: Contributing Guidelines - Submit code improvements
We welcome contributions! Please see our development guidelines for:
- Code standards
- Testing requirements
- Pull request process
- Docker best practices
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes
- Test thoroughly across PHP versions
- Commit your changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
This project inherits its license from Laradock. See LICENSE for details.
This project was originally called Laradock and has been forked to target specifically the images needed to run InvoicePlane.
- Laradock: github.com/laradock/laradock
- License: Original license file included in this repository
Version: 2.0
Last Updated: 2025-01-05
Maintained by: InvoicePlane Team
Note: Helper scripts use
docker-composefor backward compatibility, butdocker compose(v2) is recommended for manual commands.