Skip to content

Processing job in local mode should detect and default to the provided image ENTRYPOINT #3422

Open
@AndreiVoinovTR

Description

@AndreiVoinovTR

When running a processing job that:

  • uses a custom image
  • takes some 'arguments'
  • and being run in a local mode

..the user is forced to always pass an 'entrypoint' argument to the Processor, although the image itself might have a default ENTRYPOINT defined.

On the other hand, if the same configuration is run as a remote job, it works as expected - i.e. when an 'entrypoint' argument is not provided to the Processor, the job uses the one defined in the image itself.

To reproduce
One would need base/custom docker image with ENTRYPOINT defined.

See the snippet below:

from sagemaker.processing import Processor

processor = Processor(
    image_uri='NNN.dkr.ecr.us-east-1.amazonaws.com/custom-image',
    role="arn:aws:iam::NNN:role/service-role/some-role",
    base_job_name="preprocess",
    instance_count=1,
    instance_type='local',
    # entrypoint = ["python3", "preprocess.py"],
)

processor.run(
    arguments=[
        "--input-path", "my-input",
        "--output-path", "my-output"
    ]
)

The code above, with the line entrypoint = ["python3", "preprocess.py"] commented out, fails with the following exception:

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/local/image.py:757, in _SageMakerContainer._create_docker_host(self, host, environment, optml_subdirs, command, volumes)
    755         host_config["entrypoint"] = self.container_entrypoint
    756     if self.container_arguments:
--> 757         host_config["entrypoint"] = host_config["entrypoint"] + self.container_arguments
    759 # for GPU support pass in nvidia as the runtime, this is equivalent
    760 # to setting --runtime=nvidia in the docker commandline.
    761 if self.instance_type == "local_gpu":

KeyError: 'entrypoint'

Expected behavior
The job should not need an 'entrypoint' argument specified, it should default to the entrypoint defined inside the docker image.

Screenshots or logs
Full exception stack:

INFO:sagemaker:Creating processing-job with name preprocess-2022-10-18-09-46-41-207
INFO:sagemaker.local.local_session:Starting processing job
INFO:botocore.credentials:Found credentials in shared credentials file: ~/.aws/credentials

Job Name:  preprocess-2022-10-18-09-46-41-207
Inputs:  []
Outputs:  []
WARNING:sagemaker.local.image:Using the short-lived AWS credentials found in session. They might expire while running.

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In [4], line 12
      1 from sagemaker.processing import Processor
      3 processor = Processor(
      4     image_uri='451191978663.dkr.ecr.us-east-1.amazonaws.com/a204311-ml-workspace-modelopsextehvui-use1:test_experiment_123-preprocess',
      5     role="arn:aws:iam::451191978663:role/service-role/a204311-ml-workspace-ModelOpsExtEhVUI-prod-use1",
   (...)
      9     # entrypoint = ["python3", "preprocess.py"],
     10 )
---> 12 processor.run(
     13     arguments=[
     14         "--input-path", "my-input",
     15         "--output-path", "my-output"
     16     ]
     17 )

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/workflow/pipeline_context.py:248, in runnable_by_pipeline.<locals>.wrapper(*args, **kwargs)
    245     run_func(*args, **kwargs)
    246     return self_instance.sagemaker_session.context
--> 248 return run_func(*args, **kwargs)

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/processing.py:203, in Processor.run(self, inputs, outputs, arguments, wait, logs, job_name, experiment_config, kms_key)
    190     raise ValueError(
    191         """Logs can only be shown if wait is set to True.
    192         Please either set wait to True or set logs to False."""
    193     )
    195 normalized_inputs, normalized_outputs = self._normalize_args(
    196     job_name=job_name,
    197     arguments=arguments,
   (...)
    200     outputs=outputs,
    201 )
--> 203 self.latest_job = ProcessingJob.start_new(
    204     processor=self,
    205     inputs=normalized_inputs,
    206     outputs=normalized_outputs,
    207     experiment_config=experiment_config,
    208 )
    209 self.jobs.append(self.latest_job)
    210 if wait:

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/processing.py:796, in ProcessingJob.start_new(cls, processor, inputs, outputs, experiment_config)
    793 print("Outputs: ", process_args["output_config"]["Outputs"])
    795 # Call sagemaker_session.process using the arguments dictionary.
--> 796 processor.sagemaker_session.process(**process_args)
    798 return cls(
    799     processor.sagemaker_session,
    800     processor._current_job_name,
   (...)
    803     processor.output_kms_key,
    804 )

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/session.py:956, in Session.process(self, inputs, output_config, job_name, resources, stopping_condition, app_specification, environment, network_config, role_arn, tags, experiment_config)
    953     LOGGER.debug("process request: %s", json.dumps(request, indent=4))
    954     self.sagemaker_client.create_processing_job(**request)
