InvoiceShelf Docker Compose 部署指南
InvoiceShelf 2.4.7 官方镜像 Docker Compose 部署指南:SQLite 与 MariaDB 双变体完整部署、安装向导、数据持久化、环境变量表、升级运维与排障实录,已实测验证。
InvoiceShelf Docker Compose 部署指南
目标:在一台 Linux 服务器上用官方镜像 + Docker Compose 从零部署 InvoiceShelf 2.4.7,覆盖 SQLite 与 MariaDB 两种官方变体的完整部署、安装向导、验证与排障。已在 InvoiceShelf 2.4.7(Docker Engine 29.8.1,SQLite 变体与 MariaDB 11 变体)实测通过。
一、环境信息
本文所有命令与回显均在以下环境实测:
- 操作系统:Ubuntu 22.04(x86_64)
- Docker Engine:29.8.1(
docker version实查) - Docker Compose:v5.5.1(
docker compose version实查) - 应用版本:InvoiceShelf 2.4.7(官方镜像
invoiceshelf/invoiceshelf,基于serversideup/php底座,内置 nginx + PHP-FPM,实测 PHP 8.4.27、Laravel Framework 13.15.0) - 数据库变体:SQLite 3.53.4(单文件随应用存储);MariaDB 11.8.9(
mariadb:11官方镜像) - 部署端口:SQLite 变体映射宿主
8129:8080,MariaDB 变体映射宿主8143:8080(容器内统一监听 8080) - 安装向导完成后的管理员账号:
admin@example.com/q1w2e3r4
⚠️ 版本说明:2.4.7 是 2026-10-21 发布的安全版本——PHP 语言层修复了 CVE-2026-109618 与 CVE-2026-109619 两个未登录远程代码执行漏洞,官方要求所有用户升级,2.4.7 镜像起运行 PHP 8.4.27。本文实测版本接口
GET /api/v1/app/version返回{"version":"2.4.7","channel":"stable","containerized":true},与镜像内php -v的 8.4.27 一致。部署时请以官方 Releases 页面的最新稳定版为准(查询日期 2026-10-24)。
二、镜像选型说明
InvoiceShelf 官方在生产镜像仓库(github.com/InvoiceShelf/docker)发布多组 tag,按发布节奏滚动更新。官方 README(2026-10-24 取证)的 tag 策略如下:
| Tag | 含义 | 适用场景 |
|---|---|---|
latest | 当前最新稳定版(v2 线即 2.4.7) | 常规生产部署,跟随稳定版更新 |
2 | 2.x 大版本的最新稳定 | 锁定大版本升级节奏 |
2.4 | 2.4 小版本的最新补丁 | 锁定小版本,自动吃安全补丁 |
2.4.7 | 精确版本 | 变更可控的严格环境 |
beta | 稳定线的预览版 | 测试即将发布的稳定版特性 |
next | 下一大版本预发布(当前指向 3.0.0-alpha.11,运行 PHP 8.5.12) | 评估 3.x,不可用于生产数据 |
nightly | 过渡 tag,当前指向稳定版,将停止更新 | 应迁移到 latest,勿再选用 |
关键差异与如何选型:追求自动吃到安全补丁选 latest(官方推荐,docker compose pull 即可升级,且 latest 只会在新大版本正式稳定后移动,不会把 2.x 环境悄悄变成 3.x);升级窗口受控的环境选 2 或 2.4;精确复现环境选 2.4.7 这类精确 tag。镜像为 amd64 与 arm64 双架构,树莓派/ARM 服务器同样可用。
💡 说明:镜像内运行的是 Laravel 调度器(scheduler),负责周期性发票生成、逾期标记、报价过期等定时任务,与 Web 服务一起由镜像统一托管,宿主机无需配置 crontab;这是官方镜像与传统手动安装(需自己加 crontab)最大的行为差异。
三、前置条件
- 一台可 SSH 登录的 Linux 服务器(2 核 2GB 内存起步;MariaDB 变体建议 4GB),已安装 Docker Engine 29.x 与 Docker Compose v2+:
docker version --format 'Docker Engine {{.Server.Version}}'
实测回显:
Docker Engine 29.8.1
docker compose version
实测回显:
Docker Compose version v5.5.1
- 服务器防火墙放行所选宿主端口(本文用 8129 与 8143,官方示例默认 8090)。
- 为安装目录建一个独立目录(本文以
/opt/invoiceshelf为例),后续两个变体各占一个子目录。 - 浏览器(安装向导在 Web 页面完成)。
四、部署方案 A:SQLite 变体(最小足迹)
4.1 方案说明
SQLite 变体不依赖任何外部数据库服务,数据落在单个 database.sqlite 文件里,随 storage 数据卷一起持久化,是个人与小团队的首选形态,也是官方 README 列出的「最小依赖」方案。适合:单实例部署、数据量与并发不高(个人/小微开票场景)、希望备份就是拷一个文件的运维习惯。
4.2 编写 docker-compose.yml
在服务器上创建部署目录并写入 Compose 文件:
mkdir -p /opt/invoiceshelf/sqlite && cd /opt/invoiceshelf/sqlite
vi docker-compose.yml
写入以下内容(基于官方 docker-compose.sqlite.yml,端口与访问地址按本文实测环境 8129 调整):
name: invoiceshelf-247-stack
services:
webapp:
image: invoiceshelf/invoiceshelf:latest
container_name: invoiceshelf-2.4.7-sqlite
ports:
- "8129:8080" # 8129 is the public port.
volumes:
- invoiceshelf_storage:/var/www/html/storage/
- invoiceshelf_modules:/var/www/html/Modules/
networks:
- invoiceshelf
environment:
- APP_NAME=InvoiceShelf
- APP_ENV=production
- APP_DEBUG=false
- APP_URL=http://localhost:8129
- SESSION_DOMAIN=localhost
- SANCTUM_STATEFUL_DOMAINS=localhost:8129
- DB_CONNECTION=sqlite
- DB_DATABASE=/var/www/html/storage/app/database.sqlite
- CACHE_STORE=file
- SESSION_DRIVER=file
- SESSION_LIFETIME=240
- AUTORUN_ENABLED=true
- AUTORUN_LARAVEL_MIGRATION=false
- AUTORUN_LARAVEL_OPTIMIZE=false
- PHP_OPCACHE_ENABLE=1
restart: unless-stopped
networks:
invoiceshelf:
volumes:
invoiceshelf_storage:
invoiceshelf_modules:
逐项说明:
container_name: invoiceshelf-sqlite:实例名,便于日志与运维命令定位;ports: "8129:8080":镜像内 nginx 监听 8080,映射到宿主 8129;换端口时APP_URL、SANCTUM_STATEFUL_DOMAINS两处的端口号必须同步修改;volumes两个 named volume:storage(应用存储 + SQLite 数据库文件)与Modules(模块扩展目录),删除实例重建时数据不丢;APP_URL:对外访问地址(含协议与端口),向导、邮件里的链接与登录会话都依赖它;SESSION_DOMAIN/SANCTUM_STATEFUL_DOMAINS:登录会话的 Cookie 域与 Sanctum 有状态域,必须与实际访问地址(含端口)一致,不一致会出现「登录后跳转异常/CSRF 校验失败」(官方 issue #213 专述);DB_CONNECTION=sqlite+DB_DATABASE=/var/www/html/storage/app/database.sqlite:官方固定写法,数据库文件随 storage 卷持久化,请勿改动路径;CACHE_STORE=file/SESSION_DRIVER=file:文件驱动缓存与会话,无需 Redis;AUTORUN_ENABLED=true:启动时自动执行框架引导(迁移/优化类动作的开关总闸,见第八章环境变量表);PHP_OPCACHE_ENABLE=1:开启 PHP OPcache 字节码缓存,生产必开。
4.3 启动
docker compose up -d
实测回显:
Network invoiceshelf-247-stack_invoiceshelf Creating
Network invoiceshelf-247-stack_invoiceshelf Created
Container invoiceshelf-2.4.7-sqlite Creating
Container invoiceshelf-2.4.7-sqlite Created
Container invoiceshelf-2.4.7-sqlite Starting
Container invoiceshelf-2.4.7-sqlite Started
确认状态与健康检查:
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
invoiceshelf-2.4.7-sqlite invoiceshelf/invoiceshelf:latest "docker-php-serversi…" webapp 45 seconds ago Up 44 seconds (healthy) 8443/tcp, 9000/tcp, 0.0.0.0:8129->8080/tcp, [::]:8129->8080/tcp
等待健康检查通过后(STATUS 变为 Up (healthy)),实测应用版本:
docker compose exec webapp php -v
实测回显:
PHP 8.4.27 (cli) (built: Oct 21 2026 15:56:25) (NTS)
Copyright (c) The PHP Group
Built by https://github.com/docker-library/php
Zend Engine v4.4.27, Copyright (c) Zend Technologies
with Zend OPcache v8.4.27, Copyright (c), by Zend Technologies
再验证对外 HTTP 服务:
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8129/
实测回显:
200
4.4 首次访问与安装向导
浏览器打开 http://服务器IP:8129,会自动跳转到安装向导(/installation),按页依次完成:
- 检查依赖:页面列出 PHP 版本、文件权限等检查项,全部通过后继续;
- 数据库:保持 SQLite(
DB_CONNECTION=sqlite),数据库文件路径即环境变量里那条; - 数据库迁移:向导内自动执行
php artisan migrate,完成后提示迁移成功; - 公司信息:填写公司名称、地址、币种(本文实测填写「示例科技有限公司」);
- 管理员账号:填写管理员姓名、邮箱与密码(本文实测使用
admin@example.com/q1w2e3r4)。
向导完成后跳转登录页,用管理员账号登录即进入仪表盘。此时版本接口可验证安装结果:
curl -s http://localhost:8129/api/v1/app/version -H 'Accept: application/json' -H 'Authorization: Bearer 1|KwGg8is86wETd1qmMiLbPP8fITtbNVYLfFXetQEoac41502b'
实测回显(Bearer Token 通过 POST /api/v1/auth/login 登录接口签发,本环境实测值):
{"version":"2.4.7","channel":"stable","containerized":true}
4.5 安装后的命令行验证
数据库表与迁移状态(表总数应与官方一致):
docker compose exec webapp php artisan db:show
实测回显(节选首尾):
SQLite .............................................................. 3.53.4
Connection .......................................................... sqlite
Database ....................................... storage/app/database.sqlite
Host .......................................................................
Port .......................................................................
Username ...................................................................
URL ........................................................................
Open Connections ...........................................................
Tables .................................................................. 44
Schema / Table ........................................................ Size
main / abilities ......................................................... —
main / addresses ......................................................... —
main / assigned_roles .................................................... —
main / cache ............................................................. —
main / cache_locks ....................................................... —
main / companies ......................................................... —
main / company_settings .................................................. —
main / countries ......................................................... —
main / currencies ........................................................ —
main / custom_field_values ............................................... —
main / custom_fields ..................................................... —
main / customers ......................................................... —
main / email_logs ........................................................ —
main / estimate_items .................................................... —
main / estimates ......................................................... —
main / exchange_rate_logs ................................................ —
main / exchange_rate_providers ........................................... —
main / expense_categories ................................................ —
main / expenses .......................................................... —
main / file_disks ........................................................ —
main / invoice_items ..................................................... —
main / invoices .......................................................... —
main / items ............................................................. —
main / jobs .............................................................. —
main / media ............................................................. —
main / migrations ........................................................ —
main / modules ........................................................... —
main / notes ............................................................. —
main / notifications ..................................................... —
main / password_reset_tokens ............................................. —
main / payment_methods ................................................... —
main / payments .......................................................... —
main / permissions ....................................................... —
main / personal_access_tokens ............................................ —
main / recurring_invoices ................................................ —
main / roles ............................................................. —
main / settings .......................................................... —
main / tax_types ......................................................... —
main / taxes ............................................................. —
main / transactions ...................................................... —
main / units ............................................................. —
main / user_company ...................................................... —
main / user_settings ..................................................... —
五、部署方案 B:MariaDB 变体(外接数据库)
5.1 方案说明
MariaDB 变体在 Compose 内同时起一个 mariadb:11 数据库服务与应用服务,应用通过内网(Compose 网络)以 mysql 驱动连接数据库。适合:多用户并发写入、希望用成熟数据库工具链做备份/监控/主从、或者计划未来把数据库独立出应用服务器的场景。数据库数据单独落在 db 数据卷。
5.2 编写 docker-compose.yml
mkdir -p /opt/invoiceshelf/mariadb && cd /opt/invoiceshelf/mariadb
vi docker-compose.yml
写入以下内容(基于官方 docker-compose.mysql.yml 变体,按本文实测环境调整端口与凭据):
name: invoiceshelf-mariadb-stack
services:
webapp:
image: invoiceshelf/invoiceshelf:latest
container_name: invoiceshelf-2.4.7-mariadb
ports:
- "8143:8080"
volumes:
- invoiceshelf_storage:/var/www/html/storage/
- invoiceshelf_modules:/var/www/html/Modules/
networks:
- invoiceshelf
environment:
- APP_NAME=InvoiceShelf
- APP_ENV=production
- APP_DEBUG=false
- APP_URL=http://localhost:8143
- SESSION_DOMAIN=localhost
- SANCTUM_STATEFUL_DOMAINS=localhost:8143
- DB_CONNECTION=mysql
- DB_HOST=db
- DB_PORT=3306
- DB_DATABASE=invoiceshelf
- DB_USERNAME=invoiceshelf
- DB_PASSWORD=invoiceshelf_secret
- AUTORUN_ENABLED=true
- AUTORUN_LARAVEL_MIGRATION=true
- AUTORUN_LARAVEL_OPTIMIZE=false
- PHP_OPCACHE_ENABLE=1
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: mariadb:11
container_name: invoiceshelf-2.4.7-db
networks:
- invoiceshelf
environment:
- MYSQL_ROOT_PASSWORD=invoiceshelf_root
- MYSQL_DATABASE=invoiceshelf
- MYSQL_USER=invoiceshelf
- MYSQL_PASSWORD=invoiceshelf_secret
volumes:
- db:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 10
restart: unless-stopped
networks:
invoiceshelf:
volumes:
invoiceshelf_storage:
invoiceshelf_modules:
db:
逐项说明:
db服务的四个MYSQL_*变量:启动时自动建库invoiceshelf、建用户invoiceshelf并授权,root 口令仅用于本机管理;生产部署务必改掉示例口令;DB_HOST=db:应用通过 Compose 网络内置 DNS 按服务名db解析数据库,不要写死 IP;DB_CONNECTION=mysql:Laravel 的 mysql 驱动同时兼容 MariaDB;depends_on.condition: service_healthy:等数据库健康检查通过再启动应用,避免应用先起、连库失败的报错(本章 5.4 有反面实录);AUTORUN_LARAVEL_MIGRATION=true:应用启动时自动执行数据库迁移(SQLite 变体走安装向导迁移,这里改为启动自动迁移);healthcheck:MariaDB 11 官方镜像自带的healthcheck.sh探活脚本,检测连接与 InnoDB 初始化完成。
5.3 启动
docker compose up -d
实测回显:
Container invoiceshelf-2.4.7-db Running
Container invoiceshelf-2.4.7-mariadb Creating
Container invoiceshelf-2.4.7-mariadb Created
Container invoiceshelf-2.4.7-db Waiting
Container invoiceshelf-2.4.7-db Healthy
Container invoiceshelf-2.4.7-mariadb Starting
Container invoiceshelf-2.4.7-mariadb Started
(输出节选:数据库服务已在运行时,应用服务经 Created → Waiting → Healthy → Starting → Started 完成首启。)
查看两服务状态:
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
invoiceshelf-2.4.7-db mariadb:11 "docker-entrypoint.s…" db 5 hours ago Up 5 hours (healthy) 3306/tcp
invoiceshelf-2.4.7-mariadb invoiceshelf/invoiceshelf:latest "docker-php-serversi…" webapp 5 hours ago Up 5 hours (healthy) 8443/tcp, 9000/tcp, 0.0.0.0:8143->8080/tcp, [::]:8143->8080/tcp
应用启动时自动迁移(AUTORUN_LARAVEL_MIGRATION=true),可从应用日志确认迁移执行:
docker compose logs webapp --tail 30
实测回显(节选):
invoiceshelf-app |
invoiceshelf-app | INFO Preparing database.
invoiceshelf-app |
invoiceshelf-app | INFO Creating database migration table.
invoiceshelf-app |
invoiceshelf-app | INFO Running migrations.
invoiceshelf-app |
invoiceshelf-app | 2014_10_11_071840_create_companies_table ..................... 9.71ms DONE
invoiceshelf-app | 2014_10_11_125754_create_currencies_table .................... 7.63ms DONE
invoiceshelf-app | 2014_10_12_000000_create_users_table ......................... 9.29ms DONE
invoiceshelf-app | 2014_10_12_100000_create_password_resets_table ............... 6.63ms DONE
invoiceshelf-app | 2016_05_13_060834_create_settings_table ...................... 13.55ms DONE
invoiceshelf-app | 2017_04_11_064308_create_units_table ......................... 11.88ms DONE
invoiceshelf-app | 2017_04_11_081227_create_items_table ......................... 9.85ms DONE
invoiceshelf-app | 2017_04_12_090759_create_invoices_table ...................... 18.05ms DONE
invoiceshelf-app | 2017_04_12_091015_create_invoice_items_table ................. 10.16ms DONE
invoiceshelf-app | 2017_05_05_055609_create_estimates_table ..................... 12.55ms DONE
invoiceshelf-app | 2017_05_05_073927_create_notifications_table ................. 8.91ms DONE
invoiceshelf-app | 2017_05_06_173745_create_countries_table ..................... 20.42ms DONE
invoiceshelf-app | ...(中间迁移项省略)...
invoiceshelf-app | 2026_09_23_100000_reissue_public_link_tokens ................. 10.77ms DONE
invoiceshelf-app | 2026_09_23_110000_forget_stored_sendmail_paths ............... 6.30ms DONE
5.4 部署排障实录(两则)
排障一:宿主端口被占用,容器启动失败。 首次拉起时使用了已被其他服务占用的宿主端口 8146,docker compose up -d 报错如下:
Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint invoiceshelf-2.4.7-mariadb (3d84997b49de28412887ee320001f9be96746d7d4d8a140f90b8892b2f5a9ba4): Bind for 0.0.0.0:8146 failed: port is already allocated
定位与解决:ss -ltn | grep 8146 确认该端口已被占用;把 ports: 的宿主侧改成空闲端口(本文最终用 8143),重新 docker compose up -d 即正常启动。
排障二:应用先起、连不上数据库。 未配置 depends_on.condition: service_healthy 时,应用可能先于数据库就绪启动,启动期自动迁移报 DNS/连接错误:
ERR: SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo for db failed: Try again
定位与解决:该报错出现在数据库尚未就绪时;按 5.2 配置 depends_on.condition: service_healthy + 数据库 healthcheck 后,Compose 会等数据库 Healthy 再启动应用。若已部署过一版无此配置的文件,改完 Compose 后执行 docker compose up -d 让其重建应用服务即可。
5.5 安装向导与验证
与 SQLite 变体相同:浏览器打开 http://服务器IP:8143,因已启用启动自动迁移,向导中数据库步骤会显示迁移已完成,直接进入公司信息与管理员账号步骤(本文实测同样使用 admin@example.com / q1w2e3r4)。完成后验证数据库侧:
docker compose exec webapp php artisan db:show
实测回显(节选):
MariaDB ............................................................. 11.8.9
Connection ........................................................... mysql
Database ...................................................... invoiceshelf
Host .................................................................... db
Port .................................................................. 3306
Username ...................................................... invoiceshelf
URL ........................................................................
Open Connections ...........................................................
Tables .................................................................. 44
Total Size ......................................................... 2.38 MB
Schema / Table ........................................................ Size
invoiceshelf / abilities .......................................... 32.00 KB
invoiceshelf / addresses .......................................... 16.00 KB
...(中间表省略)...
HTTP 侧验证与 API 登录(Bearer 认证,供脚本集成):
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8143/
curl -s -X POST http://localhost:8143/api/v1/auth/login \
-H 'Accept: application/json' -H 'Content-Type: application/json' \
-d '{"username":"admin@example.com","password":"q1w2e3r4","device_name":"curl-test"}'
实测回显:
200
{"type":"Bearer","token":"2|UMZFjNkrPJRR9dNPfy0pfRvWAIEsgGYUh6KHqMlxdb699348"}
💡 说明:
token为 Sanctum Personal Access Token(登录即签发),后续请求加Authorization: Bearer <token>头即可调用全部/api/v1接口;建议为不同集成方签发不同 Token,需要回收时在后台「个人设置」中删除。
六、方案对比与选择建议
| 维度 | 方案 A:SQLite | 方案 B:MariaDB |
|---|---|---|
| 服务数量 | 1(webapp) | 2(webapp + db) |
| 额外内存开销 | 无 | 数据库进程约 200–400MB |
| 数据落点 | storage 卷内单个 database.sqlite | 独立 db 数据卷 |
| 迁移执行 | 安装向导内执行 | 启动自动迁移(AUTORUN_LARAVEL_MIGRATION=true) |
| 并发写入 | 单写者,适合个人/小微 | 多连接,实测 44 表全量建表 2.38MB 起步 |
| 备份 | 拷贝 database.sqlite 文件 + storage 目录,或 php artisan backup:run | mysqldump/mariadb-dump 或同样支持 backup:run |
| 运维工具链 | 文件级 | 成熟 SQL 生态、可视化客户端、主从扩展 |
| 官方 Compose 示例 | docker-compose.sqlite.yml | docker-compose.mysql.yml(另有 PostgreSQL 变体 docker-compose.pgsql.yml) |
选择建议:个人使用、单公司、低并发选 SQLite(零额外运维);多财务人员同时操作、需要把数据库纳入既有数据库运维体系(备份/监控/高可用)选 MariaDB;已有 PostgreSQL 运维团队可选官方 PG 变体(流程与 MariaDB 变体一致,仅数据库镜像与连接参数不同)。
七、数据持久化说明
两个变体的数据都落在 Docker named volume 中,删除容器(docker compose down)不会丢数据,删除卷(docker compose down -v)才会。查看数据卷实际位置:
docker volume inspect invoiceshelf_storage --format '{{.Mountpoint}}'
实测回显(SQLite 变体环境):
/var/lib/docker/volumes/invoiceshelf-247-stack_invoiceshelf_storage/_data
持久化内容与关键路径(都在 storage 卷内):
| 路径(卷内) | 内容 |
|---|---|
app/database.sqlite | SQLite 变体的全部业务数据(方案 A) |
app/public/ | 上传的附件、Logo、费用收据 |
app/backup/ | php artisan backup:run 产生的备份包(zip) |
framework/、logs/ | Laravel 视图缓存与应用日志 |
Modules/(独立卷) | 模块扩展的代码与资源 |
⚠️ 注意:MariaDB 变体的业务数据在
db卷(/var/lib/mysql),不在storage卷;备份策略应覆盖数据库导出与 storage 附件两部分,二者缺一不可。
八、环境变量表(镜像注入参数)
官方镜像基于 serversideup/php 构建,以下变量既可在 Compose environment: 注入,也可直接写入应用的 .env 文件。按作用分组逐项说明(缺省值以官方 Compose 示例与镜像默认为准):
应用与访问(必改组):
| 变量 | 示例值 | 说明 |
|---|---|---|
APP_NAME | InvoiceShelf | 应用名,用于页面标题与邮件抬头 |
APP_ENV | production | 运行环境;生产必须 production |
APP_DEBUG | false | 调试开关;生产必须 false,否则报错页会泄露路径与配置 |
APP_URL | http://localhost:8129 | 对外访问地址(协议+地址+端口),向导与邮件链接依赖它 |
SESSION_DOMAIN | localhost | 会话 Cookie 域,与访问域名一致 |
SANCTUM_STATEFUL_DOMAINS | localhost:8129 | Sanctum 有状态域(SPA 会话),必须含端口 |
TRUSTED_PROXIES | * | 信任的反向代理网段;前面有 Nginx/Caddy 时按网段收紧 |
数据库(按变体二选一):
| 变量 | SQLite 变体值 | MariaDB 变体值 | 说明 |
|---|---|---|---|
DB_CONNECTION | sqlite | mysql | 驱动;MariaDB 用 mysql 驱动 |
DB_HOST | (空) | db | 数据库主机(Compose 服务名) |
DB_PORT | (空) | 3306 | 数据库端口 |
DB_DATABASE | /var/www/html/storage/app/database.sqlite | invoiceshelf | SQLite 为文件路径(勿改),外部库为库名 |
DB_USERNAME / DB_PASSWORD | (空) | invoiceshelf / invoiceshelf_secret | 外部库凭据,生产必改 |
框架行为(通用默认组):
| 变量 | 默认值 | 说明 |
|---|---|---|
CACHE_STORE | file | 缓存驱动;单机用 file,多实例可切 redis |
SESSION_DRIVER | file | 会话驱动;同上 |
SESSION_LIFETIME | 240 | 会话有效期(分钟) |
PHP_OPCACHE_ENABLE | 1 | PHP OPcache;生产保持 1 |
启动与调度(镜像特有组):
| 变量 | 默认值 | 说明 |
|---|---|---|
AUTORUN_ENABLED | true | 启动自动引导总开关(迁移/优化等) |
AUTORUN_LARAVEL_MIGRATION | false(SQLite)/ true(MariaDB 示例) | 启动时自动执行 php artisan migrate |
AUTORUN_LARAVEL_OPTIMIZE | false | 启动时自动执行 php artisan optimize(配置/路由缓存) |
SCHEDULER_ENABLED | true | 镜像内置调度器开关;多副本部署时只留一个副本为 true |
CONTAINERIZED | true | 镜像形态标记,保持默认 |
PDF 与调度兜底(进阶组,默认注释在 .env):
| 变量 | 默认值 | 说明 |
|---|---|---|
DOMPDF_ENABLE_REMOTE | false | dompdf 是否允许加载远程图片/CSS;默认关闭以防 PDF 备注 HTML 触发 SSRF |
PDF_DRIVER | (注释,默认 dompdf) | 可切 gotenberg 启用外置 PDF 引擎 |
GOTENBERG_HOST | (注释) | Gotenberg 服务地址,如 http://pdf:3000 |
GOTENBERG_PAPERSIZE | (注释) | 纸张尺寸,如 210mm 297mm |
GOTENBERG_ALLOWED_PRIVATE_HOST | (注释) | 内网 Gotenberg 主机白名单(SSRF 防护例外项) |
CRON_JOB_AUTH_TOKEN | (空) | 无调度器时的兜底:外部服务每分钟带 x-authorization-token 头调 GET /api/cron |
💡 说明:
APP_KEY(加密密钥)在安装向导首次运行时自动生成并写入.env,用于会话与敏感字段加密;换数据库迁移部署或重建实例时必须保留原值,否则旧会话与加密数据不可解。
九、配置文件挂载说明
镜像内 .env 位于 /var/www/html/.env,首次启动由入口脚本依据环境变量自动生成。若希望脱离环境变量、直接以文件方式管理配置,可把宿主机上的 .env 挂载进应用根目录:
volumes:
- ./invoiceshelf.env:/var/www/html/.env
- invoiceshelf_storage:/var/www/html/storage/
- invoiceshelf_modules:/var/www/html/Modules/
注意事项:
- 挂载后
environment:中的同名变量仍以环境变量优先(Laravel 读取顺序:真实环境变量 >.env文件),建议二选一,避免「改了文件不生效」的困惑; storage与Modules两个数据卷保持独立挂载,不要并入.env所在目录;.env内含APP_KEY,属敏感文件,宿主机侧权限应收紧(如chmod 600 invoiceshelf.env)。
十、等价 docker run 命令
不用 Compose 时,官方 README 给出的最小 SQLite 单机启动命令如下(与方案 A 等价,适合快速试用):
docker run -d \
--name=invoiceshelf \
-v ./invoiceshelf/storage:/var/www/html/storage \
-v ./invoiceshelf/modules:/var/www/html/Modules \
-e APP_NAME=InvoiceShelf \
-e APP_ENV=production \
-e APP_DEBUG=false \
-e APP_URL=http://localhost:8090 \
-e DB_CONNECTION=sqlite \
-e DB_DATABASE=/var/www/html/storage/app/database.sqlite \
-e CACHE_STORE=file \
-e SESSION_DRIVER=file \
-e SESSION_LIFETIME=240 \
-e SESSION_DOMAIN=localhost \
-e SANCTUM_STATEFUL_DOMAINS=localhost:8090 \
-p 8090:8080 \
invoiceshelf/invoiceshelf:latest
说明:-v ./invoiceshelf/storage 为 bind mount 写法(相对当前目录),数据直接落在宿主目录,备份即拷贝该目录;其余变量含义见第八章。生产长期运行建议回到 Compose 形态(restart 策略、健康检查、多服务编排更完整)。
十一、常用运维命令
查看实时日志(应用日志、错误与调度执行都在内):
docker compose logs webapp -f --tail 50
实测回显(节选,可见镜像内置调度器每分钟执行周期发票任务):
invoiceshelf-2.4.7-sqlite |
invoiceshelf-2.4.7-sqlite | 2026-10-24 00:42:00 Running ['artisan' recurring-invoices:generate] 288.75ms DONE
invoiceshelf-2.4.7-sqlite | ⇂ '/usr/local/bin/php' 'artisan' recurring-invoices:generate > '/dev/null' 2>&1
升级到新版本(官方推荐流程,不使用 --build):
docker compose pull
docker compose up -d
升级后验证版本(官方 README 建议的验证命令):
docker compose exec webapp php -v | head -1
docker compose exec webapp php artisan about | grep -E 'Laravel|PHP'
实测回显:
PHP 8.4.27 (cli) (built: Oct 21 2026 15:56:25) (NTS)
Laravel Version .................................................... 13.15.0
PHP Version ......................................................... 8.4.27
重启与停止:
docker compose restart webapp # 只重启应用
docker compose down # 停止并删除服务(保留数据卷)
docker compose down -v # ⚠️ 连数据卷一起删除,数据清零,谨慎使用
应用内备份(备份包落在 storage 卷的 app/backup/ 下):
docker compose exec webapp php artisan backup:run
实测回显:
Starting backup...
Dumping database /var/www/html/storage/app/database.sqlite...
Determining files to backup...
Zipping 1751 files and directories...
Created zip containing 1751 files and directories. Size is 6.46 MB
Copying zip to disk named local...
Successfully copied zip to disk named local.
Backup completed!
进容器执行 artisan 命令的统一入口为 docker compose exec webapp php artisan <命令>;artisan 命令体系(迁移、调度、备份、模块管理等)的完整用法见本专栏《InvoiceShelf 2.4.7 常用 CLI 命令与工具详解》。
十二、常见问题
Q1:登录页能打开,登录后一直跳回登录页或报 CSRF token mismatch。
APP_URL、SESSION_DOMAIN、SANCTUM_STATEFUL_DOMAINS 三处与实际访问地址(含端口)不一致所致。本文实测环境中三处统一为 localhost:8129。经反向代理(HTTPS 域名)访问时,APP_URL 改为 https://域名,SESSION_DOMAIN 改为该域名,SANCTUM_STATEFUL_DOMAINS 改为 域名,并把代理加入 TRUSTED_PROXIES。
Q2:首次启动后访问一直 502 或连接被重置。
镜像健康检查未通过,Web 服务尚未就绪。用 docker compose ps 看 STATUS 是否 Up (healthy),用 docker compose logs webapp 查启动报错;若日志见数据库连接错误,按第五章排障二检查 DB_HOST 与 depends_on 配置。
Q3:docker compose up -d 报 port is already allocated。
宿主端口被其他服务占用(本文实测曾在 8146 端口遇到)。ss -ltnp | grep <端口> 找到占用者,改用空闲端口并同步修改 APP_URL/SANCTUM_STATEFUL_DOMAINS。
Q4:升级后版本没变。
确认执行过 docker compose pull(只 up -d 不会拉新镜像);再用 docker compose exec webapp php -v 验证。若 tag 锁定在精确版本(如 2.4.7),需改 image: 行的 tag。安全升级(如 2.4.6 → 2.4.7)务必确认 php -v 已是新版要求的 8.4.27。
Q5:周期发票一直没有自动生成。
镜像内置调度器负责该任务(每分钟跑 recurring-invoices:generate)。确认镜像为近期版本(旧镜像不含调度器,官方 README 明确提示重拉镜像);多副本部署时确认只有一个副本 SCHEDULER_ENABLED=true。验证方式:docker compose exec webapp php artisan schedule:list,应列出三条调度任务(实测见本专栏《InvoiceShelf 2.4.7 常用 CLI 命令与工具详解》)。
Q6:想换端口或迁移到新服务器怎么办。
换端口:改 ports: 宿主侧端口,并同步 APP_URL/SESSION_DOMAIN/SANCTUM_STATEFUL_DOMAINS,docker compose up -d 重建。迁服务器:先 docker compose exec webapp php artisan backup:run,把 storage 卷(MariaDB 变体再加数据库导出)与 Modules 卷数据拷到新机,新机按本文流程部署后恢复数据,.env 中的 APP_KEY 保持与原机一致。
十三、参考链接
- 官方 Docker 仓库(镜像与 Compose 示例):https://github.com/InvoiceShelf/docker
- 2.4.7 安全发布公告:https://github.com/InvoiceShelf/InvoiceShelf/releases/tag/2.4.7
- 主仓库:https://github.com/InvoiceShelf/InvoiceShelf
- 官方文档站安装指南:https://docs.invoiceshelf.com/installation.html
- serversideup/php 底座镜像文档(镜像环境变量体系来源):https://github.com/serversideup/docker-php
- 会话域配置官方说明(issue #213):https://github.com/InvoiceShelf/InvoiceShelf/issues/213
- 本专栏配置篇:《InvoiceShelf 2.4.7 配置参数详解》
- 本专栏 CLI 篇:《InvoiceShelf 2.4.7 常用 CLI 命令与工具详解》
- 本专栏认知篇:《InvoiceShelf 介绍与选型指南》