@@ -32,12 +32,13 @@ import (
32
32
)
33
33
34
34
type buildOptions struct {
35
- noCache bool
36
- progress string
37
- pull bool
38
- tag string
39
- folder string
40
- args []string
35
+ noCache bool
36
+ progress string
37
+ pull bool
38
+ tag string
39
+ folder string
40
+ imageIDFile string
41
+ args []string
41
42
}
42
43
43
44
func Cmd (dockerCli command.Cli ) * cobra.Command {
@@ -48,11 +49,7 @@ func Cmd(dockerCli command.Cli) *cobra.Command {
48
49
Example : `$ docker app build --tag my/app:1.0.0 .` ,
49
50
Args : cli .ExactArgs (1 ),
50
51
RunE : func (cmd * cobra.Command , args []string ) error {
51
- ref , err := runBuild (dockerCli , args [0 ], opts )
52
- if err == nil {
53
- fmt .Printf ("Successfully build %s\n " , ref .String ())
54
- }
55
- return err
52
+ return runBuild (dockerCli , args [0 ], opts )
56
53
},
57
54
}
58
55
@@ -63,49 +60,78 @@ func Cmd(dockerCli command.Cli) *cobra.Command {
63
60
flags .StringVarP (& opts .folder , "folder" , "f" , "" , "Docker app folder containing application definition" )
64
61
flags .BoolVar (& opts .pull , "pull" , false , "Always attempt to pull a newer version of the image" )
65
62
flags .StringArrayVar (& opts .args , "build-arg" , []string {}, "Set build-time variables" )
63
+ flags .StringVar (& opts .imageIDFile , "iidfile" , "" , "Write the app image ID to the file" )
66
64
67
65
return cmd
68
66
}
69
67
70
- func runBuild (dockerCli command.Cli , contextPath string , opt buildOptions ) (reference. Reference , error ) {
68
+ func runBuild (dockerCli command.Cli , contextPath string , opt buildOptions ) error {
71
69
err := checkMinimalEngineVersion (dockerCli )
72
70
if err != nil {
73
- return nil , err
71
+ return err
74
72
}
75
73
76
- if err = checkBuildArgsUniqueness (opt .args ); err != nil {
77
- return nil , err
74
+ if opt .imageIDFile != "" {
75
+ // Avoid leaving a stale file if we eventually fail
76
+ if err := os .Remove (opt .imageIDFile ); err != nil && ! os .IsNotExist (err ) {
77
+ return err
78
+ }
78
79
}
79
80
80
- var ref reference.Reference
81
- ref , err = packager .GetNamedTagged (opt .tag )
82
- if err != nil {
83
- return nil , err
81
+ if err = checkBuildArgsUniqueness (opt .args ); err != nil {
82
+ return err
84
83
}
85
84
86
85
application , err := getAppFolder (opt , contextPath )
87
86
if err != nil {
88
- return nil , err
87
+ return err
89
88
}
90
89
91
90
app , err := packager .Extract (application )
92
91
if err != nil {
93
- return nil , err
92
+ return err
94
93
}
95
94
defer app .Cleanup ()
96
95
96
+ bundle , err := buildImageUsingBuildx (app , contextPath , opt , dockerCli )
97
+ if err != nil {
98
+ return err
99
+ }
100
+
101
+ var ref reference.Reference
102
+ ref , err = packager .GetNamedTagged (opt .tag )
103
+ if err != nil {
104
+ return err
105
+ }
106
+
107
+ id , err := packager .PersistInBundleStore (ref , bundle )
108
+ if err != nil {
109
+ return err
110
+ }
111
+
112
+ if opt .imageIDFile != "" {
113
+ if err = ioutil .WriteFile (opt .imageIDFile , []byte (id .String ()), 0644 ); err != nil {
114
+ fmt .Fprintf (dockerCli .Err (), "Failed to write application image id in %s: %s" , opt .imageIDFile , err )
115
+ }
116
+ }
117
+
118
+ fmt .Printf ("Successfully built %s\n " , id )
119
+ if ref != nil {
120
+ fmt .Printf ("Successfully tagged %s\n " , ref .String ())
121
+ }
122
+ return err
123
+ }
124
+
125
+ func buildImageUsingBuildx (app * types.App , contextPath string , opt buildOptions , dockerCli command.Cli ) (* bundle.Bundle , error ) {
97
126
buildopts , err := parseCompose (app , contextPath , opt )
98
127
if err != nil {
99
128
return nil , err
100
129
}
101
-
102
130
buildopts ["com.docker.app.invocation-image" ], err = createInvocationImageBuildOptions (dockerCli , app )
103
131
if err != nil {
104
132
return nil , err
105
133
}
106
-
107
134
debugBuildOpts (buildopts )
108
-
109
135
ctx , cancel := context .WithCancel (appcontext .Context ())
110
136
defer cancel ()
111
137
const drivername = "buildx_buildkit_default"
@@ -119,9 +145,7 @@ func runBuild(dockerCli command.Cli, contextPath string, opt buildOptions) (refe
119
145
Driver : d ,
120
146
},
121
147
}
122
-
123
148
pw := progress .NewPrinter (ctx , os .Stderr , opt .progress )
124
-
125
149
// We rely on buildx "docker" builder integrated in docker engine, so don't need a DockerAPI here
126
150
resp , err := build .Build (ctx , driverInfo , buildopts , nil , dockerCli .ConfigFile (), pw )
127
151
if err != nil {
@@ -137,8 +161,7 @@ func runBuild(dockerCli command.Cli, contextPath string, opt buildOptions) (refe
137
161
if err != nil {
138
162
return nil , err
139
163
}
140
-
141
- return packager .PersistInBundleStore (ref , bundle )
164
+ return bundle , nil
142
165
}
143
166
144
167
func getAppFolder (opt buildOptions , contextPath string ) (string , error ) {
0 commit comments