--> 956 self._intercept_create_request(process_request, submit, self.process.__name__)

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/session.py:4317, in Session._intercept_create_request(self, request, create, func_name)
   4304 def _intercept_create_request(
   4305     self, request: typing.Dict, create, func_name: str = None  # pylint: disable=unused-argument
   4306 ):
   4307     """This function intercepts the create job request.
   4308 
   4309     PipelineSession inherits this Session class and will override
   (...)
   4315         func_name (str): the name of the function needed intercepting
   4316     """
-> 4317     return create(request)

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/session.py:954, in Session.process.<locals>.submit(request)
    952 LOGGER.info("Creating processing-job with name %s", job_name)
    953 LOGGER.debug("process request: %s", json.dumps(request, indent=4))
--> 954 self.sagemaker_client.create_processing_job(**request)

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/local/local_session.py:128, in LocalSagemakerClient.create_processing_job(self, ProcessingJobName, AppSpecification, ProcessingResources, Environment, ProcessingInputs, ProcessingOutputConfig, **kwargs)
    126 processing_job = _LocalProcessingJob(container)
    127 logger.info("Starting processing job")
--> 128 processing_job.start(
    129     ProcessingInputs, ProcessingOutputConfig, Environment, ProcessingJobName
    130 )
    132 LocalSagemakerClient._processing_jobs[ProcessingJobName] = processing_job

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/local/entities.py:140, in _LocalProcessingJob.start(self, processing_inputs, processing_output_config, environment, processing_job_name)
    137 self.processing_output_config = processing_output_config
    138 self.environment = environment
--> 140 self.container.process(
    141     processing_inputs, processing_output_config, environment, processing_job_name
    142 )
    144 self.end_time = datetime.datetime.now()
    145 self.state = self._COMPLETED

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/local/image.py:153, in _SageMakerContainer.process(self, processing_inputs, processing_output_config, environment, processing_job_name)
    144     _create_processing_config_file_directories(self.container_root, host)
    145     self.write_processing_config_files(
    146         host,
    147         environment,
   (...)
    150         processing_job_name,
    151     )
--> 153 self._generate_compose_file(
    154     "process", additional_volumes=volumes, additional_env_vars=environment
    155 )
    156 compose_command = self._compose()
    158 if _ecr_login_if_needed(self.sagemaker_session.boto_session, self.image):

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/local/image.py:671, in _SageMakerContainer._generate_compose_file(self, command, additional_volumes, additional_env_vars)
    668 elif command == "process":
    669     optml_dirs = {"output", "config"}
--> 671 services = {
    672     h: self._create_docker_host(h, environment, optml_dirs, command, additional_volumes)
    673     for h in self.hosts
    674 }
    676 content = {
    677     # Use version 2.3 as a minimum so that we can specify the runtime
    678     "version": "2.3",
    679     "services": services,
    680     "networks": {"sagemaker-local": {"name": "sagemaker-local"}},
    681 }
    683 docker_compose_path = os.path.join(self.container_root, DOCKER_COMPOSE_FILENAME)

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/local/image.py:672, in <dictcomp>(.0)
    668 elif command == "process":
    669     optml_dirs = {"output", "config"}
    671 services = {
--> 672     h: self._create_docker_host(h, environment, optml_dirs, command, additional_volumes)
    673     for h in self.hosts
    674 }
    676 content = {
    677     # Use version 2.3 as a minimum so that we can specify the runtime
    678     "version": "2.3",
    679     "services": services,
    680     "networks": {"sagemaker-local": {"name": "sagemaker-local"}},
    681 }
    683 docker_compose_path = os.path.join(self.container_root, DOCKER_COMPOSE_FILENAME)

File ~/work/temp/labs-test_project/.venv/lib/python3.8/site-packages/sagemaker/local/image.py:757, in _SageMakerContainer._create_docker_host(self, host, environment, optml_subdirs, command, volumes)
    755         host_config["entrypoint"] = self.container_entrypoint
    756     if self.container_arguments:
--> 757         host_config["entrypoint"] = host_config["entrypoint"] + self.container_arguments
    759 # for GPU support pass in nvidia as the runtime, this is equivalent
    760 # to setting --runtime=nvidia in the docker commandline.
    761 if self.instance_type == "local_gpu":

KeyError: 'entrypoint'

System information
A description of your system. Please provide:

  • SageMaker Python SDK version: 2.112.2
  • Framework name (eg. PyTorch) or algorithm (eg. KMeans): Processor
  • Framework version: -
  • Python version: 3.8
  • CPU or GPU: -
  • Custom Docker image (Y/N): Y

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions