mirror of
https://github.com/docker/compose.git
synced 2025-07-27 07:34:10 +02:00
Merge pull request #3980 from aanand/shell-out-attach
Attach interactively on Windows by shelling out
This commit is contained in:
commit
de15ec835a
@ -17,6 +17,7 @@ from .utils import call_silently
|
|||||||
from .utils import is_docker_for_mac_installed
|
from .utils import is_docker_for_mac_installed
|
||||||
from .utils import is_mac
|
from .utils import is_mac
|
||||||
from .utils import is_ubuntu
|
from .utils import is_ubuntu
|
||||||
|
from .utils import is_windows
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -90,11 +91,7 @@ def exit_with_error(msg):
|
|||||||
|
|
||||||
def get_conn_error_message(url):
|
def get_conn_error_message(url):
|
||||||
if call_silently(['which', 'docker']) != 0:
|
if call_silently(['which', 'docker']) != 0:
|
||||||
if is_mac():
|
return docker_not_found_msg("Couldn't connect to Docker daemon.")
|
||||||
return docker_not_found_mac
|
|
||||||
if is_ubuntu():
|
|
||||||
return docker_not_found_ubuntu
|
|
||||||
return docker_not_found_generic
|
|
||||||
if is_docker_for_mac_installed():
|
if is_docker_for_mac_installed():
|
||||||
return conn_error_docker_for_mac
|
return conn_error_docker_for_mac
|
||||||
if call_silently(['which', 'docker-machine']) == 0:
|
if call_silently(['which', 'docker-machine']) == 0:
|
||||||
@ -102,25 +99,26 @@ def get_conn_error_message(url):
|
|||||||
return conn_error_generic.format(url=url)
|
return conn_error_generic.format(url=url)
|
||||||
|
|
||||||
|
|
||||||
docker_not_found_mac = """
|
def docker_not_found_msg(problem):
|
||||||
Couldn't connect to Docker daemon. You might need to install Docker:
|
return "{} You might need to install Docker:\n\n{}".format(
|
||||||
|
problem, docker_install_url())
|
||||||
https://docs.docker.com/engine/installation/mac/
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
docker_not_found_ubuntu = """
|
def docker_install_url():
|
||||||
Couldn't connect to Docker daemon. You might need to install Docker:
|
if is_mac():
|
||||||
|
return docker_install_url_mac
|
||||||
https://docs.docker.com/engine/installation/ubuntulinux/
|
elif is_ubuntu():
|
||||||
"""
|
return docker_install_url_ubuntu
|
||||||
|
elif is_windows():
|
||||||
|
return docker_install_url_windows
|
||||||
|
else:
|
||||||
|
return docker_install_url_generic
|
||||||
|
|
||||||
|
|
||||||
docker_not_found_generic = """
|
docker_install_url_mac = "https://docs.docker.com/engine/installation/mac/"
|
||||||
Couldn't connect to Docker daemon. You might need to install Docker:
|
docker_install_url_ubuntu = "https://docs.docker.com/engine/installation/ubuntulinux/"
|
||||||
|
docker_install_url_windows = "https://docs.docker.com/engine/installation/windows/"
|
||||||
https://docs.docker.com/engine/installation/
|
docker_install_url_generic = "https://docs.docker.com/engine/installation/"
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
conn_error_docker_machine = """
|
conn_error_docker_machine = """
|
||||||
|
@ -6,7 +6,9 @@ import contextlib
|
|||||||
import functools
|
import functools
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import pipes
|
||||||
import re
|
import re
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from inspect import getdoc
|
from inspect import getdoc
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
@ -406,11 +408,6 @@ class TopLevelCommand(object):
|
|||||||
service = self.project.get_service(options['SERVICE'])
|
service = self.project.get_service(options['SERVICE'])
|
||||||
detach = options['-d']
|
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 exec`."
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
container = service.get_container(number=index)
|
container = service.get_container(number=index)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
@ -418,6 +415,28 @@ class TopLevelCommand(object):
|
|||||||
command = [options['COMMAND']] + options['ARGS']
|
command = [options['COMMAND']] + options['ARGS']
|
||||||
tty = not options["-T"]
|
tty = not options["-T"]
|
||||||
|
|
||||||
|
if IS_WINDOWS_PLATFORM and not detach:
|
||||||
|
args = ["exec"]
|
||||||
|
|
||||||
|
if options["-d"]:
|
||||||
|
args += ["--detach"]
|
||||||
|
else:
|
||||||
|
args += ["--interactive"]
|
||||||
|
|
||||||
|
if not options["-T"]:
|
||||||
|
args += ["--tty"]
|
||||||
|
|
||||||
|
if options["--privileged"]:
|
||||||
|
args += ["--privileged"]
|
||||||
|
|
||||||
|
if options["--user"]:
|
||||||
|
args += ["--user", options["--user"]]
|
||||||
|
|
||||||
|
args += [container.id]
|
||||||
|
args += command
|
||||||
|
|
||||||
|
sys.exit(call_docker(args))
|
||||||
|
|
||||||
create_exec_options = {
|
create_exec_options = {
|
||||||
"privileged": options["--privileged"],
|
"privileged": options["--privileged"],
|
||||||
"user": options["--user"],
|
"user": options["--user"],
|
||||||
@ -675,12 +694,6 @@ class TopLevelCommand(object):
|
|||||||
service = self.project.get_service(options['SERVICE'])
|
service = self.project.get_service(options['SERVICE'])
|
||||||
detach = options['-d']
|
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']:
|
if options['--publish'] and options['--service-ports']:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
'Service port mapping and manual port mapping '
|
'Service port mapping and manual port mapping '
|
||||||
@ -969,17 +982,20 @@ def run_one_off_container(container_options, project, service, options):
|
|||||||
signals.set_signal_handler_to_shutdown()
|
signals.set_signal_handler_to_shutdown()
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
operation = RunOperation(
|
if IS_WINDOWS_PLATFORM:
|
||||||
project.client,
|
exit_code = call_docker(["start", "--attach", "--interactive", container.id])
|
||||||
container.id,
|
else:
|
||||||
interactive=not options['-T'],
|
operation = RunOperation(
|
||||||
logs=False,
|
project.client,
|
||||||
)
|
container.id,
|
||||||
pty = PseudoTerminal(project.client, operation)
|
interactive=not options['-T'],
|
||||||
sockets = pty.sockets()
|
logs=False,
|
||||||
service.start_container(container)
|
)
|
||||||
pty.start(sockets)
|
pty = PseudoTerminal(project.client, operation)
|
||||||
exit_code = container.wait()
|
sockets = pty.sockets()
|
||||||
|
service.start_container(container)
|
||||||
|
pty.start(sockets)
|
||||||
|
exit_code = container.wait()
|
||||||
except signals.ShutdownException:
|
except signals.ShutdownException:
|
||||||
project.client.stop(container.id)
|
project.client.stop(container.id)
|
||||||
exit_code = 1
|
exit_code = 1
|
||||||
@ -1044,3 +1060,15 @@ def exit_if(condition, message, exit_code):
|
|||||||
if condition:
|
if condition:
|
||||||
log.error(message)
|
log.error(message)
|
||||||
raise SystemExit(exit_code)
|
raise SystemExit(exit_code)
|
||||||
|
|
||||||
|
|
||||||
|
def call_docker(args):
|
||||||
|
try:
|
||||||
|
executable_path = subprocess.check_output(["which", "docker"]).strip()
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
raise UserError(errors.docker_not_found_msg("Couldn't find `docker` binary."))
|
||||||
|
|
||||||
|
args = [executable_path] + args
|
||||||
|
log.debug(" ".join(map(pipes.quote, args)))
|
||||||
|
|
||||||
|
return subprocess.call(args)
|
||||||
|
@ -11,6 +11,7 @@ import sys
|
|||||||
import docker
|
import docker
|
||||||
|
|
||||||
import compose
|
import compose
|
||||||
|
from ..const import IS_WINDOWS_PLATFORM
|
||||||
|
|
||||||
# WindowsError is not defined on non-win32 platforms. Avoid runtime errors by
|
# WindowsError is not defined on non-win32 platforms. Avoid runtime errors by
|
||||||
# defining it as OSError (its parent class) if missing.
|
# defining it as OSError (its parent class) if missing.
|
||||||
@ -73,6 +74,10 @@ def is_ubuntu():
|
|||||||
return platform.system() == 'Linux' and platform.linux_distribution()[0] == 'Ubuntu'
|
return platform.system() == 'Linux' and platform.linux_distribution()[0] == 'Ubuntu'
|
||||||
|
|
||||||
|
|
||||||
|
def is_windows():
|
||||||
|
return IS_WINDOWS_PLATFORM
|
||||||
|
|
||||||
|
|
||||||
def get_version_info(scope):
|
def get_version_info(scope):
|
||||||
versioninfo = 'docker-compose version {}, build {}'.format(
|
versioninfo = 'docker-compose version {}, build {}'.format(
|
||||||
compose.__version__,
|
compose.__version__,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user