From fbfa3da5ebac618f2e339bb26359718d097045c3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 May 2026 05:05:27 +0000 Subject: [PATCH 1/4] fix: use gosu entrypoint to fix SQLite error 14 on root-owned bind mounts Agent-Logs-Url: https://github.com/PoiCraft/MotdTracker/sessions/bda16920-ffa7-4459-b1e1-0200ecb9645d Co-authored-by: gggxbbb <39845709+gggxbbb@users.noreply.github.com> --- Dockerfile | 15 +++++++++++---- entrypoint.sh | 10 ++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 entrypoint.sh diff --git a/Dockerfile b/Dockerfile index 61ac35d..7bd0e0a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,21 +28,24 @@ RUN cargo build --release FROM debian:bookworm-slim AS runtime RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates \ + ca-certificates gosu \ && rm -rf /var/lib/apt/lists/* WORKDIR /app -# Copy only the compiled binary +# Copy only the compiled binary and the entrypoint helper COPY --from=builder /app/target/release/motdtracker . +COPY entrypoint.sh /app/entrypoint.sh +RUN chmod +x /app/entrypoint.sh # Create the default data directory for the SQLite database RUN mkdir -p data -# Run as a non-root user for better security +# Create the unprivileged runtime user. +# chown the data dir so anonymous Docker volumes are initialised with the +# correct ownership; the entrypoint.sh re-applies chown for bind mounts. RUN useradd -r -u 10001 -s /bin/false motdtracker \ && chown motdtracker:motdtracker /app/data -USER motdtracker # Persist the SQLite database across container restarts VOLUME ["/app/data"] @@ -50,9 +53,13 @@ VOLUME ["/app/data"] # Default listen port (matches the default in AppConfig) EXPOSE 5011 +# entrypoint.sh runs as root, fixes /app/data ownership, then drops to the +# motdtracker user via gosu before executing the application. +# # Mount your config.toml at /app/config.toml before starting. # Example: # docker run -v ./config.toml:/app/config.toml \ # -v motdtracker_data:/app/data \ # -p 5011:5011 ghcr.io/poicraft/motdtracker +ENTRYPOINT ["/app/entrypoint.sh"] CMD ["./motdtracker"] diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..51d1df3 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +# When /app/data is bind-mounted from the host Docker may create the directory +# as root, preventing the unprivileged motdtracker user from writing the SQLite +# database. Fix ownership here (runs as root before privilege drop). +chown -R motdtracker:motdtracker /app/data || \ + echo "Warning: could not chown /app/data – database writes may fail if the directory is root-owned" + +exec gosu motdtracker "$@" \ No newline at end of file From b33420ec7dfdbc7c181eaab67c913eec69a2f13d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 May 2026 05:07:25 +0000 Subject: [PATCH 2/4] docs: fix Docker section in README - correct image name and replace hard tabs Agent-Logs-Url: https://github.com/PoiCraft/MotdTracker/sessions/0a447b0f-c9fe-41ef-85e5-7963f40a55a2 Co-authored-by: gggxbbb <39845709+gggxbbb@users.noreply.github.com> --- README.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 15e05f7..52ea43d 100644 --- a/README.md +++ b/README.md @@ -326,15 +326,15 @@ git push origin v0.1.0 ### 直接运行(Docker) ```bash -# 拉取镜像(替换为实际 owner/repo) -docker pull ghcr.io/poicraft/motdtracker-rs:latest +# 拉取镜像 +docker pull ghcr.io/poicraft/motdtracker:latest # 以后台模式运行,映射端口并挂载数据目录 docker run -d --name motdtracker \ - -p 5011:5011 \ - -v $(pwd)/data:/app/data \ - -v $(pwd)/config.toml:/app/config.toml \ - ghcr.io/poicraft/motdtracker-rs:latest + -p 5011:5011 \ + -v $(pwd)/data:/app/data \ + -v $(pwd)/config.toml:/app/config.toml \ + ghcr.io/poicraft/motdtracker:latest # 查看日志 docker logs -f motdtracker @@ -347,17 +347,17 @@ docker logs -f motdtracker ```yaml version: "3.8" services: - motdtracker: - image: ghcr.io/poicraft/motdtracker-rs:latest - container_name: motdtracker - restart: unless-stopped - ports: - - "5011:5011" - volumes: - - ./data:/app/data - - ./config.toml:/app/config.toml - environment: - - TZ=Asia/Shanghai + motdtracker: + image: ghcr.io/poicraft/motdtracker:latest + container_name: motdtracker + restart: unless-stopped + ports: + - "5011:5011" + volumes: + - ./data:/app/data + - ./config.toml:/app/config.toml + environment: + - TZ=Asia/Shanghai ``` 启动服务: From 1abe3e8dfbdaac66f5882f8fd816991e7b9e2dd9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 May 2026 05:12:51 +0000 Subject: [PATCH 3/4] fix(build): use commit timestamp and fix unknown hash in Docker builds Agent-Logs-Url: https://github.com/PoiCraft/MotdTracker/sessions/611ba5ac-d9bd-4bd6-99fa-2206fde9cecf Co-authored-by: gggxbbb <39845709+gggxbbb@users.noreply.github.com> --- .github/workflows/release.yml | 9 +++++++++ Dockerfile | 7 ++++++- build.rs | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 849254b..8eb2b08 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -94,6 +94,12 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Get commit metadata + id: commit + run: | + echo "hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + echo "time=$(git log -1 --format=%ct)" >> $GITHUB_OUTPUT + - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -126,6 +132,9 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + build-args: | + GIT_COMMIT_HASH=${{ steps.commit.outputs.hash }} + GIT_COMMIT_TIME=${{ steps.commit.outputs.time }} cache-from: type=gha cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile index 7bd0e0a..8bca695 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,7 +22,12 @@ RUN npm ci --prefix frontend # build.rs will run `npm run build` (node_modules already present) # and embed the resulting dist/ into the binary. COPY . . -RUN cargo build --release + +# Accept git metadata as build args so that build.rs can embed the correct +# version string even though .git is excluded from the Docker build context. +ARG GIT_COMMIT_HASH=unknown +ARG GIT_COMMIT_TIME=0 +RUN GIT_COMMIT_HASH=${GIT_COMMIT_HASH} GIT_COMMIT_TIME=${GIT_COMMIT_TIME} cargo build --release # ---- Stage 2: Runtime ---- FROM debian:bookworm-slim AS runtime diff --git a/build.rs b/build.rs index c52e20e..7261f64 100644 --- a/build.rs +++ b/build.rs @@ -16,20 +16,46 @@ fn main() { } // Generate pseudo version: vA.B.C-yyyyMMddhhmmss-{git-hash-short} + // Falls back to GIT_COMMIT_HASH / GIT_COMMIT_TIME env vars when the .git + // directory is absent (e.g. Docker builds where .git is in .dockerignore). let pkg_version = std::env::var("CARGO_PKG_VERSION").unwrap(); + let git_hash = Command::new("git") .args(["rev-parse", "--short", "HEAD"]) .output() .ok() .filter(|o| o.status.success()) .map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string()) + .or_else(|| std::env::var("GIT_COMMIT_HASH").ok()) .unwrap_or_else(|| "unknown".to_string()); + // Use the commit's own timestamp, not the build time. + let commit_secs = Command::new("git") + .args(["log", "-1", "--format=%ct"]) + .output() + .ok() + .filter(|o| o.status.success()) + .and_then(|o| { + String::from_utf8_lossy(&o.stdout) + .trim() + .parse::() + .ok() + }) + .or_else(|| { + std::env::var("GIT_COMMIT_TIME") + .ok() + .and_then(|s| s.parse::().ok()) + }) + .unwrap_or_else(|| { + use std::time::{SystemTime, UNIX_EPOCH}; + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + }); + let now = { - use std::time::{SystemTime, UNIX_EPOCH}; - let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); - let secs = duration.as_secs(); - let tm = time_from_epoch(secs); + let tm = time_from_epoch(commit_secs); format!( "{:04}{:02}{:02}{:02}{:02}{:02}", tm.0, tm.1, tm.2, tm.3, tm.4, tm.5 From b6b7dead365a74fcb5ddfc14391daba6a68d9ca1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 May 2026 05:27:38 +0000 Subject: [PATCH 4/4] fix: address review feedback on build.rs, Dockerfile, entrypoint.sh and README Agent-Logs-Url: https://github.com/PoiCraft/MotdTracker/sessions/5b47c25e-fa90-4785-90df-4fb89ce304e9 Co-authored-by: gggxbbb <39845709+gggxbbb@users.noreply.github.com> --- Dockerfile | 2 +- README.md | 10 +++++----- build.rs | 3 +++ entrypoint.sh | 9 ++++++--- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8bca695..b4887c7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,7 @@ COPY . . # Accept git metadata as build args so that build.rs can embed the correct # version string even though .git is excluded from the Docker build context. ARG GIT_COMMIT_HASH=unknown -ARG GIT_COMMIT_TIME=0 +ARG GIT_COMMIT_TIME= RUN GIT_COMMIT_HASH=${GIT_COMMIT_HASH} GIT_COMMIT_TIME=${GIT_COMMIT_TIME} cargo build --release # ---- Stage 2: Runtime ---- diff --git a/README.md b/README.md index 52ea43d..62a68ab 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ Rust 高性能后端 + React 前端 · 单文件部署 · 前端内嵌 -[![CI](https://github.com/PoiCraft/motdtracker-rs/actions/workflows/ci.yml/badge.svg)](https://github.com/PoiCraft/motdtracker-rs/actions/workflows/ci.yml) -[![Release](https://img.shields.io/github/v/release/PoiCraft/motdtracker-rs?label=Latest)](https://github.com/PoiCraft/motdtracker-rs/releases/latest) +[![CI](https://github.com/PoiCraft/MotdTracker/actions/workflows/ci.yml/badge.svg)](https://github.com/PoiCraft/MotdTracker/actions/workflows/ci.yml) +[![Release](https://img.shields.io/github/v/release/PoiCraft/MotdTracker?label=Latest)](https://github.com/PoiCraft/MotdTracker/releases/latest) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) [![Rust](https://img.shields.io/badge/Rust-1.75+-orange.svg)](https://www.rust-lang.org/) @@ -36,7 +36,7 @@ MotdTracker 是一个专为 Minecraft 服务器设计的多入口点实时监控 ## 下载预编译版本 -前往 [GitHub Releases](https://github.com/PoiCraft/motdtracker-rs/releases/latest) 下载对应平台的预编译二进制: +前往 [GitHub Releases](https://github.com/PoiCraft/MotdTracker/releases/latest) 下载对应平台的预编译二进制: | 平台 | 文件 | |------|------| @@ -45,7 +45,7 @@ MotdTracker 是一个专为 Minecraft 服务器设计的多入口点实时监控 | macOS x86_64 | `motdtracker-x86_64-apple-darwin.tar.gz` | | macOS ARM64 | `motdtracker-aarch64-apple-darwin.tar.gz` | -> 每次 push 到 main 分支会自动构建,可在 [Actions](https://github.com/PoiCraft/motdtracker-rs/actions/workflows/ci.yml) 页面下载最新开发版 artifact。 +> 每次 push 到 main 分支会自动构建,可在 [Actions](https://github.com/PoiCraft/MotdTracker/actions/workflows/ci.yml) 页面下载最新开发版 artifact。 下载解压后直接运行: @@ -307,7 +307,7 @@ git config core.hooksPath .githooks ## CI / CD -- **push / PR** → 自动 check + test + 多平台构建,产物上传到 [Actions](https://github.com/PoiCraft/motdtracker-rs/actions) +- **push / PR** → 自动 check + test + 多平台构建,产物上传到 [Actions](https://github.com/PoiCraft/MotdTracker/actions) - **打 tag(`v*`)** → 自动构建 + 生成 GitHub Release + 上传预编译二进制 + SHA256 校验和 ```bash diff --git a/build.rs b/build.rs index 7261f64..0c41b8f 100644 --- a/build.rs +++ b/build.rs @@ -14,6 +14,8 @@ fn main() { println!("cargo:rerun-if-changed=.git/{}", ref_path); } } + println!("cargo:rerun-if-env-changed=GIT_COMMIT_HASH"); + println!("cargo:rerun-if-env-changed=GIT_COMMIT_TIME"); // Generate pseudo version: vA.B.C-yyyyMMddhhmmss-{git-hash-short} // Falls back to GIT_COMMIT_HASH / GIT_COMMIT_TIME env vars when the .git @@ -45,6 +47,7 @@ fn main() { std::env::var("GIT_COMMIT_TIME") .ok() .and_then(|s| s.parse::().ok()) + .filter(|&t| t > 0) }) .unwrap_or_else(|| { use std::time::{SystemTime, UNIX_EPOCH}; diff --git a/entrypoint.sh b/entrypoint.sh index 51d1df3..2ed7a4b 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -3,8 +3,11 @@ set -e # When /app/data is bind-mounted from the host Docker may create the directory # as root, preventing the unprivileged motdtracker user from writing the SQLite -# database. Fix ownership here (runs as root before privilege drop). -chown -R motdtracker:motdtracker /app/data || \ - echo "Warning: could not chown /app/data – database writes may fail if the directory is root-owned" +# database. Fix ownership only when necessary (avoids startup latency on large +# bind mounts). +if [ "$(stat -c '%u:%g' /app/data 2>/dev/null)" != "10001:10001" ]; then + chown motdtracker:motdtracker /app/data || \ + echo "Warning: could not chown /app/data – database writes may fail if the directory is root-owned" +fi exec gosu motdtracker "$@" \ No newline at end of file