Hello,
Starting with InvoiceShelf 2.2.0-alpha1 and the 2025-09-01 nightly builds, we’ve made significant changes to the Docker image and how storage is handled. These updates fix longstanding issues with the old image and align the project with modern Laravel/Docker best practices.
We now use serversideup/php:8.3-fpm-nginx-alpine as the base image.
- Tuned for Laravel workloads
- Proper PHP configuration out of the box
- Multi-platform
- Easier to maintain than a custom-built base
The old images created a /data directory, duplicating Laravel’s storage (/var/www/html/storage) and symlinking back. This led to permission and consistency issues.
- Old:
/data(bind-mounted from./invoiceshelf/data) - New: Use Laravel’s default path
/var/www/html/storagedirectly
Action: Update your docker-compose.yml to mount your local ./invoiceshelf/data to /var/www/html/storage (instead of /data).
# New compose (snippet)
services:
webapp:
volumes:
- ./invoiceshelf/data:/var/www/html/storageIf you use the SQLite variant:
- Old host path:
invoiceshelf/conf/database.sqlite - New host path:
invoiceshelf/data/app/database.sqlite - Container path (env):
/var/www/html/storage/app/database.sqlite
Copy the file from the old path to the new path, then update your environment:
# From your Compose project root:
mkdir -p invoiceshelf/data/app
cp invoiceshelf/conf/database.sqlite invoiceshelf/data/app/database.sqliteDB_CONNECTION=sqlite
DB_DATABASE=/var/www/html/storage/app/database.sqliteIf you used a slightly different folder name, adjust the paths accordingly.
The /conf directory is no longer part of the container.
.envis generated at startup from environment variables.- SQLite databases are expected under
/var/www/html/storage/app/. - Starting with 2.2.0 proper, mail configuration moves into the database (no longer set in
docker-compose.yml).
Instead of mounting a host path, you can let Docker manage the storage location via a named volume (reduces host-permission issues).
Old compose (host bind mounts):
volumes:
- ./invoiceshelf_sqlite/data:/data
- ./invoiceshelf_sqlite/conf:/confNew compose (Docker named volume):
services:
webapp:
volumes:
- invoiceshelf_storage:/var/www/html/storage
volumes:
invoiceshelf_storage:If you want to migrate existing storage into the named volume:
- Create and inspect the volume:
docker volume create {compose_project}_invoiceshelf_storage
docker volume inspect {compose_project}_invoiceshelf_storageWhere {compose_project} is the name of your directory where the docker compose is located. If you cloned this repository it will be docker.
- Copy your current storage content into the volume
If you prefer, you can also start the container once and use
docker cpto move files into/var/www/html/storage.
For users who prefer to keep the previous Docker behavior, we’ve published legacy tags:
invoiceshelf/invoiceshelf:2.1.1-legacyinvoiceshelf/invoiceshelf:latest-legacy
These tags point to the legacy image compatible with the old layout and compose patterns. To use them, simply change the image tag in your
docker-compose.yml, for example:
services:
webapp:
image: invoiceshelf/invoiceshelf:latest-legacy
# or pin a specific legacy version:
# image: invoiceshelf/invoiceshelf:2.1.1-legacyThe entrypoint script is much simpler now:
- No
/dataor/confhandling .envis created on first start (values injected from env vars)- SQLite DB created under
/var/www/html/storage/app/if missing - Leaner, more reliable permissions handling
Full diff between the old and new docker-compose setups:
Compare on GitHub
Best regards,
Darko