Repository: bentoml/BentoML

Issue:
Failure to containerize model if build-arg value contains multiple `=` characters
**Describe the bug**
Containerization fails due to unpacking issue when passing the `--build-arg` argument with value including multiple `=` characters.

In particular, the string split operation in [bento_service.containerize()](https://github.com/bentoml/BentoML/blob/d8ae9490a834e1aab371a2b69e937acb5c86f19d/bentoml/cli/bento_service.py#L384) fails to assign the resulting values to variables for cases when the input is split into >2 tokens.

**To Reproduce**
The BentoML fails to containerize the model when one wants to set the EXTRA_PIP_INSTALL_ARGS environment variable with argument-value pairs to be passed to `pip install`.

A scenario is the following:
One wants to specify an additional `--extra-index-url` pip argument to specify an internal PyPI server.

A simple example can be extracted from the `bentoml-quick-start-guide.ipynb`.

1. Register a new bento service. i.e. `IrisClassifier` for this scenario
2. Run `bentoml containerize IrisClassifier:latest -t iris-classifier --build-arg EXTRA_PIP_INSTALL_ARGS=--extra-index-url=https://myorgpypi.org/`

The failure occurs (see logs below) due to the splitting of the string `EXTRA_PIP_INSTALL_ARGS=--extra-index-url=https://myorgpypi.org/` as
``` python
[
  "EXTRA_PIP_INSTALL_ARGS",
  "--extra-index-url",
  "https://myorgpypi.org/"
]
```
instead of
``` python
[
  "EXTRA_PIP_INSTALL_ARGS",
  "--extra-index-url=https://myorgpypi.org/"
]
```

**Expected behavior**
With respect to the string split operation in [bento_service.containerize()](https://github.com/bentoml/BentoML/blob/d8ae9490a834e1aab371a2b69e937acb5c86f19d/bentoml/cli/bento_service.py#L384), the solution would be to force the split function to split only once: `key, value = arg.split("=", 1)`

**Screenshots/Logs**

When running: `bentoml containerize IrisClassifier:latest -t iris-classifier --build-arg EXTRA_PIP_INSTALL_ARGS=--extra-index-url=https://myorgpypi.org/`:

```
[2021-01-13 10:26:00,840] DEBUG - Setting debug mode: ON for current session
[2021-01-13 10:26:00,840] DEBUG - Creating local YataiService instance
[2021-01-13 10:26:01,087] DEBUG - Upgrading tables to the latest revision
[2021-01-13 10:26:02,595] INFO - Getting latest version IrisClassifier:20210108154220_FD6FEA
Found Bento: /home/luca/bentoml/repository/IrisClassifier/20210108154220_FD6FEA
Image version not specified, using version parsed from BentoService: '20210108154220_FD6FEA'
Traceback (most recent call last):
  File "/home/luca/PycharmProjects/bentoProject/.venv/bin/bentoml", line 8, in <module>
    sys.exit(cli())
  File "/home/luca/PycharmProjects/bentoProject/.venv/lib/python3.7/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/home/luca/PycharmProjects/bentoProject/.venv/lib/python3.7/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/home/luca/PycharmProjects/bentoProject/.venv/lib/python3.7/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/luca/PycharmProjects/bentoProject/.venv/lib/python3.7/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/luca/PycharmProjects/bentoProject/.venv/lib/python3.7/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/home/luca/PycharmProjects/bentoProject/.venv/lib/python3.7/site-packages/bentoml/cli/click_utils.py", line 138, in wrapper
    return func(*args, **kwargs)
  File "/home/luca/PycharmProjects/bentoProject/.venv/lib/python3.7/site-packages/bentoml/cli/click_utils.py", line 115, in wrapper
    return_value = func(*args, **kwargs)
  File "/home/luca/PycharmProjects/bentoProject/.venv/lib/python3.7/site-packages/bentoml/cli/click_utils.py", line 99, in wrapper
    return func(*args, **kwargs)
  File "/home/luca/PycharmProjects/bentoProject/.venv/lib/python3.7/site-packages/bentoml/cli/bento_service.py", line 409, in containerize
    key, value = arg.split("=")
ValueError: too many values to unpack (expected 2)
```

**Environment:**
 - OS: Ubuntu 18.04.4
 - Python Version: Python 3.7.9
 - BentoML Version: BentoML-0.10.1


**Additional context**
No additional context



Discussion:
@lucascott Thank you for reporting.  I will work on fixing it

Resolving patch:
diff --git a/bentoml/cli/bento_service.py b/bentoml/cli/bento_service.py
--- a/bentoml/cli/bento_service.py
+++ b/bentoml/cli/bento_service.py
@@ -381,7 +381,7 @@ def containerize(bento, push, tag, build_arg, yatai_url):
         docker_build_args = {}
         if build_arg:
             for arg in build_arg:
-                key, value = arg.split("=")
+                key, value = arg.split("=", 1)
                 docker_build_args[key] = value
         if yatai_url is not None:
             spinner_message = f'Sending containerize RPC to YataiService at {yatai_url}'
diff --git a/bentoml/yatai/yatai_service_impl.py b/bentoml/yatai/yatai_service_impl.py
--- a/bentoml/yatai/yatai_service_impl.py
+++ b/bentoml/yatai/yatai_service_impl.py
@@ -500,7 +500,9 @@ def ContainerizeBento(self, request, context=None):
                     safe_retrieve(bento_service_bundle_path, temp_bundle_path)
                     try:
                         docker_client.images.build(
-                            path=temp_bundle_path, tag=tag, buildargs=request.build_args
+                            path=temp_bundle_path,
+                            tag=tag,
+                            buildargs=dict(request.build_args),
                         )
                     except (docker.errors.APIError, docker.errors.BuildError) as error:
                         logger.error(f'Encounter container building issue: {error}')


Test patch:
diff --git a/tests/integration/yatai_server/test_containerize.py b/tests/integration/yatai_server/test_containerize.py
--- a/tests/integration/yatai_server/test_containerize.py
+++ b/tests/integration/yatai_server/test_containerize.py
@@ -1,4 +1,5 @@
 import logging
+import subprocess
 
 from bentoml.yatai.client import get_yatai_client
 from tests.bento_service_examples.example_bento_service import ExampleBentoService
@@ -16,3 +17,27 @@ def test_yatai_server_containerize_without_push():
     tag = 'mytag'
     built_tag = yc.repository.containerize(bento=f'{svc.name}:{svc.version}', tag=tag)
     assert built_tag == f'{tag}:{svc.version}'
+
+
+def test_yatai_server_containerize_from_cli():
+    svc = ExampleBentoService()
+    svc.pack('model', [1, 2, 3])
+    logger.info('Saving bento service to local yatai server')
+    svc.save()
+    bento_tag = f'{svc.name}:{svc.version}'
+    tag = 'mytagfoo'
+
+    command = [
+        'bentoml',
+        'containerize',
+        bento_tag,
+        '--build-arg',
+        'EXTRA_PIP_INSTALL_ARGS=--extra-index-url=https://pypi.org',
+        '-t',
+        tag,
+    ]
+    docker_proc = subprocess.Popen(
+        command, stdout=subprocess.PIPE, stderr=subprocess.PIPE
+    )
+    stdout = docker_proc.stdout.read().decode('utf-8')
+    assert f'{tag}:{svc.version}' in stdout, 'Failed to build container'