Files
lsky-pro-docker/Dockerfile
T
mole404 7ddb15b7bd fix(sync): 改成「按镜像版本标记」条件同步,并修掉首启分支把 .env 带进空卷的 500
老师选定方案甲(按版本标记条件同步),并修掉上一次 CI 抓到的真问题。

1) 修 500(我上一次改动引入的):首启分支还原成与上游逐字一致
   `cp -a /var/www/lsky/* /var/www/html/` + 单独拷 .env.example。
   镜像是带 .env 的(构建时由 .env.example 生成、APP_KEY 为空),
   上一版用 `cp -a /var/www/lsky/.` 把它带进了空卷,Lsky 安装向导撞上已存在的
   空 .env 直接 500 —— 全新建站会挂。现在钉了构建期护栏:首启分支必须保持
   `/*` 形态且必须拷 .env.example,否则构建失败。

2) 版本标记:build 阶段生成 .code-revision(fork sha + 源码 commit + 两个补丁 md5),
   入口脚本比较镜像内与卷内这一份:
     空卷               → 全量播种(并写上标记)
     已有卷 + 标记不同  → 同步代码 + 清编译视图缓存(= 换了镜像)
     已有卷 + 标记相同  → 跳过(不白写整棵应用树,手改保留)
   排除清单不变:.env / storage / database / bootstrap/cache / public/i 一律不碰。
   附带好处:回滚也变成「换一行 image」—— 旧镜像标记不同会自动把代码同步回去。

3) CI 自证重写为三个真实 docker 场景(不过就不 promote latest):
   A) 空卷:安装页 200 + 卷里必须没有 .env(钉住上面那个 500 的根因)
   B) 已有卷 + 旧标记:代码被同步、.env(含权限位)/数据库/上传/config 缓存一项不被碰、视图缓存已清
   C) 已有卷 + 同标记:跳过同步、手动修补保留、对外服务的 JS 仍是补丁版

本地自证:入口脚本三分支仿真 15/15、jsdom 行为测试 25/25、
Dockerfile 全部构建期断言 grep 命中、workflow 三个 run 脚本 bash/sh -n 通过。
2026-09-28 18:59:14 +08:00

168 lines
7.9 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/HalcyonAzure/lsky-pro-docker ,AGPL-3.0)
#
# 与上游的差异(详见 README):
# 1. 源码钉死在 LSKY_COMMIT,不再在构建时拉 master,镜像内容不会随上游漂移
# 2. 叠加 overlay/ 里的前端补丁:修复 iOS Safari 长按无法弹出图床自定义菜单的问题
# 3. 基础镜像显式写成 Debian bookworm 变体(与 2024-04 那版线上镜像同一 Debian 大版本)
# 4. install-php-extensions 钉到具体版本,不再用 latest
# 5. 构建期自证:源码快照与补丁产物都用 md5 断言,对不上直接构建失败
#
# 构建:docker build -t lsky-pro-docker .
# ---------------------------------------------------------------------------
# 上游源码快照:911275c 是 2024-04-29 构建的 halcyonazure/lsky-pro-docker:latest 所使用的 master HEAD
ARG LSKY_COMMIT=911275c13b038c7a8b710de44664f23887eeb6f6
ARG PHP_VERSION=8.1
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
# 安装必要的依赖
RUN apt-get update && \
apt-get install -y curl unzip && \
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/*
# 拉取钉死的源码快照(上游原本是拉 refs/heads/master)
RUN curl -sSL -o lsky.zip "https://github.com/lsky-org/lsky-pro/archive/${LSKY_COMMIT}.zip" \
&& unzip lsky.zip \
&& mv "./lsky-pro-${LSKY_COMMIT}"/* ./ \
&& mv "./lsky-pro-${LSKY_COMMIT}/.env.example" ./ \
&& rm -rf lsky.zip "lsky-pro-${LSKY_COMMIT}"
# 自证 1:确认拉到的确实是预期的那份上游快照。
# 对不上说明上游 archive 变了或 LSKY_COMMIT 被改错,直接让构建失败,不要产出不可信的镜像。
RUN printf '%s\n' \
'bab81ff5e43b50a760935c7b3ae6475c ./public/js/context-js/context-js.js' \
'a7bcd8549c656501a057214637f10b45 ./app/Services/ImageService.php' \
'674975e4e5561cc15c27626cb1ce5233 ./config/convention.php' \
'22c896eb7322ec2ff37d5eddd7ca0dec ./resources/views/user/images.blade.php' \
| md5sum -c -
RUN php -r "file_exists('.env') || copy('.env.example', '.env');" \
&& composer install
# ---------------------------------------------------------------------------
# fork 补丁:iOS 长按菜单修复
#
# overlay/context-js.js 同时写到两个位置:
# resources/js/context-js.js —— 补丁的可读源码
# public/js/context-js/context-js.js —— 浏览器实际加载的那份
# (上游 webpack.mix.js 里本来也是 mix.copy('resources/js/context-js.js', 'public/js/context-js'),
# 只是仓库里 public/ 下那份是旧工具链留下的压缩产物,一直没跟着源码更新。)
# ---------------------------------------------------------------------------
COPY overlay/context-js.js ./resources/js/context-js.js
COPY overlay/context-js.js ./public/js/context-js/context-js.js
COPY overlay/images.blade.php ./resources/views/user/images.blade.php
# 自证 2:补丁确实落盘、内容与预期完全一致;blade 的版本串也在。
# 以后改 overlay/ 里的文件,记得同步更新这里的 md5(故意做成"改了不更新就构建失败")。
RUN printf '%s\n' \
'528d32fc5adc0d306b6d8f773ee5caaf ./public/js/context-js/context-js.js' \
'528d32fc5adc0d306b6d8f773ee5caaf ./resources/js/context-js.js' \
'576929df685fdb93f9950c16d924bcdc ./resources/views/user/images.blade.php' \
| md5sum -c - \
&& grep -q "context-js.js') . '?v=ios-longpress2'" ./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
# 代码版本标记:入口脚本用它判断「卷里的代码是不是当前镜像这一版」,不一致才同步(见 entrypoint.sh)。
# 它由源码 commit + 补丁 md5 组成,正好是上面刚断言过的值 —— 任何代码/补丁变化都会让它变。
RUN printf '%s\n' \
"fork_sha=${FORK_SHA}" \
"lsky_commit=${LSKY_COMMIT}" \
"context_js_md5=528d32fc5adc0d306b6d8f773ee5caaf" \
"images_blade_md5=576929df685fdb93f9950c16d924bcdc" \
> .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)" \
org.opencontainers.image.description="Lsky Pro 图床的 Docker 镜像;源码钉在 lsky-org/lsky-pro@${LSKY_COMMIT},并叠加 iOS 长按菜单修复" \
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
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 && \
\
{ \
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 'cp -a /var/www/lsky/\* /var/www/html/' /entrypoint.sh \
&& grep -q 'cp -a /var/www/lsky/.env.example /var/www/html' /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"]