Repository: localstack/localstack

Issue:
feature request: Lambda container name collision in multi-tenanted localstack environment
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Feature description

I know this is a bit out there, and I'm probably the only one that wants this.

We're running a multi-tenanted localstack env, so we have multiple parent localstack containers running on the same host. Each parent container spawns child Lambda containers are required. With `LAMBDA_EXECUTOR: docker-reuse` at least, when a parent container spawns a child container it gives it the name:
`localstack_lambda_arn_aws_lambda_<region>_000000000000_function_<function_name>`.

The problem for us is that we cannot deploy a function with the same name across two localstack instances as the container names of the resulting Lambda containers overlap. If you do this and invoke the function, the container is created from the relevant parent - but then reused by all other parents as the container "already exists".

I'm not sure of the full implications of this, but at the very least it will use incorrect function code as it's just reusing the container created by the other instance. Presumably there is also issues RE: transparent SDK patching and DNS, as it's _probably_ talking to the wrong parent instance.

### 🧑‍💻 Implementation

I'm not sure what other implications this has, but I can see here that the Lambda container prefix is hard coded.
https://github.com/localstack/localstack/blob/49f36937c7d823f77ed821bfd4242e87d9685b7d/localstack/services/awslambda/lambda_executors.py#L1030 

Instead of the hard coded `localstack` value, could this instead use the localstack parent's container name?

If this causes an issue, could there perhaps be another environment variable added, allowing us to customise the Lambda container name prefix?

### Anything else?

_No response_


Discussion:

Resolving patch:
diff --git a/localstack/services/awslambda/lambda_executors.py b/localstack/services/awslambda/lambda_executors.py
--- a/localstack/services/awslambda/lambda_executors.py
+++ b/localstack/services/awslambda/lambda_executors.py
@@ -26,6 +26,7 @@
     store_lambda_logs,
 )
 from localstack.services.install import GO_LAMBDA_RUNTIME, INSTALL_PATH_LOCALSTACK_FAT_JAR
+from localstack.utils import bootstrap
 from localstack.utils.aws import aws_stack
 from localstack.utils.aws.aws_models import LambdaFunction
 from localstack.utils.aws.dead_letter_queue import (
@@ -942,7 +943,9 @@ def get_all_container_names(self):
         """
         with self.docker_container_lock:
             LOG.debug("Getting all lambda containers names.")
-            list_result = DOCKER_CLIENT.list_containers(filter="name=localstack_lambda_*")
+            list_result = DOCKER_CLIENT.list_containers(
+                filter=f"name={self.get_container_prefix()}*"
+            )
             container_names = list(map(lambda container: container["name"], list_result))
 
             return container_names
@@ -1021,13 +1024,20 @@ def start_idle_container_destroyer_interval(self):
         self.idle_container_destroyer()
         threading.Timer(60.0, self.start_idle_container_destroyer_interval).start()
 
+    def get_container_prefix(self) -> str:
+        """
+        Returns the prefix of all docker-reuse lambda containers for this LocalStack instance
+        :return: Lambda container name prefix
+        """
+        return f"{bootstrap.get_main_container_name()}_lambda_"
+
     def get_container_name(self, func_arn):
         """
         Given a function ARN, returns a valid docker container name.
         :param func_arn: The ARN of the lambda function.
         :return: A docker compatible name for the arn.
         """
-        return "localstack_lambda_" + re.sub(r"[^a-zA-Z0-9_.-]", "_", func_arn)
+        return self.get_container_prefix() + re.sub(r"[^a-zA-Z0-9_.-]", "_", func_arn)
 
 
 class LambdaExecutorSeparateContainers(LambdaExecutorContainers):


Test patch:
diff --git a/tests/unit/test_lambda.py b/tests/unit/test_lambda.py
--- a/tests/unit/test_lambda.py
+++ b/tests/unit/test_lambda.py
@@ -749,9 +749,9 @@ def test_list_non_existant_function_aliases_returns_error(self):
     def test_get_container_name(self):
         executor = lambda_executors.EXECUTOR_CONTAINERS_REUSE
         name = executor.get_container_name(aws_stack.lambda_function_arn("my_function_name"))
-        self.assertEqual(
+        self.assertIn(
+            f"_lambda_arn_aws_lambda_{aws_stack.get_region()}_{TEST_AWS_ACCOUNT_ID}_function_my_function_name",
             name,
-            f"localstack_lambda_arn_aws_lambda_{aws_stack.get_region()}_{TEST_AWS_ACCOUNT_ID}_function_my_function_name",
         )
 
     def test_concurrency(self):