From 11f0f1b9b22a40e9001c0416f814eb047fc2b448 Mon Sep 17 00:00:00 2001 From: Guillaume Desforges Date: Wed, 24 Jul 2024 19:37:41 +0200 Subject: [PATCH] fix: handle docker network host Fixes #4236. PR #669 allowed usage of the host network for Docker containers, but that feature was removed in PR #5279. This change reintroduces setting `network_mode` to `host` when `docker_network` is `host`, and adds some additional debug logging to ease debugging. --- samcli/local/docker/container.py | 31 ++++++++++++++++------- tests/unit/local/docker/test_container.py | 2 +- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/samcli/local/docker/container.py b/samcli/local/docker/container.py index a34e96c7c1b..5ee7273d8ab 100644 --- a/samcli/local/docker/container.py +++ b/samcli/local/docker/container.py @@ -154,6 +154,7 @@ def __init__( self.rapid_port_host = find_free_port( network_interface=self._container_host_interface, start=self._start_port_range, end=self._end_port_range ) + except NoFreePortsError as ex: raise ContainerNotStartableException(str(ex)) from ex @@ -216,15 +217,25 @@ def create(self): if self._env_vars: kwargs["environment"] = self._env_vars - kwargs["ports"] = {self.RAPID_PORT_CONTAINER: (self._container_host_interface, self.rapid_port_host)} - - if self._exposed_ports: - kwargs["ports"].update( - { - container_port: (self._container_host_interface, host_port) - for container_port, host_port in self._exposed_ports.items() - } - ) + if self.network_id == "host": + kwargs["network_mode"] = self.network_id + # When using host network, aws-lambda-rie will bind to 8080 + self.rapid_port_host = int(self.RAPID_PORT_CONTAINER) + LOG.warning("Using host network mode will bind to port %s", self.RAPID_PORT_CONTAINER) + + # It is not possible to both use host network and expose ports + if "network_mode" in kwargs and kwargs["network_mode"] == "host": + LOG.warning("Using host network mode, ignoring any port mappings") + else: + kwargs["ports"] = {self.RAPID_PORT_CONTAINER: (self._container_host_interface, self.rapid_port_host)} + + if self._exposed_ports: + kwargs["ports"].update( + { + container_port: (self._container_host_interface, host_port) + for container_port, host_port in self._exposed_ports.items() + } + ) if self._entrypoint: kwargs["entrypoint"] = self._entrypoint @@ -236,6 +247,8 @@ def create(self): if self._extra_hosts: kwargs["extra_hosts"] = self._extra_hosts + LOG.debug("Docker will start with the following arguments: %s", kwargs) + try: real_container = self.docker_client.containers.create(self._image, **kwargs) except DockerAPIError as ex: diff --git a/tests/unit/local/docker/test_container.py b/tests/unit/local/docker/test_container.py index b181ce33fa0..3345bed9cea 100644 --- a/tests/unit/local/docker/test_container.py +++ b/tests/unit/local/docker/test_container.py @@ -307,7 +307,7 @@ def test_must_connect_to_host_network_on_create(self, mock_resolve_symlinks): self.image, command=self.cmd, working_dir=self.working_dir, - ports=self.always_exposed_ports, + network_mode="host", tty=False, use_config_proxy=True, volumes=expected_volumes,