50
50
'workdir' : 'working_dir' ,
51
51
}
52
52
53
+ DOCKER_START_KEYS = [
54
+ 'cap_add' ,
55
+ 'cap_drop' ,
56
+ 'dns' ,
57
+ 'dns_search' ,
58
+ 'env_file' ,
59
+ 'net' ,
60
+ 'privileged' ,
61
+ 'restart' ,
62
+ ]
63
+
53
64
VALID_NAME_CHARS = '[a-zA-Z0-9]'
54
65
55
66
@@ -145,7 +156,8 @@ def restart(self, **options):
145
156
146
157
def scale (self , desired_num ):
147
158
"""
148
- Adjusts the number of containers to the specified number and ensures they are running.
159
+ Adjusts the number of containers to the specified number and ensures
160
+ they are running.
149
161
150
162
- creates containers until there are at least `desired_num`
151
163
- stops containers until there are at most `desired_num` running
@@ -192,12 +204,24 @@ def remove_stopped(self, **options):
192
204
log .info ("Removing %s..." % c .name )
193
205
c .remove (** options )
194
206
195
- def create_container (self , one_off = False , insecure_registry = False , ** override_options ):
207
+ def create_container (self ,
208
+ one_off = False ,
209
+ insecure_registry = False ,
210
+ do_build = True ,
211
+ ** override_options ):
196
212
"""
197
213
Create a container for this service. If the image doesn't exist, attempt to pull
198
214
it.
199
215
"""
200
- container_options = self ._get_container_create_options (override_options , one_off = one_off )
216
+ container_options = self ._get_container_create_options (
217
+ override_options ,
218
+ one_off = one_off )
219
+
220
+ if (do_build and
221
+ self .can_be_built () and
222
+ not self .client .images (name = self .full_name )):
223
+ self .build ()
224
+
201
225
try :
202
226
return Container .create (self .client , ** container_options )
203
227
except APIError as e :
@@ -212,15 +236,18 @@ def create_container(self, one_off=False, insecure_registry=False, **override_op
212
236
return Container .create (self .client , ** container_options )
213
237
raise
214
238
215
- def recreate_containers (self , insecure_registry = False , ** override_options ):
239
+ def recreate_containers (self , insecure_registry = False , do_build = True , ** override_options ):
216
240
"""
217
241
If a container for this service doesn't exist, create and start one. If there are
218
242
any, stop them, create+start new ones, and remove the old containers.
219
243
"""
220
244
containers = self .containers (stopped = True )
221
245
if not containers :
222
246
log .info ("Creating %s..." % self ._next_container_name (containers ))
223
- container = self .create_container (insecure_registry = insecure_registry , ** override_options )
247
+ container = self .create_container (
248
+ insecure_registry = insecure_registry ,
249
+ do_build = do_build ,
250
+ ** override_options )
224
251
self .start_container (container )
225
252
return [(None , container )]
226
253
else :
@@ -259,7 +286,7 @@ def recreate_container(self, container, **override_options):
259
286
container .remove ()
260
287
261
288
options = dict (override_options )
262
- new_container = self .create_container (** options )
289
+ new_container = self .create_container (do_build = False , ** options )
263
290
self .start_container (new_container , intermediate_container = intermediate_container )
264
291
265
292
intermediate_container .remove ()
@@ -273,8 +300,7 @@ def start_container_if_stopped(self, container, **options):
273
300
log .info ("Starting %s..." % container .name )
274
301
return self .start_container (container , ** options )
275
302
276
- def start_container (self , container = None , intermediate_container = None , ** override_options ):
277
- container = container or self .create_container (** override_options )
303
+ def start_container (self , container , intermediate_container = None , ** override_options ):
278
304
options = dict (self .options , ** override_options )
279
305
port_bindings = build_port_bindings (options .get ('ports' ) or [])
280
306
@@ -307,14 +333,19 @@ def start_container(self, container=None, intermediate_container=None, **overrid
307
333
)
308
334
return container
309
335
310
- def start_or_create_containers (self , insecure_registry = False , detach = False ):
336
+ def start_or_create_containers (
337
+ self ,
338
+ insecure_registry = False ,
339
+ detach = False ,
340
+ do_build = True ):
311
341
containers = self .containers (stopped = True )
312
342
313
343
if not containers :
314
344
log .info ("Creating %s..." % self ._next_container_name (containers ))
315
345
new_container = self .create_container (
316
346
insecure_registry = insecure_registry ,
317
- detach = detach
347
+ detach = detach ,
348
+ do_build = do_build ,
318
349
)
319
350
return [self .start_container (new_container )]
320
351
else :
@@ -407,16 +438,13 @@ def _get_container_create_options(self, override_options, one_off=False):
407
438
container_options ['environment' ] = merge_environment (container_options )
408
439
409
440
if self .can_be_built ():
410
- if len (self .client .images (name = self ._build_tag_name ())) == 0 :
411
- self .build ()
412
- container_options ['image' ] = self ._build_tag_name ()
441
+ container_options ['image' ] = self .full_name
413
442
else :
414
443
container_options ['image' ] = self ._get_image_name (container_options ['image' ])
415
444
416
445
# Delete options which are only used when starting
417
- for key in ['privileged' , 'net' , 'dns' , 'dns_search' , 'restart' , 'cap_add' , 'cap_drop' , 'env_file' ]:
418
- if key in container_options :
419
- del container_options [key ]
446
+ for key in DOCKER_START_KEYS :
447
+ container_options .pop (key , None )
420
448
421
449
return container_options
422
450
@@ -431,7 +459,7 @@ def build(self, no_cache=False):
431
459
432
460
build_output = self .client .build (
433
461
self .options ['build' ],
434
- tag = self ._build_tag_name () ,
462
+ tag = self .full_name ,
435
463
stream = True ,
436
464
rm = True ,
437
465
nocache = no_cache ,
@@ -451,14 +479,15 @@ def build(self, no_cache=False):
451
479
image_id = match .group (1 )
452
480
453
481
if image_id is None :
454
- raise BuildError (self )
482
+ raise BuildError (self , event if all_events else 'Unknown' )
455
483
456
484
return image_id
457
485
458
486
def can_be_built (self ):
459
487
return 'build' in self .options
460
488
461
- def _build_tag_name (self ):
489
+ @property
490
+ def full_name (self ):
462
491
"""
463
492
The tag to give to images built for this service.
464
493
"""
0 commit comments