66 "encoding/json"
77 "errors"
88 "fmt"
9+ "io/ioutil"
910 "os"
11+ "path/filepath"
1012 "strconv"
1113 "strings"
1214
@@ -34,14 +36,15 @@ type buildOptions struct {
3436 progress string
3537 pull bool
3638 tag string
39+ folder string
3740}
3841
3942func Cmd (dockerCli command.Cli ) * cobra.Command {
4043 var opts buildOptions
4144 cmd := & cobra.Command {
42- Use : "build [APP_NAME ] [OPTIONS ]" ,
45+ Use : "build [OPTIONS ] [CONTEXT_PATH ]" ,
4346 Short : "Build service images for the application" ,
44- Example : `$ docker app build myapp.dockerapp --tag my/app:1.0.0` ,
47+ Example : `$ docker app build --tag my/app:1.0.0 . ` ,
4548 Args : cli .ExactArgs (1 ),
4649 RunE : func (cmd * cobra.Command , args []string ) error {
4750 ref , err := runBuild (dockerCli , args [0 ], opts )
@@ -56,12 +59,13 @@ func Cmd(dockerCli command.Cli) *cobra.Command {
5659 flags .BoolVar (& opts .noCache , "no-cache" , false , "Do not use cache when building the image" )
5760 flags .StringVar (& opts .progress , "progress" , "auto" , "Set type of progress output (auto, plain, tty). Use plain to show container output" )
5861 flags .StringVarP (& opts .tag , "tag" , "t" , "" , "Application image and optionally a tag in the 'image:tag' format" )
62+ flags .StringVarP (& opts .folder , "folder" , "f" , "" , "Docker app folder containing application definition" )
5963 flags .BoolVar (& opts .pull , "pull" , false , "Always attempt to pull a newer version of the image" )
6064
6165 return cmd
6266}
6367
64- func runBuild (dockerCli command.Cli , application string , opt buildOptions ) (reference.Reference , error ) {
68+ func runBuild (dockerCli command.Cli , contextPath string , opt buildOptions ) (reference.Reference , error ) {
6569 err := checkMinimalEngineVersion (dockerCli )
6670 if err != nil {
6771 return nil , err
@@ -73,18 +77,35 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
7377 return nil , err
7478 }
7579
80+ application , err := getAppFolder (opt , contextPath )
81+ if err != nil {
82+ return nil , err
83+ }
84+
7685 app , err := packager .Extract (application )
7786 if err != nil {
7887 return nil , err
7988 }
8089 defer app .Cleanup ()
8190
82- buildopts , err := parseCompose (app , opt )
91+ serviceTag := ref
92+ if serviceTag == nil {
93+ named , err := reference .WithName (app .Metadata ().Name )
94+ if err != nil {
95+ return nil , err
96+ }
97+ serviceTag , err = reference .WithTag (named , app .Metadata ().Version )
98+ if err != nil {
99+ return nil , err
100+ }
101+ }
102+
103+ buildopts , err := parseCompose (app , contextPath , opt , serviceTag )
83104 if err != nil {
84105 return nil , err
85106 }
86107
87- buildopts ["com.docker.app.invocation-image" ], err = createInvocationImageBuildOptions (dockerCli , app )
108+ buildopts ["com.docker.app.invocation-image" ], err = createInvocationImageBuildOptions (dockerCli , app , serviceTag )
88109 if err != nil {
89110 return nil , err
90111 }
@@ -126,6 +147,25 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
126147 return packager .PersistInBundleStore (ref , bundle )
127148}
128149
150+ func getAppFolder (opt buildOptions , contextPath string ) (string , error ) {
151+ application := opt .folder
152+ if application == "" {
153+ files , err := ioutil .ReadDir (contextPath )
154+ if err != nil {
155+ return "" , err
156+ }
157+ for _ , f := range files {
158+ if strings .HasSuffix (f .Name (), ".dockerapp" ) {
159+ if application != "" {
160+ return "" , fmt .Errorf ("%s contains multiple *.dockerapp folders, use -f option to select the one to build" , contextPath )
161+ }
162+ application = filepath .Join (contextPath , f .Name ())
163+ }
164+ }
165+ }
166+ return application , nil
167+ }
168+
129169func checkMinimalEngineVersion (dockerCli command.Cli ) error {
130170 info , err := dockerCli .Client ().Info (appcontext .Context ())
131171 if err != nil {
@@ -165,7 +205,7 @@ func updateBundle(dockerCli command.Cli, bundle *bundle.Bundle, resp map[string]
165205 return nil
166206}
167207
168- func createInvocationImageBuildOptions (dockerCli command.Cli , app * types.App ) (build.Options , error ) {
208+ func createInvocationImageBuildOptions (dockerCli command.Cli , app * types.App , serviceTag reference. Reference ) (build.Options , error ) {
169209 buildContext := bytes .NewBuffer (nil )
170210 if err := packager .PackInvocationImageContext (dockerCli , app , buildContext ); err != nil {
171211 return build.Options {}, err
@@ -176,6 +216,7 @@ func createInvocationImageBuildOptions(dockerCli command.Cli, app *types.App) (b
176216 ContextPath : "-" ,
177217 },
178218 Session : []session.Attachable {authprovider .NewDockerAuthProvider (os .Stderr )},
219+ Tags : []string {fmt .Sprintf ("%s-installer" , serviceTag .String ())},
179220 }, nil
180221}
181222
0 commit comments