Files
lsky-pro-docker/Dockerfile
T
mole404 30862d602f feat(图片页 1/2): 详细信息与移动到相册改用居中卡片弹窗、二级菜单返回键加空隙
#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 等。
2026-09-29 14:34:25 +08:00

221 lines
13 KiB
Docker
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ---------------------------------------------------------------------------
# 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"]