Running the SAM CLI on Linux

Tags: , ,

I find the SAM (Serverless Application Model) CLI extremely frustrating to use on Linux, starting with installation. But this week I learned two things that simplify both installation and operation. I’m passing them on in the hopes that they’ll be useful to you as well. Happy Friday!

Homebrew isn’t required

For me, the most annoying thing about the documented process for installing SAM on Linux is the need for Homebrew. It’s not just that I already have a package manager. It’s not just that I have to install Homebrew by running a shell script downloaded from Github. The real annoyance for me is that the installation doesn’t work!

This is because I already have Python 3 installed on my Linux system. Which means that Homebrew won’t install its own copy (it does, however, install a copy of Python 3.7 as a private dependency of the SAM executable). Which means that when I try to build my Python Lambda with the SAM CLI, I get messages like “Binary validation failed for python” as it checks to see if the system-installed version matches the project’s runtime specification.

I was ranting about this, and my friend Jason responded with “you know that you can just install it with pip, don’t you?” Well, no, because I assumed that the SAM team wouldn’t make us jump through Homebrew hoops if they didn’t need dependencies that weren’t satisfied by a typical developer’s Linux install. Turns out I was wrong.

pip3 install aws-sam-cli

There are some caveats. First is that you have to have a recent version of Python 3 already installed. Based on the Homebrew dependency, I’m guessing that 3.7 would be optimal, but I’ve been running on 3.6.9 with no problems.

Build in a container

One of the problems with bypassing Homebrew is that the sam build command looks for runtime dependencies on your host operating system, and will fail if it doesn’t find them. However, there’s a simple work-around:

sam build --use-container

The only documentation for --use-container says this:

If your functions depend on packages that have natively compiled dependencies, use this flag to build your function inside an AWS Lambda-like Docker container.

Assuming that you noticed this at all, you probably ignored it as irrelevant to your build. What made me take a second look was that the README for a SAM-generated Python application showed it as the recommended build command.

The good news is that it works: all of the necessary dependencies are in the container. And your project only depends on the container during the build: once it’s done, you can deploy just using the command-line tool.

The bad news is that the build now needs a 2 GB Docker image (more-or-less, depending on Lambda runtime), so you’ll need a fast Internet connection or lots of patience. Fortunately, Docker caches this image, so you don’t need to download it for every build.

And that download is worth it to me to avoid Homebrew.