chore(workflow,ci): update docker build process and add multi-arch support

Update the GitHub Actions workflow to include Go setup, multi-arch builds, and push multi-arch Docker images. Also, refactor the CSV service to improve logging and caching mechanism.
This commit is contained in:
wood chen 2024-11-16 05:34:37 +08:00
parent 981759be39
commit 61e84d87b8
3 changed files with 69 additions and 16 deletions

View File

@ -7,9 +7,9 @@ on:
tags:
- v*
paths-ignore:
- 'lankong_tools/**'
- 'lankong_tools/**'
- '*.md'
- '.github/**'
- '.github/**'
env:
IMAGE_NAME: random-api-go
@ -19,9 +19,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.23'
- name: Build for amd64
run: |
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -o bin/amd64/random-api .
- name: Build for arm64
run: |
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -a -installsuffix cgo -o bin/arm64/random-api .
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
@ -34,11 +47,11 @@ jobs:
username: woodchen
password: ${{ secrets.ACCESS_TOKEN }}
- name: Build and push
- name: Build and push multi-arch image
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile
file: Dockerfile.run
push: true
tags: woodchen/${{ env.IMAGE_NAME }}:latest
platforms: linux/amd64,linux/arm64
@ -53,8 +66,8 @@ jobs:
host: ${{ secrets.SERVER_HOST }}
username: root
key: ${{ secrets.SERVER_SSH_KEY }}
source: "public.zip"
target: "/tmp"
source: 'public.zip'
target: '/tmp'
- name: Execute deployment commands
uses: appleboy/ssh-action@master
@ -87,4 +100,4 @@ jobs:
docker rm random-api-go || true
# 启动容器
docker compose -f /opt/1panel/docker/compose/random-api-go/docker-compose.yml up -d
docker compose -f /opt/1panel/docker/compose/random-api-go/docker-compose.yml up -d

23
Dockerfile.run Normal file
View File

@ -0,0 +1,23 @@
FROM --platform=$TARGETPLATFORM alpine:latest
WORKDIR /root/
# 安装必要的包
RUN apk --no-cache add ca-certificates tzdata tini
# 创建日志目录并设置权限
RUN mkdir -p /var/log/random-api && chmod 755 /var/log/random-api
# 根据目标平台复制对应的二进制文件
ARG TARGETARCH
COPY bin/${TARGETARCH}/random-api .
COPY public ./public
COPY public /tmp/public
COPY start.sh /start.sh
RUN chmod +x /start.sh
EXPOSE 5003
# 使用 tini 作为初始化系统
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/start.sh"]

View File

@ -28,11 +28,19 @@ func InitializeCSVService() error {
return fmt.Errorf("failed to load CSV paths: %v", err)
}
// 预加载所有CSV内容
// 获取一个CSVPathsCache的副本避免长时间持有锁
Mu.RLock()
defer Mu.RUnlock()
pathsCopy := make(map[string]map[string]string)
for prefix, suffixMap := range CSVPathsCache {
pathsCopy[prefix] = make(map[string]string)
for suffix, path := range suffixMap {
pathsCopy[prefix][suffix] = path
}
}
Mu.RUnlock()
// 使用副本进行初始化
for prefix, suffixMap := range pathsCopy {
for suffix, csvPath := range suffixMap {
selector, err := GetCSVContent(csvPath)
if err != nil {
@ -113,51 +121,55 @@ func LoadCSVPaths() error {
}
func GetCSVContent(path string) (*models.URLSelector, error) {
log.Printf("开始获取CSV内容: %s", path)
Mu.RLock()
selector, exists := csvCache[path]
Mu.RUnlock()
if exists {
log.Printf("从缓存中获取到CSV内容: %s", path)
return selector, nil
}
var fileContent []byte
var err error
// 获取环境变量中的基础URL
baseURL := os.Getenv(config.EnvBaseURL)
if baseURL != "" {
// 如果设置了基础URL构建完整的URL
var fullURL string
if strings.HasPrefix(baseURL, "http://") || strings.HasPrefix(baseURL, "https://") {
// 如果baseURL已经包含协议,直接使用
fullURL = utils.JoinURLPath(baseURL, path)
} else {
// 如果没有协议,添加https://
fullURL = "https://" + utils.JoinURLPath(baseURL, path)
}
log.Printf("尝试从URL获取: %s", fullURL)
// 创建HTTP客户端
client := &http.Client{
Timeout: config.RequestTimeout,
}
resp, err := client.Get(fullURL)
if err != nil {
log.Printf("HTTP请求失败: %v", err)
return nil, fmt.Errorf("HTTP请求失败: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
log.Printf("HTTP请求返回非200状态码: %d", resp.StatusCode)
return nil, fmt.Errorf("HTTP请求返回非200状态码: %d", resp.StatusCode)
}
fileContent, err = io.ReadAll(resp.Body)
if err != nil {
log.Printf("读取响应内容失败: %v", err)
return nil, fmt.Errorf("读取响应内容失败: %w", err)
}
log.Printf("成功读取到CSV内容长度: %d bytes", len(fileContent))
} else {
// 如果没有设置基础URL从本地文件读取
fullPath := filepath.Join("public", path)
@ -170,6 +182,8 @@ func GetCSVContent(path string) (*models.URLSelector, error) {
}
lines := strings.Split(string(fileContent), "\n")
log.Printf("CSV文件包含 %d 行", len(lines))
uniqueURLs := make(map[string]bool)
var fileArray []string
for _, line := range lines {
@ -180,11 +194,14 @@ func GetCSVContent(path string) (*models.URLSelector, error) {
}
}
log.Printf("处理后得到 %d 个唯一URL", len(fileArray))
selector = models.NewURLSelector(fileArray)
Mu.Lock()
csvCache[path] = selector
Mu.Unlock()
log.Printf("CSV内容已缓存: %s", path)
return selector, nil
}