#1 「详细信息」「移动到相册」弃用右侧抽屉,改复用 x-modal 的居中卡片弹窗(新增 #image-detail-modal / #image-movements-modal 及其内容容器,三个新模板): - 详细信息:顶部小缩略图 + dl 行式布局(<640px 自动上下堆叠),标签 13px / 值 14px / leading-6;字段顺序按老师要求 = 上传时间 → 图片名称 → 其余 10 项(原抽屉里 12 项一个没删, 只换位置);弹窗内不放复制链接/下载/删除(单一职责)。 - 移动到相册:单选列表(当前所在相册带「当前」徽标)、行 min-h-[44px](手机点击区)、 未选中时「移动」disabled;请求逐字沿用原实现(同 route user.images.movement、同 payload); 点「移动」才提交,成功关弹窗 + resetImages + toastr。 - 右侧抽屉保留本职(工具栏「相册列表」入口、自带无限加载、相册增删改查)原样不动; 桌面右键、手机长按、工具栏三个入口都走新弹窗。 #2 二级菜单「<返回」箭头与文字间距:context-js.less 加 7px(选择器权重压过标记自带 mr-1)。 关键:本轮的 images.blade.php 改动不属于补丁文件(context-js.js 两份 md5 全程 = Dockerfile 钉住的 b916555a…,未动),Dockerfile 的 images_blade_md5 已随自证同步更新为 27bb3f20…,补丁重生成 2563 行 且「打回上游 = 仓库文件」字节一致。 验证:四套回归我自己跑过 —— longpress 79/79、sidebar 6/6、images-modal 35/35(静态契约: 12 字段与顺序 / 13-14px 字号 / min-h-44 / 请求不变 / 无硬编码色 / 返回键 7px / 补丁 md5 未变)、 images-modal-dom 35/35(jsdom 真跑页面内联脚本:点菜单 → 内容进新弹窗、抽屉全程为空且未被推开、 单选互斥、点「移动」实发 {selected,id,album_id} 后关弹窗、抽屉路径仍能筛选相册); php -l + view:cache exit 0;重建产物含 text-[13px]/[14px]/min-h-[44px]/max-h-[50vh]/ls-badge 等。
221 lines
13 KiB
Docker
221 lines
13 KiB
Docker
# ---------------------------------------------------------------------------
|
||
# Lsky Pro Docker 镜像 —— mole404/lsky-pro-docker
|
||
#
|
||
# 上游应用:https://github.com/lsky-org/lsky-pro (GPL-3.0,官方已停止维护)
|
||
# 上游镜像:https://github.com/HalcyonAzure/lsky-pro-docker (AGPL-3.0,本仓库由它衍生)
|
||
#
|
||
# 本仓库 = 上游应用源码快照(vendored 在 src/)+ Docker 构建脚本 + 少量前端补丁。
|
||
#
|
||
# 与上游镜像的差异(详见 README):
|
||
# 1. 应用源码**已 vendored 进本仓库**(src/ = 上游 commit 38d52c46… 即 2025-11-24 的 master 完整树)。
|
||
# 构建不再联网拉 GitHub archive:上游已明示停止维护,万一仓库被删/归档/改名也还能重建镜像;
|
||
# 之后要改 PHP 代码,直接改 src/ 下的文件、提交即可,不用再维护 overlay 叠加。
|
||
# 2. 前端补丁已就地落在 src/ 里(iOS Safari 长按弹菜单 + 菜单交互修复)。
|
||
# "我们相对上游改了什么"见 patches/ios-longpress.patch,可用 tools/diff-vs-upstream.sh 重新生成/核对。
|
||
# 3. 基础镜像显式写成 Debian bookworm 变体(与 2024-04 那版线上镜像同一 Debian 大版本)
|
||
# 4. install-php-extensions 钉到具体版本,不再用 latest
|
||
# 5. 构建期自证:① 我们从不修改的上游文件按上游 md5 校验(快照没被动过)
|
||
# ② 补丁产物与「有意偏离上游」的 composer.lock 按预期 md5 校验(改了不更新就构建失败)
|
||
#
|
||
# 构建:docker build -t lsky-pro-docker .
|
||
# ---------------------------------------------------------------------------
|
||
|
||
# 上游源码快照的版本号(只用于版本标记与镜像元数据;代码本体是仓库里的 src/)。
|
||
# 改这里 = 必须同时用 tools/vendor-upstream.sh 重新 vendor src/,否则标记与实际代码不符(自证 1 会失败)。
|
||
ARG LSKY_COMMIT=38d52c4609eb85236b45ac75acac2ced55174953
|
||
# PHP 版本:8.1 已于 2025-12-31 EOL,8.2 的 EOL 是 2026-12-31(都太近),
|
||
# 所以选 8.3(安全维护到 2027-12-31)。依赖侧配套升到同一大版本线内的最新:
|
||
# laravel/framework 9.52.21(9.x 最后一个补丁)+ symfony/* 6.4 LTS(Laravel 9 的 ^6.0 正好允许)。
|
||
# 要回退 PHP:改这个数字即可,但请连镜像 tag 一起回退(新 lock 里的包可能要求 ≥8.3)。
|
||
ARG PHP_VERSION=8.3
|
||
ARG DEBIAN_RELEASE=bookworm
|
||
ARG PHP_EXT_INSTALLER_VERSION=2.12.0
|
||
|
||
FROM php:${PHP_VERSION}-cli-${DEBIAN_RELEASE} AS build
|
||
|
||
ARG LSKY_COMMIT
|
||
ARG FORK_SHA=unknown
|
||
|
||
WORKDIR /build
|
||
|
||
# 安装必要的依赖
|
||
# curl —— 装 composer
|
||
# unzip —— composer 解压 dist 包要用(去掉它会导致 composer install 直接失败:CI 实测踩过)
|
||
# git —— 部分包会走 source 安装时的兜底
|
||
RUN docker-php-ext-install ftp
|
||
|
||
# 依赖安装(builder 阶段的平台要求必须满足,否则 composer install 直接失败)
|
||
RUN apt-get update && \
|
||
apt-get install -y curl unzip git && \
|
||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \
|
||
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||
|
||
# 应用源码:本仓库 src/ 里的 vendored 快照(= 上游那个 commit 的完整树,304 个文件)。
|
||
# 前端补丁已经就地在 src/ 里改好,这里不做任何"叠加覆盖"。改代码 = 改 src/ 然后提交。
|
||
COPY src/ /build/
|
||
|
||
# 自证 1:vendored 快照确实是上游那一版。
|
||
# 下面这两个文件我们从不修改,md5 全部等于上游原值;任何一处对不上都说明 src/ 被误改
|
||
# (或与 LSKY_COMMIT 不符)→ 直接构建失败,不产出不可信的镜像。
|
||
RUN printf '%s\n' \
|
||
'9fb843806abd6b778d8acd3366e2f0f1 ./app/Services/ImageService.php' \
|
||
'3b58bff18126a61c142cc576457c82a6 ./public/index.php' \
|
||
| md5sum -c -
|
||
|
||
# 自证 1b:有意偏离上游、但仍需锁死的文件。
|
||
# config/convention.php 与 routes/web.php 被本 fork 改过 —— 移除了「画廊」「系统升级」,
|
||
# 且首页 / 在登录状态下改为跳转「我的图片」(游客上传页只留给未登录用户)
|
||
# 两个功能(删配置项常量、删路由表条目,详见 README)。md5 随改动更新,作用不变:
|
||
# 这两个文件以后只要被改动(哪怕手滑),构建就会红。
|
||
RUN printf '%s\n' \
|
||
'ee439977cfcb2e4d3545b25689198c71 ./config/convention.php' \
|
||
'f6167a0726f8f2892494952a14c2bf49 ./routes/web.php' \
|
||
| md5sum -c -
|
||
|
||
# 有意偏离上游的另一个文件:composer.lock。
|
||
# 上游冻结在 2024-12 的解析结果(laravel 9.52.17 / symfony 6.0.x —— 两者都已 EOL),
|
||
# 我们把它升到「同一大版本线内的安全版本」:
|
||
# laravel/framework 9.52.21(9.x 最后一个补丁)、symfony/* 6.4 LTS(Laravel 9 的 ^6.0 允许)、
|
||
# guzzlehttp/guzzle 7.15.5、guzzlehttp/psr7 2.13.1、phpseclib 3.0.57、
|
||
# league/commonmark 2.10.3、aws/aws-sdk-php 3.398.1、laminas-diactoros 2.26.0
|
||
# —— 修掉了除「Laravel 9 框架自身那几条(9.x 线没有修复版本)」以外的已知公告。
|
||
# 所以它不再等于上游值 —— 但仍钉 md5:任何改动都必须同步更新这里(防止有人别处悄悄改)。
|
||
RUN printf '%s\n' \
|
||
'9dfc7d029808dbca37cc239560e8f49f ./composer.lock' \
|
||
| md5sum -c -
|
||
|
||
# --no-dev:镜像只装运行时依赖。开发包(debugbar / ignition / whoops / phpunit / faker / sail…)
|
||
# 对线上没有用途,留着既是体积也是暴露面(debugbar 那类在调试模式下会漏内部信息)。
|
||
# 连带项:卷里的 bootstrap/cache/packages.php 是"当年装着开发包"时生成的,里面记着这些包的
|
||
# ServiceProvider 类名 —— 包没了之后,Laravel 引导时加载该清单会 Class not found → 整站 500。
|
||
# 所以 entrypoint 的同步分支会作废这份清单(连同 services.php),CI 里也有对应的回归断言。
|
||
RUN php -r "file_exists('.env') || copy('.env.example', '.env');" \
|
||
&& composer install --no-dev
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# fork 补丁:iOS 长按菜单修复 + 菜单交互修复(已就地在 src/ 里,这里只做校验)
|
||
#
|
||
# 补丁涉及三个文件(两份 JS 内容必须一致,别只改一份):
|
||
# src/resources/js/context-js.js —— 可读源码
|
||
# src/public/js/context-js/context-js.js —— 浏览器实际加载的那份
|
||
# src/resources/views/user/images.blade.php —— 引入脚本那一行(资源版本串)
|
||
# (上游 webpack.mix.js 里本来也是 mix.copy('resources/js/context-js.js', 'public/js/context-js'),
|
||
# 只是仓库里 public/ 下那份是旧工具链留下的压缩产物,一直没跟着源码更新。)
|
||
# ---------------------------------------------------------------------------
|
||
|
||
# 自证 2:补丁内容与预期完全一致,blade 的资源版本串也在。
|
||
# 改 src/ 里这三个文件后必须同步更新这里的 md5(故意做成"改了不更新就构建失败"),
|
||
# 并重新生成 patches/ios-longpress.patch(tools/diff-vs-upstream.sh)。
|
||
RUN printf '%s\n' \
|
||
'b916555ab122d2b3db99153d9316a887 ./public/js/context-js/context-js.js' \
|
||
'b916555ab122d2b3db99153d9316a887 ./resources/js/context-js.js' \
|
||
'27bb3f203c931633961798dda7aab7dc ./resources/views/user/images.blade.php' \
|
||
| md5sum -c - \
|
||
&& grep -q "assetVersion('js/context-js/context-js.js')" ./resources/views/user/images.blade.php \
|
||
&& grep -q 'isIOSWebKit' ./public/js/context-js/context-js.js \
|
||
&& grep -q 'LONG_PRESS_DELAY = 250' ./public/js/context-js/context-js.js \
|
||
&& grep -q 'LONG_PRESS_DELAY = 250' ./resources/js/context-js.js \
|
||
&& grep -q 'installMenuGuard' ./public/js/context-js/context-js.js \
|
||
&& grep -q 'MENU_OPEN_GRACE' ./public/js/context-js/context-js.js \
|
||
&& grep -q 'touch-open' ./public/js/context-js/context-js.js \
|
||
&& grep -q 'fitSubmenu' ./public/js/context-js/context-js.js \
|
||
&& grep -q 'clampMenu' ./resources/js/context-js.js \
|
||
&& grep -q 'submenu-inplace' ./public/js/context-js/context-js.js \
|
||
&& grep -q 'SUBMENU_GUARD' ./public/js/context-js/context-js.js
|
||
|
||
# 代码版本标记:入口脚本用它判断「卷里的代码是不是当前镜像这一版」,不一致才同步(见 entrypoint.sh)。
|
||
# 它由源码 commit + 补丁 md5 组成,正好是上面刚断言过的值 —— 任何代码/补丁变化都会让它变。
|
||
# 改 src/ 下任何文件(哪怕一行)后,都要把对应的 md5 一并更新,否则容器不会重新同步进卷。
|
||
RUN printf '%s\n' \
|
||
"fork_sha=${FORK_SHA}" \
|
||
"lsky_commit=${LSKY_COMMIT}" \
|
||
"context_js_md5=b916555ab122d2b3db99153d9316a887" \
|
||
"images_blade_md5=27bb3f203c931633961798dda7aab7dc" \
|
||
> .code-revision \
|
||
&& cat .code-revision
|
||
|
||
FROM php:${PHP_VERSION}-apache-${DEBIAN_RELEASE}
|
||
|
||
ARG LSKY_COMMIT
|
||
ARG PHP_EXT_INSTALLER_VERSION
|
||
ARG FORK_SHA=unknown
|
||
|
||
LABEL org.opencontainers.image.source="https://github.com/mole404/lsky-pro-docker" \
|
||
org.opencontainers.image.title="lsky-pro-docker (ios-longpress + menu-ux)" \
|
||
org.opencontainers.image.description="Lsky Pro 图床的 Docker 镜像;应用源码 vendored 取自 lsky-org/lsky-pro@${LSKY_COMMIT}(构建不再依赖上游在线),并在其上做了 iOS 长按菜单修复与菜单交互修复(点菜单外只关菜单、触摸端二级菜单点击展开、滚动/缩放/Esc 关闭)" \
|
||
org.opencontainers.image.licenses="AGPL-3.0" \
|
||
org.opencontainers.image.revision="${FORK_SHA}" \
|
||
lsky.source.commit="${LSKY_COMMIT}"
|
||
|
||
# 如果构建速度慢可以换源
|
||
# RUN sed -i -E "s@http://***@http://mirrors.cloud.tencent.com@g" /etc/apt/sources.list
|
||
# 安装相关拓展(钉到具体版本,不使用 latest)
|
||
RUN curl -sSL -o /usr/local/bin/install-php-extensions \
|
||
"https://github.com/mlocati/docker-php-extension-installer/releases/download/${PHP_EXT_INSTALLER_VERSION}/install-php-extensions"
|
||
|
||
# 开启SSL
|
||
RUN a2enmod ssl && a2ensite default-ssl
|
||
|
||
# ftp 必须**显式**装进运行时镜像:官方 php:8.1 镜像自带 ftp,php:8.3 的没有
|
||
# (2026-09-28 换 8.3 时 CI 实测:builder 阶段 composer install 直接失败,
|
||
# 报 league/flysystem-ftp requires ext-ftp)。它是 Lsky 的 FTP 存储驱动要用的扩展,
|
||
# 不能依赖"从基镜像继承"。CI 里也加了 ftp 的硬断言。
|
||
RUN apt-get update && \
|
||
apt-get install -y gettext && \
|
||
apt-get clean && rm -rf /var/cache/apt/* && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* && \
|
||
a2enmod rewrite && chmod +x /usr/local/bin/install-php-extensions && \
|
||
install-php-extensions imagick bcmath pdo_mysql pdo_pgsql redis ftp && \
|
||
\
|
||
{ \
|
||
echo 'post_max_size = 100M;';\
|
||
echo 'upload_max_filesize = 100M;';\
|
||
echo 'max_execution_time = 600S;';\
|
||
} > /usr/local/etc/php/conf.d/docker-php-upload.ini; \
|
||
\
|
||
{ \
|
||
echo 'opcache.enable=1'; \
|
||
echo 'opcache.interned_strings_buffer=8'; \
|
||
echo 'opcache.max_accelerated_files=10000'; \
|
||
echo 'opcache.memory_consumption=128'; \
|
||
echo 'opcache.save_comments=1'; \
|
||
echo 'opcache.revalidate_freq=1'; \
|
||
} > /usr/local/etc/php/conf.d/opcache-recommended.ini; \
|
||
\
|
||
echo 'apc.enable_cli=1' >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini; \
|
||
\
|
||
echo 'memory_limit=512M' > /usr/local/etc/php/conf.d/memory-limit.ini; \
|
||
\
|
||
mkdir /var/www/data; \
|
||
chown -R www-data:root /var/www; \
|
||
chmod -R g=u /var/www
|
||
|
||
COPY ./ssl /etc/ssl
|
||
|
||
COPY --from=build /build /var/www/lsky/
|
||
COPY ./000-default.conf.template /etc/apache2/sites-enabled/
|
||
COPY ./ports.conf.template /etc/apache2/
|
||
COPY entrypoint.sh /
|
||
|
||
# 数据安全护栏:强制同步的排除清单缺任何一项都可能覆盖站点数据/配置,缺了就构建失败。
|
||
# (镜像自带入口脚本运行时才会执行,这里只做静态断言,保证清单不被误删。)
|
||
RUN grep -q -- '--exclude=.\/.env' /entrypoint.sh \
|
||
&& grep -q -- '--exclude=.\/storage' /entrypoint.sh \
|
||
&& grep -q -- '--exclude=.\/database' /entrypoint.sh \
|
||
&& grep -q -- '--exclude=.\/bootstrap\/cache' /entrypoint.sh \
|
||
&& grep -q -- '--exclude=.\/public\/i' /entrypoint.sh \
|
||
&& grep -q 'views/\*.php' /entrypoint.sh \
|
||
&& grep -q 'code-revision' /entrypoint.sh \
|
||
&& test -f /var/www/lsky/.code-revision \
|
||
&& grep -q '^fork_sha=' /var/www/lsky/.code-revision \
|
||
&& grep -q 'tar cf - --exclude=./.env --exclude=./.code-revision' /entrypoint.sh \
|
||
&& grep -q 'cp -a "$IMAGE_MARKER" "$VOLUME_MARKER"' /entrypoint.sh
|
||
WORKDIR /var/www/html/
|
||
VOLUME /var/www/html
|
||
ENV WEB_PORT 8089
|
||
ENV HTTPS_PORT 8088
|
||
EXPOSE ${WEB_PORT}
|
||
EXPOSE ${HTTPS_PORT}
|
||
RUN chmod a+x /entrypoint.sh
|
||
ENTRYPOINT ["/entrypoint.sh"]
|
||
CMD ["apachectl","-D","FOREGROUND"]
|