Serverless Deployment on Azure Functions

Hi guys,

I have written a quick guide on deploying to Microsoft Azure Functions, their serverless architecture (Microsoft’s equivalent of AWS Lambda). I made a PR to the course website and just waiting for it to be merged:

If you guys want to check it out now, I’ve also put it in my blog post:

The blog post has got a bit more of my personal rants and opinion but the instructions are basically the same.

Hope you guys will find this handy.

Thanks,
Nobita

3 Likes

Hi @nobita, thanks for this, just reading now and this is fantastic. How would you compare this to other deployment solutions that Azure offers, like Azure ML service (e.g via ACI or AKS, as in https://docs.microsoft.com/en-us/azure/machine-learning/service/how-to-deploy-and-where#deploy)? Thanks!

Thanks for the link @davidefiocco and very happy that you enjoyed the quick guide (it’s my first attempt to contribute here). I haven’t tried ACI or AKS yet, though I did try some of Google’s ML Engine offerings. I briefly compared these “ML PaaS” solutions in a previous blog post in case you find it helpful.

I think these ML PaaS are the way to go for most people as they add so much more ML-targeted value-added-services on top of pure deployment (like hyperparameter tuning, tracking experiment results, etc, basically the whole pipeline), in addition to the usual PaaS advantages.

Unless the person needs something very specific, and has the skills to build all the tools needed and can also spare the time required (a rare occasion), otherwise these “batteries included” solutions are probably good enough to get things started. Even if the person has a team of devs who can help, the person will get a better idea of what is ultimately needed by using these off the shelve products first.

Cheers,
Nobita

1 Like

hey @nobita
I just tried your tutorial today, but I´ve got some issue while building the docker image, so I cant continue to checkout my model inside an Azure Function :frowning:

This is the main error message:

gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tmp/pip-install-urgn5g_1/Bottleneck/.eggs/numpy-1.16.3-py3.6-linux-x86_64.egg/numpy/core/include -I/usr/local/include/python3.6m -c bottleneck/src/reduce.c -o build/temp.linux-x86_64-3.6/bottleneck/src/reduce.o -O2
  unable to execute 'gcc': No such file or directory
  error: command 'gcc' failed with exit status 1
  ----------------------------------------
  ERROR: Failed building wheel for Bottleneck

I can see that you had used pipenv --python 3.6 to create the virtual environment in your blogpost, while the official documentation describes to do it like this:

python -m venv .env
source .env/bin/activate

So maybe I have some dependency problems ?:frowning:

If you have any good advice for me, I would be happy

Thank you


Here is the complete log, if you can make more sense of it:

Collecting dataclasses; python_version < "3.7" (from fastai==1.0.52->-r requirements.txt (line 9))
  Downloading https://files.pythonhosted.org/packages/26/2f/1095cdc2868052dd1e64520f7c0d5c8c550ad297e944e641dbf1ffbb9a5d/dataclasses-0.6-py3-none-any.whl
Requirement already satisfied: setuptools in /usr/local/lib/python3.6/site-packages (from jsonschema==3.0.1->-r requirements.txt (line 12)) (41.0.1)
Building wheels for collected packages: Bottleneck, nvidia-ml-py3, pynvx, pyrsistent, PyYAML
  Building wheel for Bottleneck (setup.py): started
  Building wheel for Bottleneck (setup.py): finished with status 'error'
  ERROR: Complete output from command /usr/local/bin/python -u -c 'import setuptools, tokenize;__file__='"'"'/tmp/pip-install-urgn5g_1/Bottleneck/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-dph48hsw --python-tag cp36:
  ERROR: No Bottleneck unit testing available.
  running bdist_wheel
  running build
  running build_py
  creating build
  creating build/lib.linux-x86_64-3.6
  creating build/lib.linux-x86_64-3.6/bottleneck
  copying bottleneck/__init__.py -> build/lib.linux-x86_64-3.6/bottleneck
  copying bottleneck/version.py -> build/lib.linux-x86_64-3.6/bottleneck
  creating build/lib.linux-x86_64-3.6/bottleneck/benchmark
  copying bottleneck/benchmark/bench_detailed.py -> build/lib.linux-x86_64-3.6/bottleneck/benchmark
  copying bottleneck/benchmark/autotimeit.py -> build/lib.linux-x86_64-3.6/bottleneck/benchmark
  copying bottleneck/benchmark/bench.py -> build/lib.linux-x86_64-3.6/bottleneck/benchmark
  copying bottleneck/benchmark/__init__.py -> build/lib.linux-x86_64-3.6/bottleneck/benchmark
  creating build/lib.linux-x86_64-3.6/bottleneck/tests
  copying bottleneck/tests/move_test.py -> build/lib.linux-x86_64-3.6/bottleneck/tests
  copying bottleneck/tests/nonreduce_axis_test.py -> build/lib.linux-x86_64-3.6/bottleneck/tests
  copying bottleneck/tests/scalar_input_test.py -> build/lib.linux-x86_64-3.6/bottleneck/tests
  copying bottleneck/tests/nonreduce_test.py -> build/lib.linux-x86_64-3.6/bottleneck/tests
  copying bottleneck/tests/input_modifcation_test.py -> build/lib.linux-x86_64-3.6/bottleneck/tests
  copying bottleneck/tests/__init__.py -> build/lib.linux-x86_64-3.6/bottleneck/tests
  copying bottleneck/tests/list_input_test.py -> build/lib.linux-x86_64-3.6/bottleneck/tests
  copying bottleneck/tests/util.py -> build/lib.linux-x86_64-3.6/bottleneck/tests
  copying bottleneck/tests/reduce_test.py -> build/lib.linux-x86_64-3.6/bottleneck/tests
  creating build/lib.linux-x86_64-3.6/bottleneck/src
  copying bottleneck/src/template.py -> build/lib.linux-x86_64-3.6/bottleneck/src
  copying bottleneck/src/__init__.py -> build/lib.linux-x86_64-3.6/bottleneck/src
  creating build/lib.linux-x86_64-3.6/bottleneck/slow
  copying bottleneck/slow/move.py -> build/lib.linux-x86_64-3.6/bottleneck/slow
  copying bottleneck/slow/reduce.py -> build/lib.linux-x86_64-3.6/bottleneck/slow
  copying bottleneck/slow/nonreduce_axis.py -> build/lib.linux-x86_64-3.6/bottleneck/slow
  copying bottleneck/slow/__init__.py -> build/lib.linux-x86_64-3.6/bottleneck/slow
  copying bottleneck/slow/nonreduce.py -> build/lib.linux-x86_64-3.6/bottleneck/slow
  copying bottleneck/LICENSE -> build/lib.linux-x86_64-3.6/bottleneck
  running build_ext
  building 'bottleneck.reduce' extension
  creating build/temp.linux-x86_64-3.6
  creating build/temp.linux-x86_64-3.6/bottleneck
  creating build/temp.linux-x86_64-3.6/bottleneck/src
  gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tmp/pip-install-urgn5g_1/Bottleneck/.eggs/numpy-1.16.3-py3.6-linux-x86_64.egg/numpy/core/include -I/usr/local/include/python3.6m -c bottleneck/src/reduce.c -o build/temp.linux-x86_64-3.6/bottleneck/src/reduce.o -O2
  unable to execute 'gcc': No such file or directory
  error: command 'gcc' failed with exit status 1
  ----------------------------------------
  ERROR: Failed building wheel for Bottleneck
  Running setup.py clean for Bottleneck
  Building wheel for nvidia-ml-py3 (setup.py): started
  Building wheel for nvidia-ml-py3 (setup.py): finished with status 'done'
  Stored in directory: /home/.cache/pip/wheels/e4/1d/06/640c93f5270d67d0247f30be91f232700d19023f9e66d735c7
  Building wheel for pynvx (setup.py): started
  Building wheel for pynvx (setup.py): finished with status 'error'
  Running setup.py clean for pynvx
  ERROR: Complete output from command /usr/local/bin/python -u -c 'import setuptools, tokenize;__file__='"'"'/tmp/pip-install-urgn5g_1/pynvx/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-eqcf2jb5 --python-tag cp36:
  ERROR: running bdist_wheel
  running build
  running build_py
  creating build
  creating build/lib.linux-x86_64-3.6
  creating build/lib.linux-x86_64-3.6/pynvx
  copying pynvx/pynvml.py -> build/lib.linux-x86_64-3.6/pynvx
  copying pynvx/__init__.py -> build/lib.linux-x86_64-3.6/pynvx
  running build_ext
  Traceback (most recent call last):
    File "/tmp/pip-install-urgn5g_1/pynvx/setup.py", line 21, in run
      out = subprocess.check_output(['cmake', '--version'])
    File "/usr/local/lib/python3.6/subprocess.py", line 356, in check_output
      **kwargs).stdout
    File "/usr/local/lib/python3.6/subprocess.py", line 423, in run
      with Popen(*popenargs, **kwargs) as process:
    File "/usr/local/lib/python3.6/subprocess.py", line 729, in __init__
      restore_signals, start_new_session)
    File "/usr/local/lib/python3.6/subprocess.py", line 1364, in _execute_child
      raise child_exception_type(errno_num, err_msg, err_filename)
  FileNotFoundError: [Errno 2] No such file or directory: 'cmake': 'cmake'
  
  During handling of the above exception, another exception occurred:
  
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/tmp/pip-install-urgn5g_1/pynvx/setup.py", line 103, in <module>
      "Topic :: Software Development :: Libraries :: Python Modules",
    File "/usr/local/lib/python3.6/site-packages/setuptools/__init__.py", line 145, in setup
      return distutils.core.setup(**attrs)
    File "/usr/local/lib/python3.6/distutils/core.py", line 148, in setup
      dist.run_commands()
    File "/usr/local/lib/python3.6/distutils/dist.py", line 955, in run_commands
      self.run_command(cmd)
    File "/usr/local/lib/python3.6/distutils/dist.py", line 974, in run_command
      cmd_obj.run()
    File "/usr/local/lib/python3.6/site-packages/wheel/bdist_wheel.py", line 192, in run
      self.run_command('build')
    File "/usr/local/lib/python3.6/distutils/cmd.py", line 313, in run_command
      self.distribution.run_command(command)
    File "/usr/local/lib/python3.6/distutils/dist.py", line 974, in run_command
      cmd_obj.run()
    File "/usr/local/lib/python3.6/distutils/command/build.py", line 135, in run
      self.run_command(cmd_name)
    File "/usr/local/lib/python3.6/distutils/cmd.py", line 313, in run_command
      self.distribution.run_command(command)
    File "/usr/local/lib/python3.6/distutils/dist.py", line 974, in run_command
      cmd_obj.run()
    File "/tmp/pip-install-urgn5g_1/pynvx/setup.py", line 24, in run
      ", ".join(e.name for e in self.extensions))
  RuntimeError: CMake must be installed to build the following extensions: _pynvx
  ----------------------------------------
  ERROR: Failed building wheel for pynvx
  Building wheel for pyrsistent (setup.py): started
  Building wheel for pyrsistent (setup.py): finished with status 'done'
  Stored in directory: /home/.cache/pip/wheels/6b/b9/15/c8c6a1e095a370e8c3273e65a5c982e5cf355dde16d77502f5
  Building wheel for PyYAML (setup.py): started
  Building wheel for PyYAML (setup.py): finished with status 'done'
  Stored in directory: /home/.cache/pip/wheels/ad/56/bc/1522f864feb2a358ea6f1a92b4798d69ac783a28e80567a18b
