def run_docker_container(docker_client, service, instance, docker_hash, volumes, interactive, command, hostname, healthcheck, healthcheck_only, instance_config, soa_dir=DEFAULT_SOA_DIR, dry_run=False, json_dict=False): """docker-py has issues running a container with a TTY attached, so for consistency we execute 'docker run' directly in both interactive and non-interactive modes. In non-interactive mode when the run is complete, stop the container and remove it (with docker-py). """ if interactive: sys.stderr.write( PaastaColors.yellow( "Warning! You're running a container in interactive mode.\n" "This is *NOT* how Mesos runs containers.\n" "To run the container exactly as Mesos does, omit the -I flag.\n\n" )) else: sys.stderr.write( PaastaColors.yellow( "You're running a container in non-interactive mode.\n" "This is how Mesos runs containers.\n" "Note that some programs behave differently when running with no\n" "tty attached (as your program is about to run).\n\n")) environment = instance_config.get_env_dictionary() net = instance_config.get_net() memory = instance_config.get_mem() random_port = pick_random_port() container_name = get_container_name() docker_params = instance_config.format_docker_parameters() docker_run_args = dict( memory=memory, random_port=random_port, container_name=container_name, volumes=volumes, env=environment, interactive=interactive, docker_hash=docker_hash, command=command, hostname=hostname, net=net, docker_params=docker_params, ) docker_run_cmd = get_docker_run_cmd(**docker_run_args) joined_docker_run_cmd = ' '.join(docker_run_cmd) healthcheck_mode, healthcheck_data = get_healthcheck_for_instance( service, instance, instance_config, random_port, soa_dir=soa_dir) if dry_run: if json_dict: sys.stdout.write(json.dumps(docker_run_args) + '\n') else: sys.stdout.write(json.dumps(docker_run_cmd) + '\n') sys.exit(0) else: sys.stdout.write('Running docker command:\n%s\n' % PaastaColors.grey(joined_docker_run_cmd)) if interactive: # NOTE: This immediately replaces us with the docker run cmd. Docker # run knows how to clean up the running container in this situation. execlp('docker', *docker_run_cmd) # For testing, when execlp is patched out and doesn't replace us, we # still want to bail out. return container_started = False container_id = None try: (returncode, output) = _run(joined_docker_run_cmd) if returncode != 0: sys.stdout.write('Failure trying to start your container!\n' 'Returncode: %d\n' 'Output:\n' '%s\n' '\n' 'Fix that problem and try again.\n' 'http://y/paasta-troubleshooting\n' % (returncode, output)) # Container failed to start so no need to cleanup; just bail. sys.exit(1) container_started = True container_id = get_container_id(docker_client, container_name) sys.stdout.write('Found our container running with CID %s\n' % container_id) # If the service has a healthcheck, simulate it if healthcheck_mode: status, _ = simulate_healthcheck_on_service( instance_config, docker_client, container_id, healthcheck_mode, healthcheck_data, healthcheck) else: status = True def _output_on_failure(): sys.stdout.write( 'Your service failed to start, here is the stdout and stderr\n' ) sys.stdout.write( PaastaColors.grey( docker_client.attach(container_id, stderr=True, stream=False, logs=True))) if healthcheck_only: sys.stdout.write( 'Detected --healthcheck-only flag, exiting now.\n') if container_started: _cleanup_container(docker_client, container_id) if status: sys.exit(0) else: _output_on_failure() sys.exit(1) running = docker_client.inspect_container( container_id)['State']['Running'] if running: sys.stdout.write( 'Your service is now running! Tailing stdout and stderr:\n') for line in docker_client.attach(container_id, stderr=True, stream=True, logs=True): sys.stdout.write(PaastaColors.grey(line)) else: _output_on_failure() returncode = 3 except KeyboardInterrupt: returncode = 3 # Cleanup if the container exits on its own or interrupted. if container_started: returncode = docker_client.inspect_container( container_id)['State']['ExitCode'] _cleanup_container(docker_client, container_id) sys.exit(returncode)
def run_docker_container( docker_client, service, instance, docker_hash, volumes, interactive, command, hostname, healthcheck, healthcheck_only, instance_config, soa_dir=DEFAULT_SOA_DIR, dry_run=False ): """docker-py has issues running a container with a TTY attached, so for consistency we execute 'docker run' directly in both interactive and non-interactive modes. In non-interactive mode when the run is complete, stop the container and remove it (with docker-py). """ if interactive: sys.stderr.write(PaastaColors.yellow( "Warning! You're running a container in interactive mode.\n" "This is *NOT* how Mesos runs containers.\n" "To run the container exactly as Mesos does, omit the -I flag.\n\n" )) else: sys.stderr.write(PaastaColors.yellow( "You're running a container in non-interactive mode.\n" "This is how Mesos runs containers.\n" "Note that some programs behave differently when running with no\n" "tty attached (as your program is about to run).\n\n" )) environment = instance_config.get_env_dictionary() net = instance_config.get_net() memory = instance_config.get_mem() random_port = pick_random_port() container_name = get_container_name() docker_params = instance_config.format_docker_parameters() docker_run_cmd = get_docker_run_cmd( memory=memory, random_port=random_port, container_name=container_name, volumes=volumes, env=environment, interactive=interactive, docker_hash=docker_hash, command=command, hostname=hostname, net=net, docker_params=docker_params, ) joined_docker_run_cmd = ' '.join(docker_run_cmd) healthcheck_mode, healthcheck_data = get_healthcheck_for_instance( service, instance, instance_config, random_port, soa_dir=soa_dir) if dry_run: sys.stdout.write(json.dumps(docker_run_cmd) + '\n') sys.exit(0) else: sys.stdout.write('Running docker command:\n%s\n' % PaastaColors.grey(joined_docker_run_cmd)) if interactive: # NOTE: This immediately replaces us with the docker run cmd. Docker # run knows how to clean up the running container in this situation. execlp('docker', *docker_run_cmd) # For testing, when execlp is patched out and doesn't replace us, we # still want to bail out. return container_started = False container_id = None try: (returncode, output) = _run(joined_docker_run_cmd) if returncode != 0: sys.stdout.write( 'Failure trying to start your container!\n' 'Returncode: %d\n' 'Output:\n' '%s\n' '\n' 'Fix that problem and try again.\n' 'http://y/paasta-troubleshooting\n' % (returncode, output) ) # Container failed to start so no need to cleanup; just bail. sys.exit(1) container_started = True container_id = get_container_id(docker_client, container_name) sys.stdout.write('Found our container running with CID %s\n' % container_id) # If the service has a healthcheck, simulate it if healthcheck_mode: status, _ = simulate_healthcheck_on_service( instance_config, docker_client, container_id, healthcheck_mode, healthcheck_data, healthcheck) else: status = True def _output_on_failure(): sys.stdout.write('Your service failed to start, here is the stdout and stderr\n') sys.stdout.write(PaastaColors.grey( docker_client.attach(container_id, stderr=True, stream=False, logs=True) )) if healthcheck_only: sys.stdout.write('Detected --healthcheck-only flag, exiting now.\n') if container_started: _cleanup_container(docker_client, container_id) if status: sys.exit(0) else: _output_on_failure() sys.exit(1) running = docker_client.inspect_container(container_id)['State']['Running'] if running: sys.stdout.write('Your service is now running! Tailing stdout and stderr:\n') for line in docker_client.attach(container_id, stderr=True, stream=True, logs=True): sys.stdout.write(PaastaColors.grey(line)) else: _output_on_failure() returncode = 3 except KeyboardInterrupt: returncode = 3 # Cleanup if the container exits on its own or interrupted. if container_started: returncode = docker_client.inspect_container(container_id)['State']['ExitCode'] _cleanup_container(docker_client, container_id) sys.exit(returncode)
def run_docker_container( docker_client, service, instance, docker_hash, volumes, interactive, command, healthcheck, healthcheck_only, instance_config, soa_dir=service_configuration_lib.DEFAULT_SOA_DIR, ): """docker-py has issues running a container with a TTY attached, so for consistency we execute 'docker run' directly in both interactive and non-interactive modes. In non-interactive mode when the run is complete, stop the container and remove it (with docker-py). """ if interactive: sys.stderr.write( PaastaColors.yellow( "Warning! You're running a container in interactive mode.\n" "This is *NOT* how Mesos runs containers.\n" "To run the container exactly as Mesos does, omit the -I flag.\n\n" ) ) else: sys.stderr.write( PaastaColors.yellow( "You're running a container in non-interactive mode.\n" "This is how Mesos runs containers.\n" "Note that some programs behave differently when running with no\n" "tty attached (as your program is about to run).\n\n" ) ) environment = instance_config.get_unformatted_env() memory = instance_config.get_mem() random_port = pick_random_port() container_name = get_container_name() docker_run_cmd = get_docker_run_cmd( memory=memory, random_port=random_port, container_name=container_name, volumes=volumes, env=environment, interactive=interactive, docker_hash=docker_hash, command=command, ) # http://stackoverflow.com/questions/4748344/whats-the-reverse-of-shlex-split joined_docker_run_cmd = " ".join(pipes.quote(word) for word in docker_run_cmd) healthcheck_mode, healthcheck_data = get_healthcheck_for_instance( service, instance, instance_config, random_port, soa_dir=soa_dir ) sys.stdout.write("Running docker command:\n%s\n" % PaastaColors.grey(joined_docker_run_cmd)) if interactive: # NOTE: This immediately replaces us with the docker run cmd. Docker # run knows how to clean up the running container in this situation. execlp("docker", *docker_run_cmd) # For testing, when execlp is patched out and doesn't replace us, we # still want to bail out. return container_started = False container_id = None try: (returncode, output) = _run(joined_docker_run_cmd) if returncode != 0: sys.stdout.write( "Failure trying to start your container!\n" "Returncode: %d\n" "Output:\n" "%s\n" "\n" "Fix that problem and try again.\n" "http://y/paasta-troubleshooting\n" % (returncode, output) ) # Container failed to start so no need to cleanup; just bail. sys.exit(1) container_started = True container_id = get_container_id(docker_client, container_name) sys.stdout.write("Found our container running with CID %s\n" % container_id) # If the service has a healthcheck, simulate it if healthcheck_mode: status = simulate_healthcheck_on_service( instance_config, docker_client, container_id, healthcheck_mode, healthcheck_data, healthcheck ) else: status = True if healthcheck_only: sys.stdout.write("Detected --healthcheck-only flag, exiting now.\n") if container_started: _cleanup_container(docker_client, container_id) if status: sys.exit(0) else: sys.exit(1) sys.stdout.write("Your service is now running! Tailing stdout and stderr:\n") for line in docker_client.attach(container_id, stderr=True, stream=True, logs=True): sys.stdout.write(PaastaColors.grey(line)) except KeyboardInterrupt: returncode = 3 pass # Cleanup if the container exits on its own or interrupted. if container_started: returncode = docker_client.inspect_container(container_id)["State"]["ExitCode"] _cleanup_container(docker_client, container_id) sys.exit(returncode)