优化 Docker 镜像复制层 (#6540)

* perf(docker): consolidate runtime copy layers

* test(docker): align control rootfs contract
This commit is contained in:
InfinityPacer
2026-09-01 21:36:23 +08:00
committed by GitHub
parent c9f339a572
commit 55d8680851
3 changed files with 30 additions and 25 deletions

View File

@@ -268,17 +268,21 @@ FROM prepare_payload AS prepare_control
WORKDIR /control
COPY docker/ ./
RUN mkdir -p /bundle/control /bundle/nginx /bundle/bin \
&& find . -maxdepth 1 -type f -name '*.sh' ! -name 'launcher.sh' -exec cp -f -t /bundle/control {} + \
&& cp -f launcher.sh /bundle/entrypoint.sh \
&& cp -f nginx.common.conf /bundle/nginx/common.conf \
&& cp -f nginx.template.conf /bundle/nginx/nginx.template.conf \
&& cp -f docker_http_proxy.conf /bundle/nginx/docker_http_proxy.conf \
&& printf '%s\n' '#!/usr/bin/env bash' 'set -euo pipefail' 'cd /app' 'exec "${VENV_PATH:-/opt/venv}/bin/python3" -m app.cli "$@"' > /bundle/bin/moviepilot \
&& bash -n /bundle/entrypoint.sh \
&& for control_script in /bundle/control/*.sh; do bash -n "${control_script}" || exit 1; done \
&& chmod 755 /bundle/entrypoint.sh /bundle/bin/moviepilot \
&& chmod 500 /bundle/control/*.sh
RUN mkdir -p \
/bundle/rootfs/etc/nginx \
/bundle/rootfs/usr/local/bin \
/bundle/rootfs/usr/local/lib/moviepilot/control \
&& find . -maxdepth 1 -type f -name '*.sh' ! -name 'launcher.sh' \
-exec cp -f -t /bundle/rootfs/usr/local/lib/moviepilot/control {} + \
&& cp -f launcher.sh /bundle/rootfs/entrypoint.sh \
&& cp -f nginx.common.conf /bundle/rootfs/etc/nginx/common.conf \
&& cp -f nginx.template.conf /bundle/rootfs/etc/nginx/nginx.template.conf \
&& cp -f docker_http_proxy.conf /bundle/rootfs/etc/nginx/docker_http_proxy.conf \
&& printf '%s\n' '#!/usr/bin/env bash' 'set -euo pipefail' 'cd /app' 'exec "${VENV_PATH:-/opt/venv}/bin/python3" -m app.cli "$@"' > /bundle/rootfs/usr/local/bin/moviepilot \
&& bash -n /bundle/rootfs/entrypoint.sh \
&& for control_script in /bundle/rootfs/usr/local/lib/moviepilot/control/*.sh; do bash -n "${control_script}" || exit 1; done \
&& chmod 755 /bundle/rootfs/entrypoint.sh /bundle/rootfs/usr/local/bin/moviepilot \
&& chmod 500 /bundle/rootfs/usr/local/lib/moviepilot/control/*.sh
# final 阶段: 安装运行时依赖和配置最终镜像
FROM prepare_package AS final
@@ -287,8 +291,7 @@ ENV LD_PRELOAD="/usr/local/lib/libjemalloc.so" \
MOVIEPILOT_DOCKER_KEEPALIVE_ON_FAILURE="true"
# 引入支持 amr 编码的静态 ffmpeg
COPY --from=ffmpeg /ffmpeg /usr/local/bin/
COPY --from=ffmpeg /ffprobe /usr/local/bin/
COPY --from=ffmpeg /ffmpeg /ffprobe /usr/local/bin/
COPY --from=rclone /usr/local/bin/rclone /usr/bin/rclone
# python 环境
@@ -306,12 +309,7 @@ RUN playwright install-deps chromium \
/var/tmp/*
# 准备容器控制面和运行目录
COPY --from=prepare_control /bundle/entrypoint.sh /entrypoint.sh
COPY --from=prepare_control /bundle/control /usr/local/lib/moviepilot/control
COPY --from=prepare_control /bundle/nginx/common.conf /etc/nginx/common.conf
COPY --from=prepare_control /bundle/nginx/nginx.template.conf /etc/nginx/nginx.template.conf
COPY --from=prepare_control /bundle/nginx/docker_http_proxy.conf /etc/nginx/docker_http_proxy.conf
COPY --from=prepare_control /bundle/bin/moviepilot /usr/local/bin/moviepilot
COPY --link --from=prepare_control /bundle/rootfs/ /
RUN mkdir -p ${HOME} \
&& groupadd -r moviepilot -g 918 \

View File

@@ -42,18 +42,22 @@ def test_dockerfile_control_bundle_build_checks_fail_closed() -> None:
assert "requirements.in" not in dockerfile
assert "${VENV_PATH}/bin/pip" not in dockerfile
assert "FROM prepare_payload AS prepare_control" in dockerfile
assert "-exec cp -f -t /bundle/control {} +" in dockerfile
assert "bash -n /bundle/entrypoint.sh" in dockerfile
assert (
"COPY --from=prepare_control /bundle/control "
"/usr/local/lib/moviepilot/control" in dockerfile
"-exec cp -f -t /bundle/rootfs/usr/local/lib/moviepilot/control {} +"
in dockerfile
)
assert "bash -n /bundle/rootfs/entrypoint.sh" in dockerfile
assert (
"COPY --link --from=prepare_control /bundle/rootfs/ /" in dockerfile
)
assert 'ENTRYPOINT [ "/usr/bin/tini", "-g", "--", "/entrypoint.sh" ]' in dockerfile
assert "CMD /usr/bin/curl -fsS" in dockerfile
assert '"http://127.0.0.1:${PORT:-3001}/health/ready"' in dockerfile
assert "system/global?token=moviepilot" not in dockerfile
assert (
'for control_script in /bundle/control/*.sh; do bash -n "${control_script}" || exit 1; done'
"for control_script in "
'/bundle/rootfs/usr/local/lib/moviepilot/control/*.sh; do '
'bash -n "${control_script}" || exit 1; done'
in dockerfile
)

View File

@@ -75,7 +75,10 @@ def test_dockerfile_assigns_each_payload_to_an_independent_stage() -> None:
assert positions == sorted(positions)
for copy in copies:
assert final.count(copy) == 1
assert "COPY --from=prepare_control /bundle/entrypoint.sh /entrypoint.sh" in final
assert "COPY --link --from=prepare_control /bundle/rootfs/ /" in final
assert final.count("--from=prepare_control ") == 1
assert "COPY --from=ffmpeg /ffmpeg /ffprobe /usr/local/bin/" in final
assert final.count("COPY --from=ffmpeg ") == 1
assert "RUN rm -rf /app/frontend-dist" in dockerfile