Successfully built nvidia-ml-py3 pyrsistent PyYAML
Failed to build Bottleneck pynvx
Installing collected packages: attrs, soupsieve, beautifulsoup4, numpy, blis, Bottleneck, certifi, chardet, cycler, cymem, pyparsing, packaging, kiwisolver, python-dateutil, matplotlib, idna, urllib3, requests, torch, scipy, typing, PyYAML, numexpr, nvidia-ml-py3, Pillow, torchvision, dataclasses, fastprogress, pyrsistent, jsonschema, preshed, wasabi, plac, srsly, murmurhash, tqdm, thinc, spacy, pytz, pandas, fastai, pynvx
  Running setup.py install for Bottleneck: started
    Running setup.py install for Bottleneck: finished with status 'error'
    ERROR: Complete output from command /usr/local/bin/python -u -c 'import setuptools, tokenize;__file__='"'"'/tmp/pip-install-urgn5g_1/Bottleneck/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-po6osfra/install-record.txt --single-version-externally-managed --compile:
    ERROR: running install
    running build
    running build_py
    running build_ext
    building 'bottleneck.reduce' extension
    creating build/temp.linux-x86_64-3.6
    creating build/temp.linux-x86_64-3.6/bottleneck
    creating build/temp.linux-x86_64-3.6/bottleneck/src
    gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/usr/local/lib/python3.6/site-packages/numpy/core/include -I/usr/local/include/python3.6m -c bottleneck/src/reduce.c -o build/temp.linux-x86_64-3.6/bottleneck/src/reduce.o -O2
    unable to execute 'gcc': No such file or directory
    error: command 'gcc' failed with exit status 1
    ----------------------------------------
ERROR: Command "/usr/local/bin/python -u -c 'import setuptools, tokenize;__file__='"'"'/tmp/pip-install-urgn5g_1/Bottleneck/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-po6osfra/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-install-urgn5g_1/Bottleneck/
WARNING: You are using pip version 19.1, however version 19.1.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

Hi Jonas,

It’s failing while building Bottleneck which isn’t related to pipenv / venv, but suggest to me that it’s runing into problems with your env setup. Nonetheless, so does it work when you try to run with the venv method from https://course.fast.ai/deployment_azure_functions.html?

(I picked venv on the “official guide” to stick with python standard libraries, but on my blog I use pipenv as it’s my personal preferred approach)

If it still doesn’t work, then it’s probably related to your env setup. Note that I could only get the dependencies to compile under Ubuntu (and not under WSL Ubuntu if you are on Windows) and with Python 3.6 (as stated in the Requirements section).

Hi, Nobita Do you know why? When I try to run “func host start” and get below error, how to fix it? Thank you first!
“Python 3.6.x is required, and used in Azure Functions. You are using Python version Python 3.5.2. Please install Python 3.6, and use a virtual environment to switch to Python 3.6.”

Sorry I totally missed this earlier.

It looks like you need to use Python 3.6 rather than Python 3.5.