Skip to content

Commit a06a92f

Browse files
committed
chore: use c/s mode
1 parent 9c2a865 commit a06a92f

22 files changed

+729
-52
lines changed

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
.gitignore
66
.dockerignore
77
runner-manager
8+
runner-agent
89
*.exe
910
runners
11+
config.yaml
1012
.env
1113
*.test
1214
*.out

.env.example

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# 复制为 .env 后按需修改
2+
# cp .env.example .env
3+
#
4+
# docker-compose 会读取 .env,以下变量可选:
5+
#
6+
# Manager 镜像(与 docker-compose 中 runner-manager.image 对应)
7+
# MANAGER_IMAGE=ghcr.io/soulteary/runner-fleet:main
8+
# 使用本仓库 CI 推送的镜像时改为:ghcr.io/<owner>/<repo>:main 或 :<tag>
9+
#
10+
# 宿主机映射端口,默认 8080
11+
# MANAGER_PORT=8080
12+
#
13+
# Job 内 Docker 使用 DinD(仅非容器模式时有效):取消下一行注释
14+
# DOCKER_HOST=tcp://runner-dind:2375
15+
#
16+
# 容器模式且 Manager 在容器内时,config.yaml 中 runners.volume_host_path 需为宿主机 runners 的绝对路径,例如:
17+
# realpath runners
18+
# echo "$(cd . && pwd)/runners"

.github/workflows/build.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ jobs:
2626
- name: Vet
2727
run: go vet ./...
2828

29+
- name: Lint
30+
uses: golangci/golangci-lint-action@v9
31+
with:
32+
version: latest
33+
args: --max-same-issues=100000
34+
2935
- name: Run tests
3036
run: go test -v ./...
3137

@@ -49,10 +55,13 @@ jobs:
4955
VERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "dev-$(git rev-parse --short HEAD)")
5056
echo "version=$VERSION" >> $GITHUB_OUTPUT
5157
52-
- name: Build
58+
- name: Build Manager
5359
run: |
5460
go build -ldflags "-s -w -X main.Version=${{ steps.version.outputs.version }}" -o runner-manager .
5561
62+
- name: Build Runner Agent (container mode)
63+
run: go build -o runner-agent ./cmd/runner-agent
64+
5665
- name: Init example config
5766
run: cp config.yaml.example config.yaml
5867

.github/workflows/publish-image.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ jobs:
7474
- name: Prepare config for image
7575
run: cp config.yaml.example config.yaml
7676

77-
- name: Build and push
77+
- name: Build and push Manager image
7878
uses: docker/build-push-action@v6
7979
with:
8080
context: .
@@ -87,3 +87,22 @@ jobs:
8787
platforms: linux/amd64,linux/arm64
8888
cache-from: type=gha
8989
cache-to: type=gha,mode=max
90+
91+
- name: Prepare Runner tags (same image, tag suffix -runner)
92+
id: runner-tags
93+
run: |
94+
echo "tags<<EOF" >> "$GITHUB_OUTPUT"
95+
echo "${{ steps.meta.outputs.tags }}" | sed '/./s/\(:.*\)$/\1-runner/' >> "$GITHUB_OUTPUT"
96+
echo "EOF" >> "$GITHUB_OUTPUT"
97+
98+
- name: Build and push Runner image (container mode)
99+
uses: docker/build-push-action@v6
100+
with:
101+
context: .
102+
file: ./Dockerfile.runner
103+
push: true
104+
tags: ${{ steps.runner-tags.outputs.tags }}
105+
labels: ${{ steps.meta.outputs.labels }}
106+
platforms: linux/amd64,linux/arm64
107+
cache-from: type=gha
108+
cache-to: type=gha,mode=max

.github/workflows/release.yml

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,25 @@ jobs:
7676
username: ${{ github.actor }}
7777
password: ${{ secrets.GITHUB_TOKEN }}
7878

79-
- name: Extract metadata
79+
- name: Compute canonical image name (lowercase for GHCR)
80+
id: vars
81+
run: |
82+
CANONICAL="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
83+
echo "canonical=${CANONICAL,,}" >> "$GITHUB_OUTPUT"
84+
85+
- name: Extract metadata (Manager image)
8086
id: meta
8187
uses: docker/metadata-action@v5
8288
with:
83-
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
89+
images: ${{ steps.vars.outputs.canonical }}
8490
tags: |
8591
type=ref,event=tag
8692
type=semver,pattern={{version}}
8793
type=semver,pattern={{major}}.{{minor}}
8894
type=semver,pattern={{major}}
8995
type=raw,value=latest,enable=true
9096
91-
- name: Build and push Docker image
97+
- name: Build and push Manager Docker image
9298
uses: docker/build-push-action@v6
9399
with:
94100
context: .
@@ -102,6 +108,25 @@ jobs:
102108
cache-to: type=gha,mode=max
103109
platforms: linux/amd64,linux/arm64
104110

