def scale(self, options): """ Set number of containers to run for a service. Numbers are specified in the form `service=num` as arguments. For example: $ docker-compose scale web=2 worker=3 Usage: scale [options] [SERVICE=NUM...] Options: -t, --timeout TIMEOUT Specify a shutdown timeout in seconds. (default: 10) """ timeout = int(options.get('--timeout') or DEFAULT_TIMEOUT) for s in options['SERVICE=NUM']: if '=' not in s: raise UserError( 'Arguments to scale should be in the form service=num') service_name, num = s.split('=', 1) try: num = int(num) except ValueError: raise UserError( 'Number of containers for service "%s" is not a ' 'number' % service_name) self.project.get_service(service_name).scale(num, timeout=timeout)
def run(self, options): """ Run a one-off command on a service. For example: $ docker-compose run web python manage.py shell By default, linked services will be started, unless they are already running. If you do not want to start linked services, use `docker-compose run --no-deps SERVICE COMMAND [ARGS...]`. Usage: run [options] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...] Options: -d Detached mode: Run container in the background, print new container name. --name NAME Assign a name to the container --entrypoint CMD Override the entrypoint of the image. -e KEY=VAL Set an environment variable (can be used multiple times) -u, --user="" Run as specified username or uid --no-deps Don't start linked services. --rm Remove container after run. Ignored in detached mode. -p, --publish=[] Publish a container's port(s) to the host --service-ports Run command with the service's ports enabled and mapped to the host. -T Disable pseudo-tty allocation. By default `docker-compose run` allocates a TTY. -w, --workdir="" Working directory inside the container """ service = self.project.get_service(options['SERVICE']) detach = options['-d'] if IS_WINDOWS_PLATFORM and not detach: raise UserError( "Interactive mode is not yet supported on Windows.\n" "Please pass the -d flag when using `docker-compose run`.") if options['--publish'] and options['--service-ports']: raise UserError('Service port mapping and manual port mapping ' 'can not be used togather') if options['COMMAND']: command = [options['COMMAND']] + options['ARGS'] else: command = service.options.get('command') container_options = build_container_options(options, detach, command) exit_code = run_one_off_container(container_options, self.project, service, options) output['code'] = exit_code return output
def voodoo_load_yaml(file_name): try: # Load default voodoo config default_config_path = os.path.join(os.path.expanduser("~"), '.voodoo', 'config.yml') with open(default_config_path, 'r') as fh: voodoo_config = yaml.safe_load(fh) with open(file_name, 'r') as fh: #Load custom config config = yaml.safe_load(fh) #update voodoo config voodoo_config.update(config.pop('voodoo', {})) # share .voodoo folder in voodoo home = os.path.expanduser("~") shared = os.path.join(home, '.voodoo', 'shared') config['odoo']['volumes'].append('%s:%s' % (shared, shared)) # Add gitconfig in voodoo if 'gitconfig' in voodoo_config: gitconfig = os.path.expanduser(voodoo_config['gitconfig']) config['odoo']['volumes'].append( '%s:/home/devstep/.gitconfig' % (gitconfig)) #Add environment variable config['odoo']['environment'] += [ 'SHARED_FOLDER=%s' % shared, 'SHARED_EGGS=%s' % str(voodoo_config['shared_eggs']).lower(), ] return config except IOError as e: raise UserError(six.text_type(e))
def image_type_from_opt(flag, value): if not value: return ImageType.none try: return ImageType[value] except KeyError: raise UserError("%s flag must be one of: all, local" % flag)
def logs(self, options): """ View output from containers. Usage: logs [options] [SERVICE...] Options: --no-color Produce monochrome output. -f, --follow Follow log output. -t, --timestamps Show timestamps. --tail="all" Number of lines to show from the end of the logs for each container. """ containers = self.project.containers(service_names=options['SERVICE'], stopped=True) tail = options['--tail'] if tail is not None: if tail.isdigit(): tail = int(tail) elif tail != 'all': raise UserError("tail flag must be all or a number") log_args = { 'follow': options['--follow'], 'tail': tail, 'timestamps': options['--timestamps'] } print("Attaching to", list_containers(containers)) log_printer_from_project(self.project, containers, options['--no-color'], log_args, event_stream=self.project.events( service_names=options['SERVICE'])).run()
def build_action_from_opts(options): if options['--build'] and options['--no-build']: raise UserError("--build and --no-build can not be combined.") if options['--build']: return BuildAction.force if options['--no-build']: return BuildAction.skip return BuildAction.none
def load_project_config(self, options): explicit_config_path = options.get('--file')\ or os.environ.get('COMPOSE_FILE')\ or os.environ.get('FIG_FILE') config_path = self.get_config_path(file_path=explicit_config_path) try: with open(config_path, 'r') as fh: config = yaml.safe_load(fh) voodoo_config = config.pop('voodoo', {}) self.set_config(voodoo_config) except IOError as e: raise UserError(six.text_type(e))
def exec_command(self, options): """ Execute a command in a running container Usage: exec [options] SERVICE COMMAND [ARGS...] Options: -d Detached mode: Run command in the background. --privileged Give extended privileges to the process. --user USER Run the command as this user. -T Disable pseudo-tty allocation. By default `docker-compose exec` allocates a TTY. --index=index index of the container if there are multiple instances of a service [default: 1] """ index = int(options.get('--index')) service = self.project.get_service(options['SERVICE']) try: container = service.get_container(number=index) except ValueError as e: raise UserError(str(e)) command = [options['COMMAND']] + options['ARGS'] tty = not options["-T"] create_exec_options = { "privileged": options["--privileged"], "user": options["--user"], "tty": tty, "stdin": tty, } exec_id = container.create_exec(command, **create_exec_options) print exec_id if options['-d']: print container.start_exec(exec_id, tty=tty) print "option -d" return signals.set_signal_handler_to_shutdown() try: operation = ExecOperation( self.project.client, exec_id, interactive=tty, ) print "Pseudo Terminal" pty = PseudoTerminal(self.project.client, operation) pty.start() except signals.ShutdownException: log.info("received shutdown exception: closing") exit_code = self.project.client.exec_inspect(exec_id).get("ExitCode") sys.exit(exit_code)
def convergence_strategy_from_opts(options): no_recreate = options['--no-recreate'] force_recreate = options['--force-recreate'] if force_recreate and no_recreate: raise UserError( "--force-recreate and --no-recreate cannot be combined.") if force_recreate: return ConvergenceStrategy.always if no_recreate: return ConvergenceStrategy.never return ConvergenceStrategy.changed
def port(self, options): """ Print the public port for a port binding. Usage: port [options] SERVICE PRIVATE_PORT Options: --protocol=proto tcp or udp [default: tcp] --index=index index of the container if there are multiple instances of a service [default: 1] """ index = int(options.get('--index')) service = self.project.get_service(options['SERVICE']) try: container = service.get_container(number=index) except ValueError as e: raise UserError(str(e)) print( container.get_local_port(options['PRIVATE_PORT'], protocol=options.get('--protocol') or 'tcp') or '')
def up(self, options): """ Builds, (re)creates, starts, and attaches to containers for a service. Unless they are already running, this command also starts any linked services. The `docker-compose up` command aggregates the output of each container. When the command exits, all containers are stopped. Running `docker-compose up -d` starts the containers in the background and leaves them running. If there are existing containers for a service, and the service's configuration or image was changed after the container's creation, `docker-compose up` picks up the changes by stopping and recreating the containers (preserving mounted volumes). To prevent Compose from picking up changes, use the `--no-recreate` flag. If you want to force Compose to stop and recreate all containers, use the `--force-recreate` flag. Usage: up [options] [SERVICE...] Options: -d Detached mode: Run containers in the background, print new container names. Incompatible with --abort-on-container-exit. --no-color Produce monochrome output. --no-deps Don't start linked services. --force-recreate Recreate containers even if their configuration and image haven't changed. Incompatible with --no-recreate. --no-recreate If containers already exist, don't recreate them. Incompatible with --force-recreate. --no-build Don't build an image, even if it's missing. --build Build images before starting containers. --abort-on-container-exit Stops all containers if any container was stopped. Incompatible with -d. -t, --timeout TIMEOUT Use this timeout in seconds for container shutdown when attached or when containers are already running. (default: 10) --remove-orphans Remove containers for services not defined in the Compose file """ start_deps = not options['--no-deps'] cascade_stop = options['--abort-on-container-exit'] service_names = options['SERVICE'] timeout = int(options.get('--timeout') or DEFAULT_TIMEOUT) remove_orphans = options['--remove-orphans'] detached = options.get('-d') if detached and cascade_stop: raise UserError( "--abort-on-container-exit and -d cannot be combined.") with up_shutdown_context(self.project, service_names, timeout, detached): to_attach = self.project.up( service_names=service_names, start_deps=start_deps, strategy=convergence_strategy_from_opts(options), do_build=build_action_from_opts(options), timeout=timeout, detached=detached, remove_orphans=remove_orphans) if detached: return log_printer = log_printer_from_project( self.project, filter_containers_to_service_names(to_attach, service_names), options['--no-color'], {'follow': True}, cascade_stop, event_stream=self.project.events(service_names=service_names)) print("Attaching to", list_containers(log_printer.containers)) log_printer.run() if cascade_stop: print("Aborting on container exit...") self.project.stop(service_names=service_names, timeout=timeout)