8000 Docker: Support cpu shares and memory limit (#13504) · localstack/localstack@35f78d8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 35f78d8

Browse files
authored
Docker: Support cpu shares and memory limit (#13504)
1 parent 4a4d4cf commit 35f78d8

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

localstack-core/localstack/utils/container_utils/container_client.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,8 @@ class ContainerConfiguration:
544544
labels: dict[str, str] | None = None
545545
init: bool | None = None
546546
log_config: LogConfig | None = None
547+
cpu_shares: int | None = None
548+
mem_limit: int | str | None = None
547549

548550

549551
class ContainerConfigurator(Protocol):
@@ -979,6 +981,8 @@ def create_container_from_config(self, container_config: ContainerConfiguration)
979981
7440 ulimits=container_config.ulimits,
980982
init=container_config.init,
981983
log_config=container_config.log_config,
984+
cpu_shares=container_config.cpu_shares,
985+
mem_limit=container_config.mem_limit,
982986
)
983987

984988
@abstractmethod
@@ -1011,6 +1015,8 @@ def create_container(
10111015
ulimits: list[Ulimit] | None = None,
10121016
init: bool | None = None,
10131017
log_config: LogConfig | None = None,
1018+
cpu_shares: int | None = None,
1019+
mem_limit: int | str | None = None,
10141020
) -> str:
10151021
"""Creates a container with the given image
10161022
@@ -1048,6 +1054,8 @@ def run_container(
10481054
ulimits: list[Ulimit] | None = None,
10491055
init: bool | None = None,
10501056
log_config: LogConfig | None = None,
1057+
cpu_shares: int | None = None,
1058+
mem_limit: int | str | None = None,
10511059
) -> tuple[bytes, bytes]:
10521060
"""Creates and runs a given docker container
10531061
@@ -1086,6 +1094,8 @@ def run_container_from_config(
10861094
ulimits=container_config.ulimits,
10871095
init=container_config.init,
10881096
log_config=container_config.log_config,
1097+
cpu_shares=container_config.cpu_shares,
1098+
mem_limit=container_config.mem_limit,
10891099
)
10901100

10911101
@abstractmethod

localstack-core/localstack/utils/container_utils/docker_cmd_client.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,8 @@ def _build_run_create_cmd(
827827
ulimits: list[Ulimit] | None = None,
828828
init: bool | None = None,
829829
log_config: LogConfig | None = None,
830+
cpu_shares: int | None = None,
831+
mem_limit: int | str | None = None,
830832
) -> tuple[list[str], str]:
831833
env_file = None
832834
cmd = self._docker_cmd() + [action]
@@ -890,6 +892,10 @@ def _build_run_create_cmd(
890892
cmd += ["--log-driver", log_config.type]
891893
for key, value in log_config.config.items():
892894
cmd += ["--log-opt", f"{key}={value}"]
895+
if cpu_shares:
896+
cmd += ["--cpu-shares", str(cpu_shares)]
897+
if mem_limit:
898+
cmd += ["--memory", str(mem_limit)]
893899

894900
if additional_flags:
895901
cmd += shlex.split(additional_flags)

localstack-core/localstack/utils/container_utils/docker_sdk_client.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,8 @@ def create_container(
729729
ulimits: list[Ulimit] | None = None,
730730
init: bool | None = None,
731731
log_config: LogConfig | None = None,
732+
cpu_shares: int | None = None,
733+
mem_limit: int | str | None = None,
732734
) -> str:
733735
LOG.debug("Creating container with attributes: %s", locals())
734736
extra_hosts = None
@@ -793,6 +795,10 @@ def create_container(
793795
)
794796
for ulimit in ulimits
795797
]
798+
if cpu_shares:
799+
kwargs["cpu_shares"] = cpu_shares
800+
if mem_limit:
801+
kwargs["mem_limit"] = mem_limit
796802
mounts = None
797803
if volumes:
798804
mounts = Util.convert_mount_list_to_dict(volumes)
@@ -860,6 +866,8 @@ def run_container(
860866
ulimits: list[Ulimit] | None = None,
861867
init: bool | None = None,
862868
log_config: LogConfig | None = None,
869+
cpu_shares: int | None = None,
870+
mem_limit: int | str | None = None,
863871
) -> tuple[bytes, bytes]:
864872
LOG.debug("Running container with image: %s", image_name)
865873
container = None
@@ -891,6 +899,8 @@ def run_container(
891899
labels=labels,
892900
ulimits=ulimits,
893901
log_config=log_config,
902+
cpu_shares=cpu_shares,
903+
mem_limit=mem_limit,
894904
)
895905
result = self.start_container(
896906
container_name_or_id=container,

tests/integration/docker_utils/test_docker.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2187,6 +2187,35 @@ def test_get_container_stats(self, docker_client, create_container):
21872187
assert 0.0 <= stats["MemPerc"] <= 100.0
21882188

21892189

2190+
class TestDockerCgroupLimits:
2191+
def test_run_container_with_memory_limit(self, docker_client, create_container):
2192+
container = create_container(
2193+
"alpine",
2194+
command=[
2195+
"sh",
2196+
"-c",
2197+
"if [ -e /sys/fs/cgroup/cgroup.controllers ]; then cat /sys/fs/cgroup/memory.max; else cat /sys/fs/cgroup/memory/memory.limit_in_bytes; fi",
2198+
],
2199+
mem_limit="128m",
2200+
)
2201+
stdout, _ = docker_client.start_container(container.container_id, attach=True)
2202+
assert "134217728" in stdout.decode("utf-8")
2203+
2204+
def test_run_container_with_cpu_shares(self, docker_client, create_container):
2205+
container = create_container(
2206+
"alpine",
2207+
command=[
2208+
"sh",
2209+
"-c",
2210+
"if [ -e /sys/fs/cgroup/cgroup.controllers ]; then cat /sys/fs/cgroup/cpu.weight; else cat /sys/fs/cgroup/cpu,cpuacct/cpu.shares; fi",
2211+
],
2212+
cpu_shares=256,
2213+
)
2214+
stdout, _ = docker_client.start_container(container.container_id, attach=True)
2215+
stdout = stdout.decode("utf-8")
2216+
assert "35" in stdout or "256" in stdout
2217+
2218+
21902219
def _pull_image_if_not_exists(docker_client: ContainerClient, image_name: str):
21912220
if image_name not in docker_client.get_docker_image_names():
21922221
docker_client.pull_image(image_name)

0 commit comments

Comments
 (0)
0