111+
- name: Prepare Runner tags (same image, tag suffix -runner)
112+
id: runner-tags
113+
run: |
114+
echo "tags<<EOF" >> "$GITHUB_OUTPUT"
115+
echo "${{ steps.meta.outputs.tags }}" | sed '/./s/\(:.*\)$/\1-runner/' >> "$GITHUB_OUTPUT"
116+
echo "EOF" >> "$GITHUB_OUTPUT"
117+
118+
- name: Build and push Runner Docker image (container mode)
119+
uses: docker/build-push-action@v6
120+
with:
121+
context: .
122+
file: ./Dockerfile.runner
123+
push: true
124+
tags: ${{ steps.runner-tags.outputs.tags }}
125+
labels: ${{ steps.meta.outputs.labels }}
126+
cache-from: type=gha
127+
cache-to: type=gha,mode=max
128+
platforms: linux/amd64,linux/arm64
129+
105130
- name: Create Release
106131
uses: softprops/action-gh-release@v2
107132
with:
@@ -116,8 +141,13 @@ jobs:
116141
117142
### Docker 镜像 (GHCR)
118143
144+
- Manager(管理服务):
145+
```bash
146+
docker pull ${{ steps.vars.outputs.canonical }}:${{ steps.version.outputs.tag }}
147+
```
148+
- Runner 容器镜像(容器模式,同镜像名,tag 带 -runner 后缀):
119149
```bash
120-
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.tag }}
150+
docker pull ${{ steps.vars.outputs.canonical }}:${{ steps.version.outputs.tag }}-runner
121151
```
122152
123153
### 二进制

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# 可执行文件
22
runner-manager
3+
runner-agent
34
*.exe
45

56
# Runner 数据目录(按需取消注释)

Dockerfile

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 多阶段构建:编译 + Ubuntu 运行时(避免 Alpine 导致 GitHub Runner 运行异常)
1+
# Runner Fleet Manager:多阶段构建,编译 + Ubuntu 运行时(避免 Alpine 导致 GitHub Runner 运行异常)
22
FROM golang:1.26-bookworm AS builder
33
WORKDIR /app
44
COPY go.mod go.sum ./
@@ -8,7 +8,10 @@ ARG VERSION=dev
88
RUN CGO_ENABLED=0 go build -ldflags "-X main.Version=${VERSION}" -o runner-manager .
99

