Skip to content

Commit 4cb47e4

Browse files
committed
Merge pull request #586 from dnephin/speed_up_fig_up
Speed up fig up
2 parents 70c3676 + 3056ae4 commit 4cb47e4

File tree

5 files changed

+160
-85
lines changed

5 files changed

+160
-85
lines changed

fig/cli/main.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ def up(self, project, options):
425425
--no-color Produce monochrome output.
426426
--no-deps Don't start linked services.
427427
--no-recreate If containers already exist, don't recreate them.
428+
--no-build Don't build an image, even if it's missing
428429
"""
429430
insecure_registry = options['--allow-insecure-ssl']
430431
detached = options['-d']
@@ -440,7 +441,8 @@ def up(self, project, options):
440441
start_links=start_links,
441442
recreate=recreate,
442443
insecure_registry=insecure_registry,
443-
detach=options['-d']
444+
detach=options['-d'],
445+
do_build=not options['--no-build'],
444446
)
445447

446448
to_attach = [c for s in project.get_services(service_names) for c in s.containers()]

fig/project.py

+15-3
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,26 @@ def build(self, service_names=None, no_cache=False):
167167
else:
168168
log.info('%s uses an image, skipping' % service.name)
169169

170-
def up(self, service_names=None, start_links=True, recreate=True, insecure_registry=False, detach=False):
170+
def up(self,
171+
service_names=None,
172+
start_links=True,
173+
recreate=True,
174+
insecure_registry=False,
175+
detach=False,
176+
do_build=True):
171177
running_containers = []
172178
for service in self.get_services(service_names, include_links=start_links):
173179
if recreate:
174-
for (_, container) in service.recreate_containers(insecure_registry=insecure_registry, detach=detach):
180+
for (_, container) in service.recreate_containers(
181+
insecure_registry=insecure_registry,
182+
detach=detach,
183+
do_build=do_build):
175184
running_containers.append(container)
176185
else:
177-
for container in service.start_or_create_containers(insecure_registry=insecure_registry, detach=detach):
186+
for container in service.start_or_create_containers(
187+
insecure_registry=insecure_registry,
188+
detach=detach,
189+
do_build=do_build):
178190
running_containers.append(container)
179191

180192
return running_containers

fig/service.py

+48-19
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@
5050
'workdir' : 'working_dir',
5151
}
5252

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+
5364
VALID_NAME_CHARS = '[a-zA-Z0-9]'
5465

5566

@@ -145,7 +156,8 @@ def restart(self, **options):
145156

146157
def scale(self, desired_num):
147158
"""
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.
149161
150162
- creates containers until there are at least `desired_num`
151163
- stops containers until there are at most `desired_num` running
@@ -192,12 +204,24 @@ def remove_stopped(self, **options):
192204
log.info("Removing %s..." % c.name)
193205
c.remove(**options)
194206

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):
196212
"""
197213
Create a container for this service. If the image doesn't exist, attempt to pull
198214
it.
199215
"""
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+
201225
try:
202226
return Container.create(self.client, **container_options)
203227
except APIError as e:
@@ -212,15 +236,18 @@ def create_container(self, one_off=False, insecure_registry=False, **override_op
212236
return Container.create(self.client, **container_options)
213237
raise
214238

215-
def recreate_containers(self, insecure_registry=False, **override_options):
239+
def recreate_containers(self, insecure_registry=False, do_build=True, **override_options):
216240
"""
217241
If a container for this service doesn't exist, create and start one. If there are
218242
any, stop them, create+start new ones, and remove the old containers.
219243
"""
220244
containers = self.containers(stopped=True)
221245
if not containers:
222246
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)
224251
self.start_container(container)
225252
return [(None, container)]
226253
else:
@@ -259,7 +286,7 @@ def recreate_container(self, container, **override_options):
259286
container.remove()
260287

261288
options = dict(override_options)
262-
new_container = self.create_container(**options)
289+
new_container = self.create_container(do_build=False, **options)
263290
self.start_container(new_container, intermediate_container=intermediate_container)
264291

265292
intermediate_container.remove()
@@ -273,8 +300,7 @@ def start_container_if_stopped(self, container, **options):
273300
log.info("Starting %s..." % container.name)
274301
return self.start_container(container, **options)
275302

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):
278304
options = dict(self.options, **override_options)
279305
port_bindings = build_port_bindings(options.get('ports') or [])
280306

@@ -307,14 +333,19 @@ def start_container(self, container=None, intermediate_container=None, **overrid
307333
)
308334
return container
309335

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):
311341
containers = self.containers(stopped=True)
312342

313343
if not containers:
314344
log.info("Creating %s..." % self._next_container_name(containers))
315345
new_container = self.create_container(
316346
insecure_registry=insecure_registry,
317-
detach=detach
347+
detach=detach,
348+
do_build=do_build,
318349
)
319350
return [self.start_container(new_container)]
320351
else:
@@ -407,16 +438,13 @@ def _get_container_create_options(self, override_options, one_off=False):
407438
container_options['environment'] = merge_environment(container_options)
408439

409440
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
413442
else:
414443
container_options['image'] = self._get_image_name(container_options['image'])
415444

416445
# 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)
420448

421449
return container_options
422450

@@ -431,7 +459,7 @@ def build(self, no_cache=False):
431459

432460
build_output = self.client.build(
433461
self.options['build'],
434-
tag=self._build_tag_name(),
462+
tag=self.full_name,
435463
stream=True,
436464
rm=True,
437465
nocache=no_cache,
@@ -451,14 +479,15 @@ def build(self, no_cache=False):
451479
image_id = match.group(1)
452480

453481
if image_id is None:
454-
raise BuildError(self)
482+
raise BuildError(self, event if all_events else 'Unknown')
455483

456484
return image_id
457485

458486
def can_be_built(self):
459487
return 'build' in self.options
460488

461-
def _build_tag_name(self):
489+
@property
490+
def full_name(self):
462491
"""
463492
The tag to give to images built for this service.
464493
"""

0 commit comments

Comments
 (0)