@@ -15,7 +15,6 @@ import (
1515 "golang.org/x/sync/errgroup"
1616 "io"
1717 "os"
18- "os/exec"
1918 "path/filepath"
2019 "strings"
2120 "sync"
@@ -70,84 +69,6 @@ func DefaultTCName(name string) string {
7069 return fmt .Sprintf ("%s-%s" , name , uuid .NewString ()[0 :5 ])
7170}
7271
73- // BuildAndPublishLocalDockerImage runs Docker commands to set up a local registry, build an image, and push it.
74- func BuildAndPublishLocalDockerImage (once * sync.Once , dockerfile string , buildContext string , imageName string ) error {
75- var retErr error
76- once .Do (func () {
77- L .Info ().
78- Str ("Dockerfile" , dockerfile ).
79- Str ("Ctx" , buildContext ).
80- Str ("ImageName" , imageName ).
81- Msg ("Building local docker file" )
82- registryRunning := isContainerRunning ("local-registry" )
83- if registryRunning {
84- fmt .Println ("Local registry container is already running." )
85- } else {
86- L .Info ().Msg ("Removing local registry" )
87- _ = runCommand ("docker" , "stop" , "local-registry" )
88- _ = runCommand ("docker" , "rm" , "local-registry" )
89- L .Info ().Msg ("Starting local registry container..." )
90- err := runCommand ("docker" , "run" , "-d" , "-p" , "5050:5000" , "--name" , "local-registry" , "registry:2" )
91- if err != nil {
92- retErr = fmt .Errorf ("failed to start local registry: %w" , err )
93- }
94- L .Info ().Msg ("Local registry started" )
95- }
96-
97- img := fmt .Sprintf ("localhost:5050/%s:latest" , imageName )
98- err := runCommand ("docker" , "build" , "-t" , fmt .Sprintf ("localhost:5050/%s:latest" , imageName ), "-f" , dockerfile , buildContext )
99- if err != nil {
100- retErr = fmt .Errorf ("failed to build Docker image: %w" , err )
101- }
102- L .Info ().Msg ("Docker image built successfully" )
103-
104- L .Info ().Str ("Image" , img ).Msg ("Pushing Docker image to local registry" )
105- fmt .Println ("Pushing Docker image to local registry..." )
106- err = runCommand ("docker" , "push" , img )
107- if err != nil {
108- retErr = fmt .Errorf ("failed to push Docker image: %w" , err )
109- }
110- L .Info ().Msg ("Docker image pushed successfully" )
111- })
112- return retErr
113- }
114-
115- // isContainerRunning checks if a Docker container with the given name is running.
116- func isContainerRunning (containerName string ) bool {
117- cmd := exec .Command ("docker" , "ps" , "--filter" , fmt .Sprintf ("name=%s" , containerName ), "--format" , "{{.Names}}" )
118- output , err := cmd .Output ()
119- if err != nil {
120- return false
121- }
122- return strings .Contains (string (output ), containerName )
123- }
124-
125- // runCommand executes a command and prints the output.
126- func runCommand (name string , args ... string ) error {
127- cmd := exec .Command (name , args ... )
128- cmd .Stdout = os .Stdout
129- cmd .Stderr = os .Stderr
130- return cmd .Run ()
131- }
132-
133- // TODO: use tc.NewDockerProvider().BuildImage() to skip managing the registry container
134- // RebuildDockerImage rebuilds docker image if necessary
135- func RebuildDockerImage (once * sync.Once , dockerfile string , buildContext string , imageName string ) (string , error ) {
136- if dockerfile == "" {
137- return "" , errors .New ("docker_file path must be provided" )
138- }
139- if buildContext == "" {
140- return "" , errors .New ("docker_ctx path must be provided" )
141- }
142- if imageName == "" {
143- imageName = "ctftmp"
144- }
145- if err := BuildAndPublishLocalDockerImage (once , dockerfile , buildContext , imageName ); err != nil {
146- return "" , err
147- }
148- return fmt .Sprintf ("localhost:5050/%s:latest" , imageName ), nil
149- }
150-
15172// DockerClient wraps a Docker API client and provides convenience methods
15273type DockerClient struct {
15374 cli * client.Client
@@ -320,3 +241,30 @@ func WriteAllContainersLogs() error {
320241 }
321242 return eg .Wait ()
322243}
244+
245+ func BuildImageOnce (ctx context.Context , once * sync.Once , dctx , dfile , nameAndTag string ) error {
246+ var (
247+ p * tc.DockerProvider
248+ dockerCtx string
249+ err error
250+ )
251+ once .Do (func () {
252+ nt := strings .Split (nameAndTag , ":" )
253+ if len (nt ) != 2 {
254+ err = errors .New ("BuildImageOnce, tag must be in 'repo:tag' format" )
255+ return
256+ }
257+ p , err = tc .NewDockerProvider ()
258+ dockerCtx , err = filepath .Abs (dctx )
259+ _ , err = p .BuildImage (ctx , & tc.ContainerRequest {
260+ FromDockerfile : tc.FromDockerfile {
261+ Repo : nt [0 ],
262+ Tag : nt [1 ],
263+ Context : dockerCtx ,
264+ Dockerfile : dfile ,
265+ PrintBuildLog : true ,
266+ },
267+ })
268+ })
269+ return err
270+ }
0 commit comments