Repository: mlflow/mlflow

Issue:
[BUG] Docker build context is still created even when skipping image build
### Issues Policy acknowledgement

- [X] I have read and agree to submit bug reports in accordance with the [issues policy](https://www.github.com/mlflow/mlflow/blob/master/ISSUE_POLICY.md)

### Willingness to contribute

Yes. I can contribute a fix for this bug independently.

### MLflow version

- Client: 1.30.0


### System information

- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: Linux Ubuntu 20.04
- **Python version**: 3.9
- **yarn version, if running the dev UI**: N/A


### Describe the problem

When using a docker container environment the `mlflow run` command still creates the docker build context even though it isn't needed/used. If your project contains lots of local files such as a Python Virtual env or datasets it can take several minutes to build this context before even starting the run.

I believe: https://github.com/mlflow/mlflow/blob/v1.30.0/mlflow/projects/docker.py#L79 should be moved to below line 89.

### Tracking information

_No response_

### Code to reproduce issue

```sh
mlflow run . --skip-image-build
```

### Stack trace

N/A

### Other info / logs

_No response_

### What component(s) does this bug affect?

- [ ] `area/artifacts`: Artifact stores and artifact logging
- [ ] `area/build`: Build and test infrastructure for MLflow
- [ ] `area/docs`: MLflow documentation pages
- [ ] `area/examples`: Example code
- [ ] `area/model-registry`: Model Registry service, APIs, and the fluent client calls for Model Registry
- [ ] `area/models`: MLmodel format, model serialization/deserialization, flavors
- [ ] `area/pipelines`: Pipelines, Pipeline APIs, Pipeline configs, Pipeline Templates
- [X] `area/projects`: MLproject format, project running backends
- [ ] `area/scoring`: MLflow Model server, model deployment tools, Spark UDFs
- [ ] `area/server-infra`: MLflow Tracking server backend
- [ ] `area/tracking`: Tracking Service, tracking client APIs, autologging

### What interface(s) does this bug affect?

- [ ] `area/uiux`: Front-end, user experience, plotting, JavaScript, JavaScript dev server
- [X] `area/docker`: Docker use across MLflow's components, such as MLflow Projects and MLflow Models
- [ ] `area/sqlalchemy`: Use of SQLAlchemy in the Tracking Service or Model Registry
- [ ] `area/windows`: Windows support

### What language(s) does this bug affect?

- [ ] `language/r`: R APIs and clients
- [ ] `language/java`: Java APIs and clients
- [ ] `language/new`: Proposals for new client languages

### What integration(s) does this bug affect?

- [ ] `integrations/azure`: Azure and Azure ML integrations
- [ ] `integrations/sagemaker`: SageMaker integrations
- [ ] `integrations/databricks`: Databricks integrations


Discussion:
This makes sense to change. Thank you for identifying that the .tar creation isn't needed (as it should already exist if one is using the skip build option). We'll look for your PR!

Resolving patch:
diff --git a/mlflow/projects/docker.py b/mlflow/projects/docker.py
--- a/mlflow/projects/docker.py
+++ b/mlflow/projects/docker.py
@@ -69,14 +69,6 @@ def build_docker_image(work_dir, repository_uri, base_image, run_id, build_image
     Build a docker image containing the project in `work_dir`, using the base image.
     """
     image_uri = _get_docker_image_uri(repository_uri=repository_uri, work_dir=work_dir)
-    dockerfile = (
-        "FROM {imagename}\n COPY {build_context_path}/ {workdir}\n WORKDIR {workdir}\n"
-    ).format(
-        imagename=base_image,
-        build_context_path=_PROJECT_TAR_ARCHIVE_NAME,
-        workdir=MLFLOW_DOCKER_WORKDIR_PATH,
-    )
-    build_ctx_path = _create_docker_build_ctx(work_dir, dockerfile)
     client = docker.from_env()
     if not build_image:
         if not client.images.list(name=base_image):
@@ -87,6 +79,14 @@ def build_docker_image(work_dir, repository_uri, base_image, run_id, build_image
             image = client.images.get(base_image)
         image_uri = base_image
     else:
+        dockerfile = (
+            "FROM {imagename}\n COPY {build_context_path}/ {workdir}\n WORKDIR {workdir}\n"
+        ).format(
+            imagename=base_image,
+            build_context_path=_PROJECT_TAR_ARCHIVE_NAME,
+            workdir=MLFLOW_DOCKER_WORKDIR_PATH,
+        )
+        build_ctx_path = _create_docker_build_ctx(work_dir, dockerfile)
         with open(build_ctx_path, "rb") as docker_build_ctx:
             _logger.info("=== Building docker image %s ===", image_uri)
             image, _ = client.images.build(


Test patch: