From 2c5538bea11a5f2ee2ceec3861253254fce4b261 Mon Sep 17 00:00:00 2001 From: xfy911 Date: Tue, 16 Jun 2026 18:26:06 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=B8=A6=E5=AE=BD?= =?UTF-8?q?=E9=99=90=E9=80=9F=E5=90=88=E5=B9=B6=E5=90=8E=E9=81=97=E7=95=99?= =?UTF-8?q?=E7=9A=84=E7=BC=96=E8=AF=91=E4=B8=8E=E6=B5=8B=E8=AF=95=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20+=20=E6=96=B0=E5=A2=9E=20Docker=20=E5=A4=9A?= =?UTF-8?q?=E9=98=B6=E6=AE=B5=E6=9E=84=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Makefile: 4 个单元测试规则缺失 throttle.c(test_websocket/test_grpc/test_http3/test_acme) - test_acme_config.c: config_merge 调用缺少 has_throttle_conn_rate / has_throttle_global_rate - test_config.c: 5 处 config_merge 调用同步补齐 throttle 参数 - 新增 Dockerfile: debian bookworm-slim 多阶段构建,最终镜像约 50MB - 新增 .dockerignore: 排除构建产物和开发文件 - 编译验证:零警告(仅外部 coco 库 GNU-stack linker 提示) - 单元测试:480 个全部通过 ✓(1 个 Ignored 为预期行为) --- .dockerignore | 35 ++++++++++++++++ Dockerfile | 76 +++++++++++++++++++++++++++++++++++ Makefile | 16 ++++---- tests/unit/test_acme_config.c | 2 + tests/unit/test_config.c | 5 +++ 5 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..eb1dd8a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,35 @@ +# Git +.git +.gitignore +.gitmodules + +# 构建产物 +*.o +*.a +*.so +cocoon +tests/unit/test_* + +# IDE +.vscode +.idea +*.swp +*.swo + +# 日志 +*.log +logs/ + +# 临时文件 +*.tmp +*.bak + +# Docker 自身 +Dockerfile +.dockerignore + +# 文档 +README.md + +# 测试(运行时不需) +tests/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2ef8163 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,76 @@ +# Cocoon — 基于 coco 协程库的轻量级 Web 服务器 +# 多阶段构建,最终镜像约 50MB + +# ==================== 构建阶段 ==================== +FROM debian:bookworm-slim AS builder + +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc \ + make \ + cmake \ + git \ + libssl-dev \ + libbrotli-dev \ + libnghttp2-dev \ + libcurl4-openssl-dev \ + liburing-dev \ + zlib1g-dev \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /build + +# 复制源码(包含子模块) +COPY . . + +# 初始化并更新子模块(如果通过 COPY 未包含) +RUN git submodule update --init --recursive || true + +# 构建 coco 依赖 +RUN make deps + +# 构建 cocoon +RUN make COCO_INCLUDE=./coco/include COCO_LIB=./coco/build + +# 验证二进制 +RUN ./cocoon --help || true + +# ==================== 运行阶段 ==================== +FROM debian:bookworm-slim AS runner + +RUN apt-get update && apt-get install -y --no-install-recommends \ + libssl3 \ + libbrotli1 \ + libnghttp2-14 \ + libcurl4 \ + liburing2 \ + zlib1g \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# 创建运行用户(非 root) +RUN groupadd -r cocoon && useradd -r -g cocoon -s /bin/false cocoon + +# 创建工作目录 +WORKDIR /app + +# 复制二进制和默认配置 +COPY --from=builder /build/cocoon /usr/local/bin/cocoon +COPY --from=builder /build/cocoon.json /app/cocoon.json +COPY --from=builder /build/examples /app/examples +COPY --from=builder /build/plugins /app/plugins +COPY --from=builder /build/cocoon.service /app/cocoon.service + +# 设置权限 +RUN chown -R cocoon:cocoon /app + +# 健康检查 +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:8080/ || exit 1 + +USER cocoon + +EXPOSE 8080 + +ENTRYPOINT ["cocoon"] +CMD ["-c", "/app/cocoon.json"] diff --git a/Makefile b/Makefile index 77c9a28..7cd3d9d 100644 --- a/Makefile +++ b/Makefile @@ -102,8 +102,8 @@ $(UNIT_TEST_DIR)/test_http: $(UNIT_TEST_DIR)/test_http.c http.c log.c $(UNITY_SR $(UNIT_TEST_DIR)/test_static: $(UNIT_TEST_DIR)/test_static.c http.c log.c tls.c access_log.c platform.c cache.c acme.c throttle.c $(UNITY_SRC) $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_static.c http.c log.c tls.c access_log.c platform.c cache.c acme.c throttle.c $(UNITY_SRC) $(LDFLAGS) -$(UNIT_TEST_DIR)/test_websocket: $(UNIT_TEST_DIR)/test_websocket.c websocket.c log.c platform.c $(UNITY_SRC) - $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_websocket.c websocket.c log.c platform.c $(UNITY_SRC) $(LDFLAGS) +$(UNIT_TEST_DIR)/test_websocket: $(UNIT_TEST_DIR)/test_websocket.c websocket.c log.c platform.c throttle.c $(UNITY_SRC) + $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_websocket.c websocket.c log.c platform.c throttle.c $(UNITY_SRC) $(LDFLAGS) $(UNIT_TEST_DIR)/test_log: $(UNIT_TEST_DIR)/test_log.c log.c $(UNITY_SRC) $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_log.c log.c $(UNITY_SRC) -lm @@ -123,16 +123,16 @@ $(UNIT_TEST_DIR)/test_middleware_ext: $(UNIT_TEST_DIR)/test_middleware_ext.c mid $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_middleware_ext.c middleware_ext.c http.c log.c platform.c throttle.c $(UNITY_SRC) $(LDFLAGS) # gRPC 测试 -$(UNIT_TEST_DIR)/test_grpc: $(UNIT_TEST_DIR)/test_grpc.c grpc.c http.c log.c platform.c $(UNITY_SRC) - $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_grpc.c grpc.c http.c log.c platform.c $(UNITY_SRC) -lm +$(UNIT_TEST_DIR)/test_grpc: $(UNIT_TEST_DIR)/test_grpc.c grpc.c http.c log.c platform.c throttle.c $(UNITY_SRC) + $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_grpc.c grpc.c http.c log.c platform.c throttle.c $(UNITY_SRC) $(LDFLAGS) # 负载均衡测试 $(UNIT_TEST_DIR)/test_load_balance: $(UNIT_TEST_DIR)/test_load_balance.c load_balance.c proxy.c proxy_tls.c http.c log.c platform.c throttle.c $(UNITY_SRC) $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_load_balance.c load_balance.c proxy.c proxy_tls.c http.c log.c platform.c throttle.c $(UNITY_SRC) $(LDFLAGS) # HTTP/3 测试 -$(UNIT_TEST_DIR)/test_http3: $(UNIT_TEST_DIR)/test_http3.c http3.c http.c log.c platform.c $(UNITY_SRC) - $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_http3.c http3.c http.c log.c platform.c $(UNITY_SRC) $(LDFLAGS) +$(UNIT_TEST_DIR)/test_http3: $(UNIT_TEST_DIR)/test_http3.c http3.c http.c log.c platform.c throttle.c $(UNITY_SRC) + $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_http3.c http3.c http.c log.c platform.c throttle.c $(UNITY_SRC) $(LDFLAGS) # SSE 测试 $(UNIT_TEST_DIR)/test_sse: $(UNIT_TEST_DIR)/test_sse.c sse.c log.c $(UNITY_SRC) @@ -151,8 +151,8 @@ $(UNIT_TEST_DIR)/test_dashboard: $(UNIT_TEST_DIR)/test_dashboard.c dashboard.c s $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_dashboard.c dashboard.c sse.c log.c $(UNITY_SRC) $(LDFLAGS) # ACME 测试 -$(UNIT_TEST_DIR)/test_acme: $(UNIT_TEST_DIR)/test_acme.c acme.c log.c platform.c $(UNITY_SRC) - $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_acme.c acme.c log.c platform.c $(UNITY_SRC) $(LDFLAGS) +$(UNIT_TEST_DIR)/test_acme: $(UNIT_TEST_DIR)/test_acme.c acme.c log.c platform.c throttle.c $(UNITY_SRC) + $(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_acme.c acme.c log.c platform.c throttle.c $(UNITY_SRC) $(LDFLAGS) # ACME 配置集成测试 $(UNIT_TEST_DIR)/test_acme_config: $(UNIT_TEST_DIR)/test_acme_config.c config.c acme.c log.c access_log.c http.c platform.c throttle.c $(UNITY_SRC) diff --git a/tests/unit/test_acme_config.c b/tests/unit/test_acme_config.c index 977e1d4..d40ba7f 100644 --- a/tests/unit/test_acme_config.c +++ b/tests/unit/test_acme_config.c @@ -245,7 +245,9 @@ static void test_acme_config_merge(void) { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, + false, false, false, false, false, true); /* has_acme_enabled */ diff --git a/tests/unit/test_config.c b/tests/unit/test_config.c index 6fdc1d9..83ce270 100644 --- a/tests/unit/test_config.c +++ b/tests/unit/test_config.c @@ -306,6 +306,7 @@ void test_merge_override_all(void) { }; config_merge(&base, &cmdline, true, true, true, true, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false, false, false, false, false, false); TEST_ASSERT_EQUAL_STRING("/new", base.root_dir); TEST_ASSERT_EQUAL(9090, base.port); @@ -336,6 +337,7 @@ void test_merge_no_override(void) { }; config_merge(&base, &cmdline, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false); TEST_ASSERT_EQUAL_STRING("/old", base.root_dir); TEST_ASSERT_EQUAL(8080, base.port); @@ -360,6 +362,7 @@ void test_merge_partial_override(void) { }; config_merge(&base, &cmdline, true, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false); TEST_ASSERT_EQUAL_STRING("/new", base.root_dir); /* overridden */ TEST_ASSERT_EQUAL(8080, base.port); /* not overridden */ @@ -426,6 +429,7 @@ void test_merge_cmdline_null_root_dir(void) { cocoon_config_t base = {.root_dir = strdup("/old"), .port = 8080}; cocoon_config_t cmdline = {.root_dir = NULL, .port = 9090}; config_merge(&base, &cmdline, true, true, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false); TEST_ASSERT_EQUAL_STRING("/old", base.root_dir); /* NULL 不覆盖 */ TEST_ASSERT_EQUAL(9090, base.port); /* port 覆盖 */ @@ -435,6 +439,7 @@ void test_merge_cmdline_null_root_dir(void) { void test_merge_null_safety(void) { /* 不应 crash */ config_merge(NULL, NULL, true, true, true, true, true, true, true, true, true, true, true, true, + false, false, true, true, true, true, true, true, true, true, false, false); TEST_ASSERT_TRUE(1); }