@@ -2,10 +2,12 @@ package docker
22
33import (
44 "fmt"
5+
56 "github.com/Sirupsen/logrus"
67 "github.com/docker/docker/pkg/nat"
78 "github.com/docker/libcompose/project"
89 "github.com/docker/libcompose/utils"
10+ "github.com/fsouza/go-dockerclient"
911)
1012
1113// Service is a project.Service implementations.
@@ -39,14 +41,15 @@ func (s *Service) DependentServices() []project.ServiceRelationship {
3941 return project .DefaultDependentServices (s .context .Project , s )
4042}
4143
42- // Create implements Service.Create.
44+ // Create implements Service.Create. It ensures the image exists or build it
45+ // if it can and then create a container.
4346func (s * Service ) Create () error {
4447 containers , err := s .collectContainers ()
4548 if err != nil {
4649 return err
4750 }
4851
49- imageName , err := s .build ()
52+ imageName , err := s .ensureImageExists ()
5053 if err != nil {
5154 return err
5255 }
@@ -87,20 +90,57 @@ func (s *Service) createOne(imageName string) (*Container, error) {
8790 return containers [0 ], err
8891}
8992
93+ func (s * Service ) ensureImageExists () (string , error ) {
94+ err := s .imageExists ()
95+
96+ if err == nil {
97+ return s .imageName (), nil
98+ }
99+
100+ if err != nil && err != docker .ErrNoSuchImage {
101+ return "" , err
102+ }
103+
104+ if s .Config ().Build != "" {
105+ if s .context .NoBuild {
106+ return "" , fmt .Errorf ("Service %q needs to be built, but no-build was specified" , s .name )
107+ }
108+ return s .imageName (), s .build ()
109+ }
110+
111+ return s .imageName (), s .Pull ()
112+ }
113+
114+ func (s * Service ) imageExists () error {
115+ client := s .context .ClientFactory .Create (s )
116+
117+ _ , err := client .InspectImage (s .imageName ())
118+ return err
119+ }
120+
121+ func (s * Service ) imageName () string {
122+ if s .Config ().Image != "" {
123+ return s .Config ().Image
124+ }
125+ return fmt .Sprintf ("%s_%s" , s .context .ProjectName , s .Name ())
126+ }
127+
90128// Build implements Service.Build. If an imageName is specified or if the context has
91129// no build to work with it will do nothing. Otherwise it will try to build
92130// the image and returns an error if any.
93131func (s * Service ) Build () error {
94- _ , err := s .build ()
95- return err
132+ if s .Config ().Image != "" {
133+ return nil
134+ }
135+ return s .build ()
96136}
97137
98- func (s * Service ) build () ( string , error ) {
138+ func (s * Service ) build () error {
99139 if s .context .Builder == nil {
100- return s . Config (). Image , nil
140+ return fmt . Errorf ( "Cannot build an image without a builder configured" )
101141 }
102142
103- return s .context .Builder .Build (s .context .Project , s )
143+ return s .context .Builder .Build (s .imageName (), s . context .Project , s )
104144}
105145
106146func (s * Service ) constructContainers (imageName string , count int ) ([]* Container , error ) {
@@ -145,11 +185,19 @@ func (s *Service) constructContainers(imageName string, count int) ([]*Container
145185// Up implements Service.Up. It builds the image if needed, creates a container
146186// and start it.
147187func (s * Service ) Up () error {
148- imageName , err := s .build ()
188+ containers , err := s .collectContainers ()
149189 if err != nil {
150190 return err
151191 }
152192
193+ var imageName = s .imageName ()
194+ if len (containers ) == 0 || ! s .context .NoRecreate {
195+ imageName , err = s .ensureImageExists ()
196+ if err != nil {
197+ return err
198+ }
199+ }
200+
153201 return s .up (imageName , true )
154202}
155203
@@ -310,7 +358,7 @@ func (s *Service) Scale(scale int) error {
310358 }
311359
312360 if foundCount != scale {
313- imageName , err := s .build ()
361+ imageName , err := s .ensureImageExists ()
314362 if err != nil {
315363 return err
316364 }
@@ -323,7 +371,8 @@ func (s *Service) Scale(scale int) error {
323371 return s .up ("" , false )
324372}
325373
326- // Pull implements Service.Pull. It pulls or build the image of the service.
374+ // Pull implements Service.Pull. It pulls the image of the service and skip the service that
375+ // would need to be built.
327376func (s * Service ) Pull () error {
328377 if s .Config ().Image == "" {
329378 return nil
0 commit comments