1010
FROM ubuntu:24.04
11-
# GitHub Actions Runner 需 .NET Core 6.0 依赖(libicu 等),与 installdependencies.sh 一致
11+
LABEL org.opencontainers.image.title="Runner Fleet Manager" \
12+
org.opencontainers.image.description="GitHub Actions Runner 管理服务"
13+
14+
# GitHub Actions Runner 需 .NET Core 6.0 依赖(libicu 等)
1215
RUN apt-get update && apt-get install -y --no-install-recommends \
1316
ca-certificates \
1417
curl \
@@ -19,27 +22,31 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
1922
zlib1g \
2023
&& rm -rf /var/lib/apt/lists/*
2124

22-
# Docker CLI:DinD 模式下 Job 内 docker/setup-qemu-action、docker build 等需在容器内调用 docker 命令,通过 DOCKER_HOST 连接 DinD 守护进程
23-
# 基础镜像是 ubuntu:24.04,对应 codename noble
25+
# Docker CLI:Job 内 docker build 等通过 DOCKER_HOST 连接 DinD 或宿主机 Docker
2426
RUN install -m 0755 -d /etc/apt/keyrings \
2527
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc \
2628
&& chmod 644 /etc/apt/keyrings/docker.asc \
2729
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable" > /etc/apt/sources.list.d/docker.list \
2830
&& apt-get update && apt-get install -y --no-install-recommends docker-ce-cli \
2931
&& rm -rf /var/lib/apt/lists/*
3032

31-
# 使用非 root 用户运行,避免 GitHub Actions Runner 报 "Must not run with sudo"
32-
# UID/GID 1001 挂载 runners 卷时可按需 chown
33+
# 非 root 运行,避免 Runner 报 "Must not run with sudo";挂载卷时宿主机建议 chown 1001:1001
3334
RUN groupadd -g 1001 app && useradd -r -u 1001 -g app -d /app -s /bin/bash app
3435

3536
WORKDIR /app
3637
COPY --from=builder /app/runner-manager .
37-
COPY --from=builder /app/config.yaml ./config.yaml
38+
39+
# 默认配置:基于 example 生成,base_path 设为 /app/runners(与下方卷挂载一致);运行时可挂载自己的 config.yaml 覆盖
40+
COPY config.yaml.example ./config.yaml
41+
RUN sed -i 's|base_path: ./runners|base_path: /app/runners|' config.yaml
42+
3843
RUN mkdir -p /app/scripts /app/runners
3944
COPY scripts/install-runner.sh /app/scripts/install-runner.sh
4045
RUN chmod +x /app/scripts/install-runner.sh && chown -R app:app /app
4146

4247
USER app
4348
EXPOSE 8080
49+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
50+
CMD curl -fsS http://127.0.0.1:8080/health || exit 1
4451
ENTRYPOINT ["./runner-manager"]
45-
CMD ["-config", "config.yaml"]
52+
CMD ["-config", "/app/config.yaml"]

Dockerfile.runner

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Runner 容器镜像(容器模式用):仅包含 Agent + Runner 运行依赖,Runner 目录由 Manager 挂载到 /runner
2+
FROM golang:1.26.0-bookworm AS builder
3+
WORKDIR /app
4+
COPY go.mod go.sum ./
5+
RUN go mod download
6+
COPY . .
7+
RUN CGO_ENABLED=0 go build -o runner-agent ./cmd/runner-agent
8+
9+
FROM ubuntu:24.04
10+
LABEL org.opencontainers.image.title="Runner Fleet Runner" \
11+
org.opencontainers.image.description="GitHub Actions Runner 单实例容器,内含 Agent 供 Manager 控制"
12+
13+
RUN apt-get update && apt-get install -y --no-install-recommends \
14+
ca-certificates \
15+
curl \
16+
libicu74 \
17+
libkrb5-3 \
18+
liblttng-ust1 \
19+
libssl3 \
20+
zlib1g \
21+
&& rm -rf /var/lib/apt/lists/*
22+
23+
RUN install -m 0755 -d /etc/apt/keyrings \
24+
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc \
25+
&& chmod 644 /etc/apt/keyrings/docker.asc \
26+
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable" > /etc/apt/sources.list.d/docker.list \
27+
&& apt-get update && apt-get install -y --no-install-recommends docker-ce-cli \
28+
&& rm -rf /var/lib/apt/lists/*
29+
30+
RUN groupadd -g 1001 app && useradd -r -u 1001 -g app -d /runner -s /bin/bash app
31+
32+
WORKDIR /runner
33+
COPY --from=builder /app/runner-agent /runner/runner-agent
34+
RUN chown -R app:app /runner
35+
36+
ENV RUNNER_INSTALL_DIR=/runner
37+
ENV AGENT_PORT=8081
38+
39+
USER app
40+
EXPOSE 8081
41+
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
42+
CMD curl -fsS http://127.0.0.1:8081/health || exit 1
43+
ENTRYPOINT ["/runner/runner-agent"]

Makefile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
BINARY := runner-manager
33
VERSION ?= dev
44

5-
.PHONY: build test run docker-build docker-run docker-stop clean help
5+
# 本地构建 Runner 镜像的默认 tag;使用 CI 推送的镜像时为同仓库名、tag 带 -runner,如 ghcr.io/<owner>/<repo>:main-runner
6+
RUNNER_IMAGE ?= ghcr.io/soulteary/runner-fleet-runner:main
7+
8+
.PHONY: build test run docker-build docker-build-runner docker-run docker-stop clean help
69

710
help:
8-
@echo "targets: build test run docker-build docker-run docker-stop clean"
11+
@echo "targets: build test run docker-build docker-build-runner docker-run docker-stop clean"
912

1013
build:
1114
go build -ldflags "-X main.Version=$(VERSION)" -o $(BINARY) .
@@ -19,6 +22,9 @@ run: build
1922
docker-build:
2023
docker build --build-arg VERSION=$(VERSION) -t runner-manager:$(VERSION) .
2124

25+
docker-build-runner:
26+
docker build -f Dockerfile.runner -t $(RUNNER_IMAGE) .
27+
2228
docker-run: docker-stop
2329
docker run -d --name runner-manager -p 8080:8080 \
2430
-v $(PWD)/config.yaml:/app/config.yaml \

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
基于 Golang Echo 的 HTTP 管理界面,在一台机器上查看和管理多个 GitHub Actions 自托管 Runner。使用 YAML 配置,无需数据库。
44

55
许可证:MIT,见 [LICENSE](LICENSE)
6-
CI:push 到 `main`/`master` 时通过 [GitHub Actions](.github/workflows/build.yml) 自动执行 vet、测试与构建
6+
CI:push 到 `main`/`master` 时通过 [GitHub Actions](.github/workflows/build.yml) 执行检查与构建;[publish-image](.github/workflows/publish-image.yml) 会构建并推送 Manager 与 Runner 容器镜像到 GHCR
77

88
## 功能
99

@@ -12,6 +12,7 @@ CI:push 到 `main`/`master` 时通过 [GitHub Actions](.github/workflows/build
1212
- **快速添加**:名称 + 目标(组织/仓库)+ 可选 Token,一键添加并可自动注册
1313
- **删除**:从配置中移除(不删磁盘目录)
1414
- **启停**:对已注册 Runner 启动/停止
15+
- **容器模式**(可选):每个 Runner 运行在独立容器中,Manager 通过 C/S 控制并获取状态;Runner 与 Manager 同镜像名,CI 推送 tag 带 `-runner` 后缀(如 `:main-runner``:1.0.0-runner`
1516

1617
## 快速开始
1718

0 commit comments

Comments
 (0)