3 Commits
main ... ldc

Author SHA1 Message Date
ldc_
c7dfd1c149 feat: add Dockerfile.custom for Debian-based runner image 2026-02-02 15:32:18 +08:00
ldc_
9d0b60643c debug: add logging for containerOptions auto-addition 2026-02-02 15:31:44 +08:00
dcsunny
8fab783aa9 feat(cache): 实现缓存服务器host.docker.internal支持和配置自动检测
- 在缓存服务器启动时自动将外部URL转换为host.docker.internal格式
- 添加useHostDockerInternal字段用于标识是否使用host.docker.internal映射
- 自动向容器选项添加--add-host=host.docker.internal:host-gateway参数
- 实现配置文件自动检测功能,当未指定配置文件时默认查找config.yaml
- 在cmd.go中添加PersistentPreRunE钩子函数进行配置文件预处理
- 添加调试输出语句用于跟踪缓存服务器启动流程
2026-02-02 14:28:02 +08:00
4 changed files with 67 additions and 10 deletions

17
Dockerfile.custom Normal file
View File

@@ -0,0 +1,17 @@
FROM debian:bookworm-slim
# 安装必要的工具
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl git && rm -rf /var/lib/apt/lists/*
# 复制自定义编译的 act_runner
# 注意:构建前需要先确保当前目录下有编译好的 act_runner 二进制文件
COPY act_runner /usr/local/bin/act_runner
RUN chmod +x /usr/local/bin/act_runner
# 创建数据目录
RUN mkdir -p /data/cache
WORKDIR /data
ENTRYPOINT ["/usr/local/bin/act_runner"]
CMD ["daemon", "--config", "/config.yaml"]

View File

@@ -24,11 +24,12 @@ type cacheServerArgs struct {
func runCacheServer(ctx context.Context, configFile *string, cacheArgs *cacheServerArgs) func(cmd *cobra.Command, args []string) error { func runCacheServer(ctx context.Context, configFile *string, cacheArgs *cacheServerArgs) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error {
fmt.Println("cache1")
cfg, err := config.LoadDefault(*configFile) cfg, err := config.LoadDefault(*configFile)
if err != nil { if err != nil {
return fmt.Errorf("invalid configuration: %w", err) return fmt.Errorf("invalid configuration: %w", err)
} }
fmt.Println("cache2")
initLogging(cfg) initLogging(cfg)
var ( var (
@@ -47,7 +48,7 @@ func runCacheServer(ctx context.Context, configFile *string, cacheArgs *cacheSer
if cacheArgs.Port != 0 { if cacheArgs.Port != 0 {
port = cacheArgs.Port port = cacheArgs.Port
} }
fmt.Println("cache2")
cacheHandler, err := artifactcache.StartHandler( cacheHandler, err := artifactcache.StartHandler(
dir, dir,
host, host,

View File

@@ -15,6 +15,8 @@ import (
) )
func Execute(ctx context.Context) { func Execute(ctx context.Context) {
configFile := ""
// ./act_runner // ./act_runner
rootCmd := &cobra.Command{ rootCmd := &cobra.Command{
Use: "act_runner [event name to run]\nIf no event name passed, will default to \"on: push\"", Use: "act_runner [event name to run]\nIf no event name passed, will default to \"on: push\"",
@@ -22,8 +24,16 @@ func Execute(ctx context.Context) {
Args: cobra.MaximumNArgs(1), Args: cobra.MaximumNArgs(1),
Version: ver.Version(), Version: ver.Version(),
SilenceUsage: true, SilenceUsage: true,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// Auto-detect config.yaml if not specified
if configFile == "" {
if _, err := os.Stat("config.yaml"); err == nil {
configFile = "config.yaml"
}
}
return nil
},
} }
configFile := ""
rootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "", "Config file path") rootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "", "Config file path")
// ./act_runner register // ./act_runner register

View File

@@ -7,6 +7,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url"
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
@@ -38,6 +39,8 @@ type Runner struct {
labels labels.Labels labels labels.Labels
envs map[string]string envs map[string]string
useHostDockerInternal bool
runningTasks sync.Map runningTasks sync.Map
} }
@@ -52,9 +55,14 @@ func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client)
for k, v := range cfg.Runner.Envs { for k, v := range cfg.Runner.Envs {
envs[k] = v envs[k] = v
} }
// Setup cache
useHostDockerInternal := false
if cfg.Cache.Enabled == nil || *cfg.Cache.Enabled { if cfg.Cache.Enabled == nil || *cfg.Cache.Enabled {
if cfg.Cache.ExternalServer != "" { if cfg.Cache.ExternalServer != "" {
envs["ACTIONS_CACHE_URL"] = cfg.Cache.ExternalServer envs["ACTIONS_CACHE_URL"] = cfg.Cache.ExternalServer
if strings.Contains(cfg.Cache.ExternalServer, "host.docker.internal") {
useHostDockerInternal = true
}
} else { } else {
cacheHandler, err := artifactcache.StartHandler( cacheHandler, err := artifactcache.StartHandler(
cfg.Cache.Dir, cfg.Cache.Dir,
@@ -66,7 +74,16 @@ func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client)
log.Errorf("cannot init cache server, it will be disabled: %v", err) log.Errorf("cannot init cache server, it will be disabled: %v", err)
// go on // go on
} else { } else {
envs["ACTIONS_CACHE_URL"] = cacheHandler.ExternalURL() + "/" // Use host.docker.internal for container access
externalURL := cacheHandler.ExternalURL()
if parsedURL, err := url.Parse(externalURL); err == nil {
parsedURL.Host = "host.docker.internal:" + parsedURL.Port()
envs["ACTIONS_CACHE_URL"] = parsedURL.String() + "/"
} else {
envs["ACTIONS_CACHE_URL"] = externalURL + "/"
}
useHostDockerInternal = true
log.Infof("Cache server started at %s, using host.docker.internal for container access", externalURL)
} }
} }
} }
@@ -81,11 +98,12 @@ func NewRunner(cfg *config.Config, reg *config.Registration, cli client.Client)
envs["GITEA_ACTIONS_RUNNER_VERSION"] = ver.Version() envs["GITEA_ACTIONS_RUNNER_VERSION"] = ver.Version()
return &Runner{ return &Runner{
name: reg.Name, name: reg.Name,
cfg: cfg, cfg: cfg,
client: cli, client: cli,
labels: ls, labels: ls,
envs: envs, envs: envs,
useHostDockerInternal: useHostDockerInternal,
} }
} }
@@ -197,6 +215,17 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
maxLifetime = time.Until(deadline) maxLifetime = time.Until(deadline)
} }
// Auto-add host.docker.internal if cache is enabled
containerOptions := r.cfg.Container.Options
if r.useHostDockerInternal {
if containerOptions == "" {
containerOptions = "--add-host=host.docker.internal:host-gateway"
} else if !strings.Contains(containerOptions, "--add-host=host.docker.internal") {
containerOptions += " --add-host=host.docker.internal:host-gateway"
}
log.Infof("Auto-added host.docker.internal mapping for cache: %s", containerOptions)
}
runnerConfig := &runner.Config{ runnerConfig := &runner.Config{
// On Linux, Workdir will be like "/<parent_directory>/<owner>/<repo>" // On Linux, Workdir will be like "/<parent_directory>/<owner>/<repo>"
// On Windows, Workdir will be like "\<parent_directory>\<owner>\<repo>" // On Windows, Workdir will be like "\<parent_directory>\<owner>\<repo>"
@@ -219,7 +248,7 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id), ContainerNamePrefix: fmt.Sprintf("GITEA-ACTIONS-TASK-%d", task.Id),
ContainerMaxLifetime: maxLifetime, ContainerMaxLifetime: maxLifetime,
ContainerNetworkMode: container.NetworkMode(r.cfg.Container.Network), ContainerNetworkMode: container.NetworkMode(r.cfg.Container.Network),
ContainerOptions: r.cfg.Container.Options, ContainerOptions: containerOptions,
ContainerDaemonSocket: r.cfg.Container.DockerHost, ContainerDaemonSocket: r.cfg.Container.DockerHost,
Privileged: r.cfg.Container.Privileged, Privileged: r.cfg.Container.Privileged,
DefaultActionInstance: r.getDefaultActionsURL(ctx, task), DefaultActionInstance: r.getDefaultActionsURL(ctx, task),