def run_container(name, image, command=None, environment=None, ro=None, rw=None, links=None, detach=True, volumes_from=None, port_bindings=None, log_syslog=False): """ Wrapper for docker create_container, start calls :param log_syslog: bool flag to redirect container's logs to host's syslog :returns: container info dict or None if container couldn't be created Raises PortAllocatedError if container couldn't start on the requested port. """ binds = ro_rw_to_binds(ro, rw) log_config = LogConfig(type=LogConfig.types.JSON) if log_syslog: log_config = LogConfig(type=LogConfig.types.SYSLOG, config={'syslog-tag': name}) host_config = _get_docker().create_host_config(binds=binds, log_config=log_config, links=links, volumes_from=volumes_from, port_bindings=port_bindings) c = _get_docker().create_container( name=name, image=image, command=command, environment=environment, volumes=binds_to_volumes(binds), detach=detach, stdin_open=False, tty=False, ports=list(port_bindings) if port_bindings else None, host_config=host_config) try: _get_docker().start(container=c['Id'], ) except APIError as e: if 'address already in use' in e.explanation: try: _get_docker().remove_container(name, force=True) except APIError: pass raise PortAllocatedError() raise return c
def test_create_host_config_obj_logconfig(self): obj = LogConfig(type=LogConfig.types.SYSLOG, config={'key1': 'val1'}) config = create_host_config(version=DEFAULT_DOCKER_API_VERSION, log_config=obj) self.assertIn('LogConfig', config) self.assertTrue(isinstance(config['LogConfig'], LogConfig)) self.assertEqual(obj, config['LogConfig'])
def _get_container_host_config(self, override_options, one_off=False): options = dict(self.options, **override_options) log_config = LogConfig(type=options.get('log_driver', ""), config=options.get('log_opt', None)) return self.client.create_host_config( links=self._get_links(link_to_self=one_off), port_bindings=build_port_bindings(options.get('ports') or []), binds=options.get('binds'), volumes_from=self._get_volumes_from(), privileged=options.get('privileged', False), network_mode=self.net.mode, devices=options.get('devices'), dns=options.get('dns'), dns_search=options.get('dns_search'), restart_policy=options.get('restart'), cap_add=options.get('cap_add'), cap_drop=options.get('cap_drop'), mem_limit=options.get('mem_limit'), memswap_limit=options.get('memswap_limit'), ulimits=build_ulimits(options.get('ulimits')), log_config=log_config, extra_hosts=options.get('extra_hosts'), read_only=options.get('read_only'), pid_mode=options.get('pid'), security_opt=options.get('security_opt'), ipc_mode=options.get('ipc'), cgroup_parent=options.get('cgroup_parent'), )
def get_log_config(logging_dict): log_driver = logging_dict.get('driver', "") if logging_dict else "" log_options = logging_dict.get('options', None) if logging_dict else None return LogConfig( type=log_driver, config=log_options )
def _get_container_host_config(self, override_options, one_off=False): options = dict(self.options, **override_options) port_bindings = build_port_bindings(options.get('ports') or []) privileged = options.get('privileged', False) cap_add = options.get('cap_add', None) cap_drop = options.get('cap_drop', None) log_config = LogConfig( type=options.get('log_driver', ""), config=options.get('log_opt', None) ) pid = options.get('pid', None) security_opt = options.get('security_opt', None) dns = options.get('dns', None) if isinstance(dns, six.string_types): dns = [dns] dns_search = options.get('dns_search', None) if isinstance(dns_search, six.string_types): dns_search = [dns_search] restart = parse_restart_spec(options.get('restart', None)) extra_hosts = build_extra_hosts(options.get('extra_hosts', None)) read_only = options.get('read_only', None) devices = options.get('devices', None) cgroup_parent = options.get('cgroup_parent', None) return self.client.create_host_config( links=self._get_links(link_to_self=one_off), port_bindings=port_bindings, binds=options.get('binds'), volumes_from=self._get_volumes_from(), privileged=privileged, network_mode=self.net.mode, devices=devices, dns=dns, dns_search=dns_search, restart_policy=restart, cap_add=cap_add, cap_drop=cap_drop, mem_limit=options.get('mem_limit'), memswap_limit=options.get('memswap_limit'), log_config=log_config, extra_hosts=extra_hosts, read_only=read_only, pid_mode=pid, security_opt=security_opt, ipc_mode=options.get('ipc'), cgroup_parent=cgroup_parent )
def _get_container_host_config(self, override_options, one_off=False): options = dict(self.options, **override_options) port_bindings = build_port_bindings(options.get('ports') or []) volume_bindings = dict( build_volume_binding(parse_volume_spec(volume)) for volume in options.get('volumes') or [] if ':' in volume) privileged = options.get('privileged', False) cap_add = options.get('cap_add', None) cap_drop = options.get('cap_drop', None) log_config = LogConfig(type=options.get('log_driver', 'json-file')) pid = options.get('pid', None) dns = options.get('dns', None) if isinstance(dns, six.string_types): dns = [dns] dns_search = options.get('dns_search', None) if isinstance(dns_search, six.string_types): dns_search = [dns_search] restart = parse_restart_spec(options.get('restart', None)) extra_hosts = build_extra_hosts(options.get('extra_hosts', None)) read_only = options.get('read_only', None) return create_host_config( links=self._get_links(link_to_self=one_off), port_bindings=port_bindings, binds=volume_bindings, volumes_from=options.get('volumes_from'), privileged=privileged, network_mode=self._get_net(), dns=dns, dns_search=dns_search, restart_policy=restart, cap_add=cap_add, cap_drop=cap_drop, log_config=log_config, extra_hosts=extra_hosts, read_only=read_only, pid_mode=pid )
def test_logconfig_invalid_config_type(self): with pytest.raises(ValueError): LogConfig(type=LogConfig.types.JSON, config='helloworld')
def create_one_container(host, version, entrypoint, env='prod', cores=None, ports=None, args=None, cpu_shares=1024, image='', need_network=False): # raw方式有些设定不同 is_raw = bool(image) if cores is None: cores = [] if ports is None: ports = [] if args is None: args = [] client = get_docker_client(host.addr) local_images = {r['RepoTags'][0] for r in client.images()} appconfig = version.appconfig appname = appconfig.appname entry = appconfig.entrypoints[entrypoint] envconfig = version.get_resource_config(env) # replace $port1... cmd = replace_ports(entry['cmd'], ports) # add extend arguments cmd = cmd + ' '.join([''] + args) if not is_raw: starter = 'launcheroot' if entry.get('privileged', '') else 'launcher' network = 'network' if need_network else 'nonetwork' cmd = '/usr/local/bin/%s %s %s' % (starter, network, cmd) network_mode = entry.get('network_mode', config.DOCKER_NETWORK_MODE) mem_limit = entry.get('mem_limit', 0) restart_policy = { 'MaximumRetryCount': 3, 'Name': entry.get('restart', 'no') } # could be no/always/on-failure # raw 模式下可以选择暴露端口 def get_ports(expose): inport, hostport = expose.split(':') return int(inport), int(hostport) exposes = [get_ports(expose) for expose in entry.get('exposes', [])] exposed_ports = None port_bindings = None if is_raw and exposes: exposed_ports = [p for p, _ in exposes] port_bindings = dict(exposes) if not image: image = '{0}/{1}:{2}'.format(config.DOCKER_REGISTRY, appname, version.short_sha) if image not in local_images: repo, tag = image.split(':', 1) for line in client.pull( repo, tag, stream=True, insecure_registry=config.DOCKER_REGISTRY_INSECURE): _log.info(line) env_dict = { 'APP_NAME': appname, 'ERU_RUNENV': env.upper(), 'ERU_POD': host.pod.name, 'ERU_HOST': host.name, } env_dict.update(envconfig.to_env_dict()) volumes = ['/writable-proc/sys'] volumes.extend(appconfig.get('volumes', [])) binds = {'/proc/sys': {'bind': '/writable-proc/sys', 'ro': False}} binds.update(appconfig.get('binds', {})) if config.ERU_CONTAINER_PERMDIR and entry.get('permdir', ''): permdir = config.ERU_CONTAINER_PERMDIR % appname env_dict['ERU_PERMDIR'] = permdir volumes.append(permdir) binds[config.ERU_HOST_PERMDIR % appname] = { 'bind': permdir, 'ro': False } extra_hosts = entry.get('hosts', None) # container name: {appname}_{entrypoint}_{ident_id} container_name = '_'.join([appname, entrypoint, gen_salt(6)]) # cpuset: '0,1,2,3' cpuset = ','.join([c.label for c in cores]) # host_config, include log_config host_config = client.create_host_config( binds=binds, network_mode=network_mode, log_config=LogConfig(type=config.DOCKER_LOG_DRIVER), ulimits=[Ulimit(name='nofile', soft=65535, hard=65535)], restart_policy=restart_policy, mem_limit=mem_limit, port_bindings=port_bindings, extra_hosts=extra_hosts, ) container = client.create_container( image=image, command=cmd, environment=env_dict, name=container_name, cpuset=cpuset, working_dir=None if is_raw else '/%s' % appname, network_disabled=config.DOCKER_NETWORK_DISABLED, volumes=volumes, host_config=host_config, cpu_shares=cpu_shares, ports=exposed_ports, ) container_id = container['Id'] client.start(container=container_id) return container_id, container_name
def test_create_host_config_obj_logconfig(self): obj = LogConfig(type=LogConfig.types.SYSLOG, config={'key1': 'val1'}) config = create_host_config(log_config=obj) self.assertIn('LogConfig', config) self.assertTrue(isinstance(config['LogConfig'], LogConfig)) self.assertEqual(obj, config['LogConfig'])
def test_logconfig_invalid_type(self): self.assertRaises(ValueError, lambda: LogConfig(type='xxx', config={})) self.assertRaises( ValueError, lambda: LogConfig(type=LogConfig.types.JSON, config='helloworld'))