dockerfiles/dockerporter.go
2024-10-23 07:17:31 +00:00

151 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"gopkg.in/yaml.v2"
)
type Tag struct {
Tag string `yaml:"tag"`
Platforms []string `yaml:"platforms"`
}
type Image struct {
Name string `yaml:"name"`
From string `yaml:"from,omitempty"` // `from` 为可选字段
Tags []Tag `yaml:"tags"`
}
type Config struct {
Target string `yaml:"target"`
Images []Image `yaml:"images"`
}
func main() {
// 记录开始时间
startTime := time.Now()
// 创建日志文件名
logFileName := fmt.Sprintf("build_%s.log", startTime.Format("20060102"))
logFile, err := os.OpenFile(logFileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
logErrorInfo(logFile, time.Now(),
fmt.Sprintf("Error opening log file: %v", err))
return
}
defer logFile.Close()
// 记录程序启动时间
logStartTime(logFile, startTime)
// 读取 YAML 文件
data, err := ioutil.ReadFile("images.yaml")
if err != nil {
logErrorInfo(logFile, time.Now(),
fmt.Sprintf("Error reading YAML file: %v", err))
return
}
// 解析 YAML 文件
var config Config
if err := yaml.Unmarshal(data, &config); err != nil {
logErrorInfo(logFile, time.Now(),
fmt.Sprintf("Error parsing YAML: %v", err))
return
}
totalImages := 0
totalTags := 0
// 遍历每个镜像信息
for _, image := range config.Images {
// 如果 `from` 字段为空,则将其设置为 `name`Docker Hub 官方镜像)
if image.From == "" {
image.From = image.Name
}
imageBuilt := false // 记录是否构建过该镜像
for _, tag := range image.Tags {
totalTags++
// 根据镜像生成 Dockerfile
dockerfilePath := filepath.Join(".", fmt.Sprintf("Dockerfile.%s:%s", image.Name, tag.Tag))
if err := generateDockerfile(image.From, tag.Tag, dockerfilePath); err != nil {
logErrorInfo(logFile, time.Now(),
fmt.Sprintf("Error generating Dockerfile for %s:%s: %v", image.Name, tag.Tag, err))
continue
}
// 合并所有平台为一个字符串
platforms := strings.Join(tag.Platforms, ",")
// 构建 Docker 镜像命令,添加 target
buildCmd := exec.Command("docker", "buildx", "build", "--push", "--platform", platforms, "-t", fmt.Sprintf("%s/%s:%s", config.Target, image.Name, tag.Tag), "-f", dockerfilePath, ".")
buildCmd.Stdout = os.Stdout
buildCmd.Stderr = os.Stderr
// 记录开始构建时间
buildStartTime := time.Now()
if err := buildCmd.Run(); err != nil {
logErrorInfo(logFile, time.Now(),
fmt.Sprintf("Error building image %s:%s for platforms %s: %v", image.Name, tag.Tag, platforms, err))
continue
}
// 记录构建结束时间
buildEndTime := time.Now()
// 记录构建日志
logBuildInfo(logFile, buildStartTime, image.Name, tag.Tag, platforms, config.Target, buildEndTime.Sub(buildStartTime))
imageBuilt = true // 标记该镜像已成功构建
// 删除生成的 Dockerfile
if err := os.Remove(dockerfilePath); err != nil {
logErrorInfo(logFile, time.Now(),
fmt.Sprintf("Error deleting Dockerfile %s: %v", dockerfilePath, err))
}
}
if imageBuilt {
totalImages++ // 仅在成功构建过一次时增加镜像计数
}
}
// 计算总时间
elapsedTime := time.Since(startTime)
logCompletion(logFile, elapsedTime, totalImages, totalTags)
}
// 记录程序启动时间
func logStartTime(logFile *os.File, startTime time.Time) {
logFile.WriteString(fmt.Sprintf("Process started at: %s\n", startTime.Format(time.RFC3339)))
}
// 记录构建信息
func logBuildInfo(logFile *os.File, startTime time.Time, imageName, tag string, platforms string, target string, duration time.Duration) {
logFile.WriteString(fmt.Sprintf("%s | Image: %s | Tag: %s | Platforms: %s | Pushed to: %s/%s:%s | Duration: %v\n",
startTime.Format(time.RFC3339), imageName, tag, platforms, target, imageName, tag, duration))
}
// 记录报错
func logErrorInfo(logFile *os.File, startTime time.Time, errorMessage string) {
logFile.WriteString(fmt.Sprintf("%s | %s\n",
startTime.Format(time.RFC3339), errorMessage))
}
// 记录完成时间和统计信息
func logCompletion(logFile *os.File, elapsedTime time.Duration, totalImages, totalTags int) {
logFile.WriteString(fmt.Sprintf("Build completed at: %s\n", time.Now().Format(time.RFC3339)))
logFile.WriteString(fmt.Sprintf("Total images built: %d\n", totalImages))
logFile.WriteString(fmt.Sprintf("Total tags processed: %d\n", totalTags))
logFile.WriteString(fmt.Sprintf("Total execution time: %v\n", elapsedTime))
}
// 生成 Dockerfile
func generateDockerfile(fromImage, tag, filePath string) error {
dockerfileContent := fmt.Sprintf("FROM %s:%s\n", fromImage, tag)
return ioutil.WriteFile(filePath, []byte(dockerfileContent), 0644)
}