AWS Lambda with Docker – revisited

There are various ways to leverage docker to develop AWS lambda serverless functions. One recent method is to deploy Python Lambda functions with container images (as specified here).

Another method is to develop the Lambda package from within an Amazon Linux docker container and then upload it to AWS Lambda (more details here). A summary of how to do this is described below and will work for any platform where you can install Docker.

Open a command prompt and type:

docker pull lambci/lambda

next, type:

docker run -it lambci/lambda:build-python3.8 bash

This will install the environment to run Python 3.8 code and open a shell prompt so you can start working. The first thing recommended to do when getting the bash prompt is yum update

when you exit the shell, you can always re-enter by typing:

docker start -i container_name

(replace container_name with the container name of given to the image named lambci/lambda:build-python3.8, which can be seen via docker ps -a)

Linux on Windows 10 via Docker

Wanting to run Linux command line under windows usually brings you to one of two options:

  1. Install WSL (Windows Subsystem for Linux) – the main advantage here is performance optimizations made by Microsoft to take the most advantage of the hardware and OS infrastructure.
  2. Install Docker for Windows 10 and then create a Linux container which you can run and get the command line prompt from

There are other options such as running a full graphical virtual machine like VirtualBox, VMWare and the like, but our focus will be getting a quick Linux command line prompt from Windows.

My personal preference is using option 2, mainly due to it being easy to install and the ability to easily create multiple sandboxed instances and easily use them for different purposes.

The following describes how to install the latest Ubuntu version and run it as a docker container.

  1. If you haven’t already done so, install Docker for Windows
  2. open a command prompt and type:
    docker pull ubuntu
  3. next, type:
    docker images
    copy the image id of the repository named ubuntu
  4. suppose the image id of the repository you copied was f6a191f19b5f, type:
    docker run -it --name=ubuntu-container f6a191f19b5f /bin/sh
  5. that’s it, you have the root prompt on the latest Ubuntu running on your Windows system!
  6. After you exit the ubuntu container, you can always enter it again by typing from the command prompt:
    docker start -i ubuntu-container

Training “cat or dog” on Windows without GPU

I was curious to see how much slower the training of chapter 1 of fast.ai would be on my GPU-less home desktop vs. a basic cloud GPU servers. The first issue was to get the code running after installing torch, torchvision and fastai modules. Apparently, there are some code modifications to make to get things running on my local system – I’ve summarized them here:

from fastai.vision.all import *

# To fix: Can't get attribute 'is_cat' on <module '__main__' (built-in)>
# https://stackoverflow.com/questions/41385708/multiprocessing-example-giving-attributeerror
from iscat import *

path = untar_data(URLs.PETS)/'images'

# added num_workers=0 to avoid:
# AttributeError: '_FakeLoader' object has no attribute 'noops'
# https://github.com/fastai/fastai/issues/3047

dls = ImageDataLoaders.from_name_func(
    path, get_image_files(path), valid_pct=0.2, seed=42,
    label_func=is_cat, item_tfms=Resize(224), num_workers=0 )

learn = cnn_learner(dls, resnet34, metrics=error_rate)
learn.fine_tune(1)

And the results ?

Well, the dataset used to train the network to distinguish between cats and dogs takes a decent GPU around 20 seconds to complete for each epoch.

Giving this task to my CPU took around 40 minutes per epoch.

Now you know why a GPU is highly recommended for machine learning, at least until someone will discover a more efficient way to do it (like this?)

cannot import name ‘mobilenet_v2’ from ‘torchvision.models’

This was the error I received when trying to import fastbook to study the excellent fast.ai course.

I had Python 3.9.1 installed and used pip to install the latest versions of torch, torchvision, and fastai

To spare the reader from boring war stories, here’s the bottom line:

  • Download the latest version of torchvision for your platform from https://download.pytorch.org/whl/torch_stable.html
    (for example cpu/torchvision-0.8.2%2Bcpu-cp39-cp39-win_amd64.whl is torchvision 0.8.2 for cpu on Windows for version 3.9 of C Python)
  • run pip install torchvision-0.8.2+cpu-cp39-cp39-win_amd64.whl (assuming this is the version you downloaded)
  • run pip install fastai --upgrade

You should now be able to import fastbook

Compiling PHP 7.3 with MySQL support for AWS Lambda

This is probably easier to do for PHP 7.4, but I wanted PHP 7.3 to make sure everything is compatible with existing code. The code below assumes you are doing this in an interactive shell in a Docker container build for creating binaries for AWS Lambda. Doing this is explained here

First, install the necessary tools to build PHP

$ yum update -y
$ yum install autoconf bison gcc gcc-c++ libcurl-devel libxml2-devel -y

Next, build the SSL version required for PHP 7.3 build

$ curl -sL http://www.openssl.org/source/openssl-1.0.1k.tar.gz | tar -xvz
$ cd openssl-1.0.1k
$ ./config & make & make install

Then download and build PHP 7.3, and configure with all the support for accessing MySQL databases

$ cd ..
$ curl -sL https://github.com/php/php-src/archive/php-7.3.0.tar.gz | tar -xvz
$ cd php-src-php-7.3.0
$ ./buildconf --force
$ /configure --prefix=/home/ec2-user/php-7-bin/ --with-openssl=/usr/local/ssl --with-curl --without-libzip --with-zlib --enable-zip --with-pdo-mysql --with-mysqli=mysqlnd
$ make install

Finally, check that the MySQL modules are there:

$ /home/ec2-user/php-7-bin/bin/php -m

Backing up AWS lambda functions

There might be a built-in method to do so, but I haven’t found one. I wanted to download packages of all the lambda files I have in AWS and ended up creating a script to do it.

Of course you should replace the –region parameter with the AWS region you run your AWS lambda functions and the –profile parameter with the appropriate AWS lambda profile in your ~/.aws/credentials file (the correct way would have been to give those as parameters to the bash script but this will be left as an exercise to the reader 😉

Feel free to copy. Don’t forget to chmod u+x …

#!/bin/bash

# Get all the function names
list=`aws lambda list-functions --region us-west-2 | jq -r .Functions[].FunctionName | perl -pe 's/\n/ /g'`

# For each lambda function, get the function's download url and download it
for val in $list; do
    url=`aws lambda get-function --region us-west-2 --function-name $val --profile amnon | jq -r .Code.Location`
    shortname=`echo $url | perl -pe's/^.+\/(.+?)-[\w]{8}.+/\1.zip/g'`
    echo $shortname
    wget -nv $url -O $shortname
done

Duplicated log lines using Python in AWS Lambda

The short version:

logname = 'processing'
formatter = logging.Formatter(fmt='%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
handler = logging.StreamHandler()
handler.setFormatter(formatter)
logger = logging.getLogger(logname)
logger.setLevel(logging.DEBUG)
logger.handlers = [] # === Make sure to add this line
logger.addHandler(handler)
logger.propagate = False # === and this line

For details, check out this link

Standard C++ libraries on AWS Lambda

While attempting to compile a test sample together a library I needed, I received the following

/usr/bin/ld: cannot find -lstdc++

installing the following solved the issue. I didn’t even check if both installations are necessary – if you have the curiosity to dig further then send your conclusions, but all I wanted was a solution to the problem at hand, and here it is:

yum install libstdc++-devel
yum install libstdc++-static