diff --git a/torchx/schedulers/docker_scheduler.py b/torchx/schedulers/docker_scheduler.py index e608d0c1b..48954a8b9 100644 --- a/torchx/schedulers/docker_scheduler.py +++ b/torchx/schedulers/docker_scheduler.py @@ -9,6 +9,7 @@ import fnmatch import logging import os.path +import re import tempfile from dataclasses import dataclass from datetime import datetime @@ -265,9 +266,12 @@ def _submit_dryrun(self, app: AppDef, cfg: DockerOpts) -> AppDryRunInfo[DockerJo rank0_env="TORCHX_RANK0_HOST", ) replica_role = values.apply(role) - # trim app_id and role name in case name is longer than 64 letters. Assume replica_id is less than 10_000. - name = f"{app_id[-30:]}-{role.name[:30]}-{replica_id}" - + # trim app_id and role name in case name is longer than 64 letters. Assume replica_id is less than 10_000. Remove invalid prefixes (https://github.com/moby/moby/blob/master/daemon/names/names.go#L6). + name = re.sub( + r"^[^a-zA-Z0-9]+", + "", + f"{app_id[-30:]}-{role.name[:30]}-{replica_id}", + ) env = default_env.copy() if replica_role.env: env.update(replica_role.env) diff --git a/torchx/schedulers/test/docker_scheduler_test.py b/torchx/schedulers/test/docker_scheduler_test.py index d5c9b3073..5b684f3a1 100644 --- a/torchx/schedulers/test/docker_scheduler_test.py +++ b/torchx/schedulers/test/docker_scheduler_test.py @@ -221,13 +221,15 @@ def test_long_hostname(self) -> None: for role in app.roles: role.name = "ethology_explore_magic_calliope_divisive_whirl_dealt_lotus_oncology_facet_deerskin_blum_elective_spill_trammel_trainer" with patch("torchx.schedulers.docker_scheduler.make_unique") as make_unique_ctx: - make_unique_ctx.return_value = "ethology_explore_magic_calliope_divisive_whirl_dealt_lotus_oncology_facet_deerskin_blum_elective_spill_trammel_12345" + make_unique_ctx.return_value = "ethology_explore_magic_calliope_divisive_whirl_dealt_lotus_oncology_facet_deerskin__.-_elective_spill_trammel_1234" info = self.scheduler.submit_dryrun(app, DockerOpts()) for container in info.request.containers: assert "name" in container.kwargs name = container.kwargs["name"] assert isinstance(name, str) assert len(name) < 65 + # Assert match container name rules https://github.com/moby/moby/blob/master/daemon/names/names.go#L6 + self.assertRegex(name, r"[a-zA-Z0-9][a-zA-Z0-9_.-]") if has_docker():