Loading b5/modules/docker.py +54 −40 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ import pwd import warnings from ..exceptions import B5ExecutionError from . import BaseModule from . import BaseModule, CONFIG_PREFIX_RE class DockerModule(BaseModule): Loading @@ -24,7 +24,7 @@ class DockerModule(BaseModule): 'docker_machine': None, 'commands': {}, 'sync': {}, 'ensure_exists': {}, 'setup': {}, } def prepare_config(self): Loading @@ -46,8 +46,12 @@ class DockerModule(BaseModule): raise B5ExecutionError('docker commands has to be a dictionary') if not isinstance(self.config['sync'], dict): raise B5ExecutionError('docker sync has to be a dictionary') if not isinstance(self.config['ensure_exists'], dict): raise B5ExecutionError('ensure_exists has to be a dictionary') if not isinstance(self.config['setup'], dict): raise B5ExecutionError('setup has to be a dictionary') else: if 'networks' in self.config['setup']: if not isinstance(self.config['setup']['networks'], list): raise B5ExecutionError('setup.networks has to be a last') ##### CONFIGURATION MANAGEMENT ##### Loading Loading @@ -143,11 +147,13 @@ class DockerModule(BaseModule): ))) script.append(self._script_function_source('run', ''' {name}:setup ( {docker_env} "$@" ) '''.format( name=self.name, docker_env=self.get_script_env(), base_path=shlex.quote(self.config['base_path']), ))) Loading @@ -166,7 +172,6 @@ class DockerModule(BaseModule): script.append(self._script_function_source('docker-compose', ''' ( cd {base_path} && \\ if (declare -f -F {name}:create_external_networks > /dev/null); then {name}:create_external_networks; fi && \\ {name}:run {docker_compose_bin} {docker_compose_configs} "$@" ) '''.format( Loading Loading @@ -461,42 +466,51 @@ class DockerModule(BaseModule): else shlex.quote(command_options.get('bin')), ))) for ensure_exists, ensure_exists_options in self.config['ensure_exists'].items(): if ensure_exists == "external_networks": network_script = "" if not isinstance(ensure_exists_options, list): raise B5ExecutionError('ensure_exists options have to be a list') for network in ensure_exists_options: network_script = network_script + """ {name}:run {docker_bin} network inspect {network} &>/dev/null || ( {name}:run {docker_bin} network create {network} && echo \"Created external network {network}.\" if self.config['setup']: # Setup networks if 'networks' in self.config['setup'] and self.config['setup']['networks']: # Create a function for each network for setup_network_name in self.config['setup']['networks']: script.append(self._script_function_source('setup:network:{network}'.format(network=setup_network_name), ''' {name}:docker network inspect {network} &>/dev/null || ( {name}:docker network create {network} && echo \"Created network {network}.\" ); """.format( '''.format( name=self.name, docker_bin=shlex.quote(self.config['docker_bin']), network=network ) if network_script == "": # no networks to create => dummy function script.append(self._script_function_source('create_external_networks', ''' ( cd {base_path} ) network=shlex.quote(setup_network_name), ))) # Create general network setup function script.append(self._script_function_source('setup:network', ''' {setup_all_networks} '''.format( base_path=shlex.quote(self.config['base_path']), setup_all_networks='\n '.join([ 'setup:network:{network}'.format(network=setup_network_name) for setup_network_name in self.config['setup']['networks'] ]) ))) else: # append script to add external networks script.append(self._script_function_source('create_external_networks', ''' ( cd {base_path} && \\ {network_script} # Create general setup function setup_ran_var_name = '_{prefix}_SETUP_RAN'.format( prefix=CONFIG_PREFIX_RE.sub('_', self.name.upper()) ) script.append('{setup_ran_var}=0'.format(setup_ran_var=setup_ran_var_name)) script.append(self._script_function_source('setup', ''' if [ "${setup_ran_var}" -eq 1 ] then return 0 fi {setup_networks} {setup_ran_var}=1 '''.format( base_path=shlex.quote(self.config['base_path']), network_script=network_script setup_networks='{name}:setup:network'.format(name=self.name) if 'networks' in self.config['setup'] and self.config['setup']['networks'] else '', setup_ran_var=setup_ran_var_name, ))) else: # Create EMPTY general setup function, if no config exists script.append(self._script_function_source('setup', ''' true ''')) for sync, sync_options in self.config['sync'].items(): if not isinstance(sync_options, dict): Loading docs/modules/docker.md +8 −7 Original line number Diff line number Diff line Loading @@ -27,9 +27,10 @@ you probably want to put inside build/, too. `--pipe-in` to handle pipes (see `container_run`). You may use `-T` or `--disable-tty` to disable pseudo-tty allocation at all. All these parameters must be passed first, as other parameters will be passed to the executed command inside docker. * **ensure_exists**: This currently only supports one subkey 'external_networks' which can be a list of external_networks to create (if they do not yet exist) before running docker-compose. There is (currently) no logic implemented to clean up these external networks after they have been created by b5. * **setup**: Allows you to tell b5 to setup some docker specific things before running docker itself. This currently only supports one subkey 'networks' which can be a list of networks to create (if they do not yet exist). There is (currently) no logic implemented to clean up these networks after they have been created by b5. Can be used to make sure networks marked as external exist before running docker. * **sync**: List of paths to sync to docker volumes. See example below. Syncing some paths into volumes may increase the performance significantly. Note that these paths will only be updated when calling `docker:update` or `docker:sync`. Internally Loading Loading @@ -237,13 +238,13 @@ task:sync:phpvendor() { ``` ### Example 4 - auto-create external networks ### Example 4 - auto-create networks If external networks are defined in docker-compose.yml they are by default not auto-created by docker-compose and using docker-compose will fail with an error message about missing these networks. To auto-create these external networks when using docker-compose commands use the option ensure_exists['external_networks'] and provide a list of external networks to auto-create: setup.networks and provide a list of networks to auto-create: docker-compose.yml: ```yaml Loading @@ -267,9 +268,9 @@ config.yml: ```yaml modules: docker: ensure_exists: setup: # networks to auto-create external_networks: networks: - test_external_net ``` Loading Loading
b5/modules/docker.py +54 −40 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ import pwd import warnings from ..exceptions import B5ExecutionError from . import BaseModule from . import BaseModule, CONFIG_PREFIX_RE class DockerModule(BaseModule): Loading @@ -24,7 +24,7 @@ class DockerModule(BaseModule): 'docker_machine': None, 'commands': {}, 'sync': {}, 'ensure_exists': {}, 'setup': {}, } def prepare_config(self): Loading @@ -46,8 +46,12 @@ class DockerModule(BaseModule): raise B5ExecutionError('docker commands has to be a dictionary') if not isinstance(self.config['sync'], dict): raise B5ExecutionError('docker sync has to be a dictionary') if not isinstance(self.config['ensure_exists'], dict): raise B5ExecutionError('ensure_exists has to be a dictionary') if not isinstance(self.config['setup'], dict): raise B5ExecutionError('setup has to be a dictionary') else: if 'networks' in self.config['setup']: if not isinstance(self.config['setup']['networks'], list): raise B5ExecutionError('setup.networks has to be a last') ##### CONFIGURATION MANAGEMENT ##### Loading Loading @@ -143,11 +147,13 @@ class DockerModule(BaseModule): ))) script.append(self._script_function_source('run', ''' {name}:setup ( {docker_env} "$@" ) '''.format( name=self.name, docker_env=self.get_script_env(), base_path=shlex.quote(self.config['base_path']), ))) Loading @@ -166,7 +172,6 @@ class DockerModule(BaseModule): script.append(self._script_function_source('docker-compose', ''' ( cd {base_path} && \\ if (declare -f -F {name}:create_external_networks > /dev/null); then {name}:create_external_networks; fi && \\ {name}:run {docker_compose_bin} {docker_compose_configs} "$@" ) '''.format( Loading Loading @@ -461,42 +466,51 @@ class DockerModule(BaseModule): else shlex.quote(command_options.get('bin')), ))) for ensure_exists, ensure_exists_options in self.config['ensure_exists'].items(): if ensure_exists == "external_networks": network_script = "" if not isinstance(ensure_exists_options, list): raise B5ExecutionError('ensure_exists options have to be a list') for network in ensure_exists_options: network_script = network_script + """ {name}:run {docker_bin} network inspect {network} &>/dev/null || ( {name}:run {docker_bin} network create {network} && echo \"Created external network {network}.\" if self.config['setup']: # Setup networks if 'networks' in self.config['setup'] and self.config['setup']['networks']: # Create a function for each network for setup_network_name in self.config['setup']['networks']: script.append(self._script_function_source('setup:network:{network}'.format(network=setup_network_name), ''' {name}:docker network inspect {network} &>/dev/null || ( {name}:docker network create {network} && echo \"Created network {network}.\" ); """.format( '''.format( name=self.name, docker_bin=shlex.quote(self.config['docker_bin']), network=network ) if network_script == "": # no networks to create => dummy function script.append(self._script_function_source('create_external_networks', ''' ( cd {base_path} ) network=shlex.quote(setup_network_name), ))) # Create general network setup function script.append(self._script_function_source('setup:network', ''' {setup_all_networks} '''.format( base_path=shlex.quote(self.config['base_path']), setup_all_networks='\n '.join([ 'setup:network:{network}'.format(network=setup_network_name) for setup_network_name in self.config['setup']['networks'] ]) ))) else: # append script to add external networks script.append(self._script_function_source('create_external_networks', ''' ( cd {base_path} && \\ {network_script} # Create general setup function setup_ran_var_name = '_{prefix}_SETUP_RAN'.format( prefix=CONFIG_PREFIX_RE.sub('_', self.name.upper()) ) script.append('{setup_ran_var}=0'.format(setup_ran_var=setup_ran_var_name)) script.append(self._script_function_source('setup', ''' if [ "${setup_ran_var}" -eq 1 ] then return 0 fi {setup_networks} {setup_ran_var}=1 '''.format( base_path=shlex.quote(self.config['base_path']), network_script=network_script setup_networks='{name}:setup:network'.format(name=self.name) if 'networks' in self.config['setup'] and self.config['setup']['networks'] else '', setup_ran_var=setup_ran_var_name, ))) else: # Create EMPTY general setup function, if no config exists script.append(self._script_function_source('setup', ''' true ''')) for sync, sync_options in self.config['sync'].items(): if not isinstance(sync_options, dict): Loading
docs/modules/docker.md +8 −7 Original line number Diff line number Diff line Loading @@ -27,9 +27,10 @@ you probably want to put inside build/, too. `--pipe-in` to handle pipes (see `container_run`). You may use `-T` or `--disable-tty` to disable pseudo-tty allocation at all. All these parameters must be passed first, as other parameters will be passed to the executed command inside docker. * **ensure_exists**: This currently only supports one subkey 'external_networks' which can be a list of external_networks to create (if they do not yet exist) before running docker-compose. There is (currently) no logic implemented to clean up these external networks after they have been created by b5. * **setup**: Allows you to tell b5 to setup some docker specific things before running docker itself. This currently only supports one subkey 'networks' which can be a list of networks to create (if they do not yet exist). There is (currently) no logic implemented to clean up these networks after they have been created by b5. Can be used to make sure networks marked as external exist before running docker. * **sync**: List of paths to sync to docker volumes. See example below. Syncing some paths into volumes may increase the performance significantly. Note that these paths will only be updated when calling `docker:update` or `docker:sync`. Internally Loading Loading @@ -237,13 +238,13 @@ task:sync:phpvendor() { ``` ### Example 4 - auto-create external networks ### Example 4 - auto-create networks If external networks are defined in docker-compose.yml they are by default not auto-created by docker-compose and using docker-compose will fail with an error message about missing these networks. To auto-create these external networks when using docker-compose commands use the option ensure_exists['external_networks'] and provide a list of external networks to auto-create: setup.networks and provide a list of networks to auto-create: docker-compose.yml: ```yaml Loading @@ -267,9 +268,9 @@ config.yml: ```yaml modules: docker: ensure_exists: setup: # networks to auto-create external_networks: networks: - test_external_net ``` Loading