mirror of
https://github.com/docker/compose.git
synced 2025-04-08 17:05:13 +02:00
Merge pull request #1824 from mrfuxi/run-with-ports
Allow manual port mapping when using "run" command
This commit is contained in:
commit
b87c09b9fc
@ -282,7 +282,7 @@ class TopLevelCommand(Command):
|
|||||||
running. If you do not want to start linked services, use
|
running. If you do not want to start linked services, use
|
||||||
`docker-compose run --no-deps SERVICE COMMAND [ARGS...]`.
|
`docker-compose run --no-deps SERVICE COMMAND [ARGS...]`.
|
||||||
|
|
||||||
Usage: run [options] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]
|
Usage: run [options] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--allow-insecure-ssl Deprecated - no effect.
|
--allow-insecure-ssl Deprecated - no effect.
|
||||||
@ -293,6 +293,7 @@ class TopLevelCommand(Command):
|
|||||||
-u, --user="" Run as specified username or uid
|
-u, --user="" Run as specified username or uid
|
||||||
--no-deps Don't start linked services.
|
--no-deps Don't start linked services.
|
||||||
--rm Remove container after run. Ignored in detached mode.
|
--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
|
--service-ports Run command with the service's ports enabled and mapped
|
||||||
to the host.
|
to the host.
|
||||||
-T Disable pseudo-tty allocation. By default `docker-compose run`
|
-T Disable pseudo-tty allocation. By default `docker-compose run`
|
||||||
@ -344,6 +345,15 @@ class TopLevelCommand(Command):
|
|||||||
if not options['--service-ports']:
|
if not options['--service-ports']:
|
||||||
container_options['ports'] = []
|
container_options['ports'] = []
|
||||||
|
|
||||||
|
if options['--publish']:
|
||||||
|
container_options['ports'] = options.get('--publish')
|
||||||
|
|
||||||
|
if options['--publish'] and options['--service-ports']:
|
||||||
|
raise UserError(
|
||||||
|
'Service port mapping and manual port mapping '
|
||||||
|
'can not be used togather'
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
container = service.create_container(
|
container = service.create_container(
|
||||||
quiet=True,
|
quiet=True,
|
||||||
|
@ -248,7 +248,7 @@ _docker-compose_run() {
|
|||||||
|
|
||||||
case "$cur" in
|
case "$cur" in
|
||||||
-*)
|
-*)
|
||||||
COMPREPLY=( $( compgen -W "-d --entrypoint -e --help --no-deps --rm --service-ports -T --user -u" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "-d --entrypoint -e --help --no-deps --rm --service-ports --publish -p -T --user -u" -- "$cur" ) )
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
__docker-compose_services_all
|
__docker-compose_services_all
|
||||||
|
@ -221,6 +221,7 @@ __docker-compose_subcommand () {
|
|||||||
'(-u --user)'{-u,--user=-}'[Run as specified username or uid]:username or uid:_users' \
|
'(-u --user)'{-u,--user=-}'[Run as specified username or uid]:username or uid:_users' \
|
||||||
"--no-deps[Don't start linked services.]" \
|
"--no-deps[Don't start linked services.]" \
|
||||||
'--rm[Remove container after run. Ignored in detached mode.]' \
|
'--rm[Remove container after run. Ignored in detached mode.]' \
|
||||||
|
"--publish[Run command with manually mapped container's port(s) to the host.]" \
|
||||||
"--service-ports[Run command with the service's ports enabled and mapped 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.]' \
|
'-T[Disable pseudo-tty allocation. By default `docker-compose run` allocates a TTY.]' \
|
||||||
'(-):services:__docker-compose_services' \
|
'(-):services:__docker-compose_services' \
|
||||||
|
@ -22,6 +22,7 @@ Options:
|
|||||||
-u, --user="" Run as specified username or uid
|
-u, --user="" Run as specified username or uid
|
||||||
--no-deps Don't start linked services.
|
--no-deps Don't start linked services.
|
||||||
--rm Remove container after run. Ignored in detached mode.
|
--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.
|
--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.
|
-T Disable pseudo-tty allocation. By default `docker-compose run` allocates a TTY.
|
||||||
```
|
```
|
||||||
@ -38,6 +39,10 @@ The second difference is the `docker-compose run` command does not create any of
|
|||||||
|
|
||||||
$ docker-compose run --service-ports web python manage.py shell
|
$ docker-compose run --service-ports web python manage.py shell
|
||||||
|
|
||||||
|
Alternatively manual port mapping can be specified. Same as when running Docker's `run` command - using `--publish` or `-p` options:
|
||||||
|
|
||||||
|
$ docker-compose run --publish 8080:80 -p 2022:22 -p 127.0.0.1:2021:21 web python manage.py shell
|
||||||
|
|
||||||
If you start a service configured with links, the `run` command first checks to see if the linked service is running and starts the service if it is stopped. Once all the linked services are running, the `run` executes the command you passed it. So, for example, you could run:
|
If you start a service configured with links, the `run` command first checks to see if the linked service is running and starts the service if it is stopped. Once all the linked services are running, the `run` executes the command you passed it. So, for example, you could run:
|
||||||
|
|
||||||
$ docker-compose run db psql -h db -U docker
|
$ docker-compose run db psql -h db -U docker
|
||||||
|
@ -346,6 +346,44 @@ class CLITestCase(DockerClientTestCase):
|
|||||||
self.assertEqual(port_range[0], "0.0.0.0:49153")
|
self.assertEqual(port_range[0], "0.0.0.0:49153")
|
||||||
self.assertEqual(port_range[1], "0.0.0.0:49154")
|
self.assertEqual(port_range[1], "0.0.0.0:49154")
|
||||||
|
|
||||||
|
@patch('dockerpty.start')
|
||||||
|
def test_run_service_with_explicitly_maped_ports(self, __):
|
||||||
|
|
||||||
|
# create one off container
|
||||||
|
self.command.base_dir = 'tests/fixtures/ports-composefile'
|
||||||
|
self.command.dispatch(['run', '-d', '-p', '30000:3000', '--publish', '30001:3001', 'simple'], None)
|
||||||
|
container = self.project.get_service('simple').containers(one_off=True)[0]
|
||||||
|
|
||||||
|
# get port information
|
||||||
|
port_short = container.get_local_port(3000)
|
||||||
|
port_full = container.get_local_port(3001)
|
||||||
|
|
||||||
|
# close all one off containers we just created
|
||||||
|
container.stop()
|
||||||
|
|
||||||
|
# check the ports
|
||||||
|
self.assertEqual(port_short, "0.0.0.0:30000")
|
||||||
|
self.assertEqual(port_full, "0.0.0.0:30001")
|
||||||
|
|
||||||
|
@patch('dockerpty.start')
|
||||||
|
def test_run_service_with_explicitly_maped_ip_ports(self, __):
|
||||||
|
|
||||||
|
# create one off container
|
||||||
|
self.command.base_dir = 'tests/fixtures/ports-composefile'
|
||||||
|
self.command.dispatch(['run', '-d', '-p', '127.0.0.1:30000:3000', '--publish', '127.0.0.1:30001:3001', 'simple'], None)
|
||||||
|
container = self.project.get_service('simple').containers(one_off=True)[0]
|
||||||
|
|
||||||
|
# get port information
|
||||||
|
port_short = container.get_local_port(3000)
|
||||||
|
port_full = container.get_local_port(3001)
|
||||||
|
|
||||||
|
# close all one off containers we just created
|
||||||
|
container.stop()
|
||||||
|
|
||||||
|
# check the ports
|
||||||
|
self.assertEqual(port_short, "127.0.0.1:30000")
|
||||||
|
self.assertEqual(port_full, "127.0.0.1:30001")
|
||||||
|
|
||||||
def test_rm(self):
|
def test_rm(self):
|
||||||
service = self.project.get_service('simple')
|
service = self.project.get_service('simple')
|
||||||
service.create_container()
|
service.create_container()
|
||||||
|
@ -7,6 +7,7 @@ import docker
|
|||||||
import mock
|
import mock
|
||||||
|
|
||||||
from compose.cli.docopt_command import NoSuchCommand
|
from compose.cli.docopt_command import NoSuchCommand
|
||||||
|
from compose.cli.errors import UserError
|
||||||
from compose.cli.main import TopLevelCommand
|
from compose.cli.main import TopLevelCommand
|
||||||
from compose.service import Service
|
from compose.service import Service
|
||||||
|
|
||||||
@ -108,6 +109,7 @@ class CLITestCase(unittest.TestCase):
|
|||||||
'-T': None,
|
'-T': None,
|
||||||
'--entrypoint': None,
|
'--entrypoint': None,
|
||||||
'--service-ports': None,
|
'--service-ports': None,
|
||||||
|
'--publish': [],
|
||||||
'--rm': None,
|
'--rm': None,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -136,6 +138,7 @@ class CLITestCase(unittest.TestCase):
|
|||||||
'-T': None,
|
'-T': None,
|
||||||
'--entrypoint': None,
|
'--entrypoint': None,
|
||||||
'--service-ports': None,
|
'--service-ports': None,
|
||||||
|
'--publish': [],
|
||||||
'--rm': None,
|
'--rm': None,
|
||||||
})
|
})
|
||||||
_, _, call_kwargs = mock_client.create_container.mock_calls[0]
|
_, _, call_kwargs = mock_client.create_container.mock_calls[0]
|
||||||
@ -160,7 +163,35 @@ class CLITestCase(unittest.TestCase):
|
|||||||
'-T': None,
|
'-T': None,
|
||||||
'--entrypoint': None,
|
'--entrypoint': None,
|
||||||
'--service-ports': None,
|
'--service-ports': None,
|
||||||
|
'--publish': [],
|
||||||
'--rm': True,
|
'--rm': True,
|
||||||
})
|
})
|
||||||
_, _, call_kwargs = mock_client.create_container.mock_calls[0]
|
_, _, call_kwargs = mock_client.create_container.mock_calls[0]
|
||||||
self.assertFalse('RestartPolicy' in call_kwargs['host_config'])
|
self.assertFalse('RestartPolicy' in call_kwargs['host_config'])
|
||||||
|
|
||||||
|
def test_command_manula_and_service_ports_together(self):
|
||||||
|
command = TopLevelCommand()
|
||||||
|
mock_client = mock.create_autospec(docker.Client)
|
||||||
|
mock_project = mock.Mock(client=mock_client)
|
||||||
|
mock_project.get_service.return_value = Service(
|
||||||
|
'service',
|
||||||
|
client=mock_client,
|
||||||
|
restart='always',
|
||||||
|
image='someimage',
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertRaises(UserError):
|
||||||
|
command.run(mock_project, {
|
||||||
|
'SERVICE': 'service',
|
||||||
|
'COMMAND': None,
|
||||||
|
'-e': [],
|
||||||
|
'--user': None,
|
||||||
|
'--no-deps': None,
|
||||||
|
'--allow-insecure-ssl': None,
|
||||||
|
'-d': True,
|
||||||
|
'-T': None,
|
||||||
|
'--entrypoint': None,
|
||||||
|
'--service-ports': True,
|
||||||
|
'--publish': ['80:80'],
|
||||||
|
'--rm': None,
|
||||||
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user