<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: James Hamann</title>
    <description>The latest articles on DEV Community by James Hamann (@jameshamann).</description>
    <link>https://dev.to/jameshamann</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F226334%2Ff0a09c48-ff3e-4fb5-bd4b-a2c793f68eda.jpeg</url>
      <title>DEV Community: James Hamann</title>
      <link>https://dev.to/jameshamann</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jameshamann"/>
    <language>en</language>
    <item>
      <title>AWS SAM and Ruby</title>
      <dc:creator>James Hamann</dc:creator>
      <pubDate>Tue, 10 Sep 2019 09:31:30 +0000</pubDate>
      <link>https://dev.to/jameshamann/what-is-aws-sam-1cmn</link>
      <guid>https://dev.to/jameshamann/what-is-aws-sam-1cmn</guid>
      <description>&lt;p&gt;AWS SAM stands for Serverless Application Model and serves as a framework to build serverless apps on AWS. This is a collection of Lambda functions and other AWS resources that come together to form an app.&lt;/p&gt;

&lt;p&gt;Whilst you are able to upload a lambda function and use the lambda console exclusively for simple apps, SAM offers a standardised template and process for developing, building and deploying apps.&lt;/p&gt;

&lt;p&gt;I moved away from using just Lambda when I found myself having to bundle and build my ruby function in a docker container using the same image as Lambda uses to ensure it was compatible. It proved a pain as the complexity of the project grew. SAM offered a simpler build and deployment solution, as well as providing a CLI which helped with developing locally.&lt;/p&gt;

&lt;h4&gt;
  
  
  Requirements
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;AWS Account&lt;/li&gt;
&lt;li&gt;AWS CLI&lt;/li&gt;
&lt;li&gt;Basic experience with the command line&lt;/li&gt;
&lt;li&gt;Basic experience with ruby&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Postman (Not strictly required but helps speed up development)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Getting started
&lt;/h4&gt;

&lt;p&gt;First of all, we need to install AWS SAM CLI. I’ll be using Homebrew, a package manager for macOS and linux, if you’re using windows head over here for other instructions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#bash&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;aws/tap
&lt;span class="o"&gt;[&lt;/span&gt;...]
&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once installed, we can use the SAM CLI to initialise our project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#bash&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;sam init — runtime ruby2.5 — name aws-sam-ruby
&lt;span class="o"&gt;[&lt;/span&gt;+] Initializing project structure...
Project generated: ./aws-sam-ruby
Steps you can take next within the project folder
&lt;span class="o"&gt;===================================================&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; Invoke Function: sam &lt;span class="nb"&gt;local &lt;/span&gt;invoke HelloWorldFunction &lt;span class="nt"&gt;--event&lt;/span&gt; event.json
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; Start API Gateway locally: sam &lt;span class="nb"&gt;local &lt;/span&gt;start-api
Read aws-sam-ruby/README.md &lt;span class="k"&gt;for &lt;/span&gt;further instructions
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; Project initialization is now &lt;span class="nb"&gt;complete
&lt;/span&gt;This would be a good &lt;span class="nb"&gt;time &lt;/span&gt;to commit and push your project, assuming you’ve got a repo setup. It’s always a good idea to commit regularly, with meaningful messages. It helps provide a &lt;span class="nb"&gt;history &lt;/span&gt;of your project and will prove useful later down the line.
&lt;span class="c"&gt;#bash &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s1"&gt;'initialises aws sam ruby project using sam cli'&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;master &lt;span class="o"&gt;(&lt;/span&gt;root-commit&lt;span class="o"&gt;)&lt;/span&gt; 8b7733d] initialises aws sam ruby project using sam cli
 8 files changed, 697 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
 create mode 100644 .gitignore
 create mode 100644 Gemfile
 create mode 100644 README.md
 create mode 100644 event.json
 create mode 100644 hello_world/Gemfile
 create mode 100644 hello_world/app.rb
 create mode 100644 template.yaml
 create mode 100644 tests/unit/test_handler.rb
&lt;span class="nv"&gt;$ &lt;/span&gt;git push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Explore the project directory, notice how the CLI generated pretty much all the files and folders we need for a simple project. It provides a great foundation following best practices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Project Structure&lt;/span&gt;
├── Gemfile
├── README.md
├── event.json
├── hello_world
│ ├── Gemfile
│ └── app.rb
├── template.yaml
└── tests
 └── unit
 └── test_handler.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, using the SAM CLI, we’re able to develop and test our function locally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#bash &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;sam &lt;span class="nb"&gt;local &lt;/span&gt;start-api
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once complete, a server will be running at localhost:3000.&lt;br&gt;
This is done using docker, the CLI spins up a docker instance matching the lambda runtime specified in the &lt;em&gt;template.yml&lt;/em&gt; file. This ensures your function is being tested on exactly the same version and build of linux that AWS Lambda is currently using. Ensuring the version is correct is especially important when bundling dependancies; if the app isn’t built on the platform it’s being run on, issues arise with compatibility and your function simply won’t work.&lt;/p&gt;

&lt;p&gt;Open up Postman and try sending a request to localhost:3000. Nothing right?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2d-WzG99--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mpn7klznoctrmuawlti7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2d-WzG99--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mpn7klznoctrmuawlti7.png" alt="Postman Empty Response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s because our skeleton app has a few defaults already setup. Open up the &lt;em&gt;template.yml&lt;/em&gt; file and have a look.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;#template.yml&lt;/span&gt;
&lt;span class="na"&gt;AWSTemplateFormatVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2010-09-09'&lt;/span&gt;
&lt;span class="na"&gt;Transform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Serverless-2016-10-31&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;aws-sam-ruby&lt;/span&gt;
&lt;span class="s"&gt;Sample SAM Template for aws-sam-ruby&lt;/span&gt;
&lt;span class="c1"&gt;# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst&lt;/span&gt;
&lt;span class="na"&gt;Globals&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Function&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;HelloWorldFunction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Serverless::Function&lt;/span&gt; &lt;span class="c1"&gt;# More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;CodeUri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello_world/&lt;/span&gt;
      &lt;span class="na"&gt;Handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app.lambda_handler&lt;/span&gt;
      &lt;span class="na"&gt;Runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ruby2.5&lt;/span&gt;
      &lt;span class="na"&gt;Events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;HelloWorld&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Api&lt;/span&gt; &lt;span class="c1"&gt;# More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api&lt;/span&gt;
          &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;Path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/hello&lt;/span&gt;
            &lt;span class="na"&gt;Method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get&lt;/span&gt;
&lt;span class="na"&gt;Outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function&lt;/span&gt;
  &lt;span class="c1"&gt;# Find out more about other implicit resources you can reference within SAM&lt;/span&gt;
  &lt;span class="c1"&gt;# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api&lt;/span&gt;
  &lt;span class="na"&gt;HelloWorldApi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;API&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Gateway&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;endpoint&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;URL&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Prod&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;stage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;World&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;function"&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Sub&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"&lt;/span&gt;
  &lt;span class="na"&gt;HelloWorldFunction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;World&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Lambda&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Function&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ARN"&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!GetAtt&lt;/span&gt; &lt;span class="s"&gt;HelloWorldFunction.Arn&lt;/span&gt;
  &lt;span class="na"&gt;HelloWorldFunctionIamRole&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Implicit&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;IAM&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Role&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;created&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;World&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;function"&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!GetAtt&lt;/span&gt; &lt;span class="s"&gt;HelloWorldFunctionRole.Arn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;First thing you’ll notice is the function is called &lt;em&gt;HelloWorld&lt;/em&gt;. You’ll also see that we’ve only defined one route, &lt;em&gt;/hello&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let’s open up our &lt;em&gt;app.rb&lt;/em&gt; file and see what we should expect to happen when we visit our route, &lt;em&gt;/hello&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#hello-world/app.rb&lt;/span&gt;
&lt;span class="c1"&gt;# require 'httparty'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'json'&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
  &lt;span class="c1"&gt;# Sample pure Lambda function&lt;/span&gt;
&lt;span class="c1"&gt;# Parameters&lt;/span&gt;
  &lt;span class="c1"&gt;# ----------&lt;/span&gt;
  &lt;span class="c1"&gt;# event: Hash, required&lt;/span&gt;
  &lt;span class="c1"&gt;#     API Gateway Lambda Proxy Input Format&lt;/span&gt;
  &lt;span class="c1"&gt;#     Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format&lt;/span&gt;
&lt;span class="c1"&gt;# context: object, required&lt;/span&gt;
  &lt;span class="c1"&gt;#     Lambda Context runtime methods and attributes&lt;/span&gt;
  &lt;span class="c1"&gt;#     Context doc: https://docs.aws.amazon.com/lambda/latest/dg/ruby-context.html&lt;/span&gt;
&lt;span class="c1"&gt;# Returns&lt;/span&gt;
  &lt;span class="c1"&gt;# ------&lt;/span&gt;
  &lt;span class="c1"&gt;# API Gateway Lambda Proxy Output Format: dict&lt;/span&gt;
  &lt;span class="c1"&gt;#     'statusCode' and 'body' are required&lt;/span&gt;
  &lt;span class="c1"&gt;#     # api-gateway-simple-proxy-for-lambda-output-format&lt;/span&gt;
  &lt;span class="c1"&gt;#     Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html&lt;/span&gt;
&lt;span class="c1"&gt;# begin&lt;/span&gt;
  &lt;span class="c1"&gt;#   response = HTTParty.get('http://checkip.amazonaws.com/')&lt;/span&gt;
  &lt;span class="c1"&gt;# rescue HTTParty::Error =&amp;gt; error&lt;/span&gt;
  &lt;span class="c1"&gt;#   puts error.inspect&lt;/span&gt;
  &lt;span class="c1"&gt;#   raise error&lt;/span&gt;
  &lt;span class="c1"&gt;# end&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;statusCode: &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="s2"&gt;"Hello World!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;# location: response.body&lt;/span&gt;
    &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It looks big, but it’s mostly comments. The actual method is quite small and, as you’ll notice, we should be expecting to see &lt;em&gt;Hello World&lt;/em&gt;! in the response. One thing to note for the future is that the response must always be in the same format and structure as listed above, otherwise some errors can occur when deploying your function.&lt;/p&gt;

&lt;p&gt;Let’s give it a go.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hyIFIJhF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/y61imcv7q90mrwdb5bfd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hyIFIJhF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/y61imcv7q90mrwdb5bfd.png" alt="Postman Success Response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It works! Now you’re ready to develop and work on your app locally.&lt;/p&gt;

&lt;h4&gt;
  
  
  Package and Deployment
&lt;/h4&gt;

&lt;p&gt;Once ready, you’ll want to deploy your app. Assuming you’ve used gems, you’ll want to make sure to build your app using a docker container with the lambda-ruby image. This is achieved using one command from the SAM CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#bash &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;sam build &lt;span class="nt"&gt;--use-container&lt;/span&gt;
2019-06-27 06:37:55 Starting Build inside a container
2019-06-27 06:37:55 Building resource &lt;span class="s1"&gt;'HelloWorldFunction'&lt;/span&gt;
Fetching lambci/lambda:build-ruby2.5 Docker container image......
2019-06-27 06:37:57 Mounting YOUR_FILE_PATH as /tmp/samcli/source:ro,delegated inside runtime container
Build Succeeded
Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml
Commands you can use next
&lt;span class="o"&gt;=========================&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; Invoke Function: sam &lt;span class="nb"&gt;local &lt;/span&gt;invoke
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; Package: sam package &lt;span class="nt"&gt;--s3-bucket&lt;/span&gt; &amp;lt;yourbucket&amp;gt;
Running RubyBundlerBuilder:CopySource
Running RubyBundlerBuilder:RubyBundle
Running RubyBundlerBuilder:RubyBundleDeployment
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we’ll create an S3 bucket to store our deployment. This is pretty helpful as it acts as a log of all the different app versions and, if something were to go wrong with a deployment, it would be pretty quick and easy to revert to a previous version stored in your S3 bucket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KakCFHb_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8jeawy6z1431o3yx25az.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KakCFHb_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8jeawy6z1431o3yx25az.png" alt="Creating an S3 Bucket"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create bucket, head over to the AWS console and search for S3. Click &lt;em&gt;Create Bucket&lt;/em&gt;, the default settings are fine, just make sure to call your bucket something useful, like the name of your app/function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xOd88eGH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ejir5bsiaj63wu1cbw8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xOd88eGH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ejir5bsiaj63wu1cbw8w.png" alt="Naming your S3 Bucket"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With everything setup, we’ll now package our app, upload it to the bucket and then deploy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#bash &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;sam package &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--template-file&lt;/span&gt; template.yaml &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="c"&gt;# This is our template file&lt;/span&gt;
    &lt;span class="nt"&gt;--output-template-file&lt;/span&gt; serverless-output.yaml &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="c"&gt;# This is the template file used with our package, SAM CLI creates a new file based on our template.yml.&lt;/span&gt;
    &lt;span class="nt"&gt;--s3-bucket&lt;/span&gt; aws-sam--ruby &lt;span class="c"&gt;# Where we upload our package&lt;/span&gt;
Successfully packaged artifacts and wrote output template to file serverless-output.yaml.
Execute the following &lt;span class="nb"&gt;command &lt;/span&gt;to deploy the packaged template
aws cloudformation deploy &lt;span class="nt"&gt;--template-file&lt;/span&gt; /Users/jameshamann/Documents/Development/aws-sam-ruby/serverless-output.yaml &lt;span class="nt"&gt;--stack-name&lt;/span&gt; &amp;lt;YOUR STACK NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You’ll notice once the package command finishes, it gives us the command to run to deploy. You can use either this or sam’s deploy command to complete deployment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#bash &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;sam deploy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--template-file&lt;/span&gt; serverless-output.yaml &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="c"&gt;#Template file generated by our package command.&lt;/span&gt;
    &lt;span class="nt"&gt;--stack-name&lt;/span&gt; aws-ruby-sam &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="c"&gt;#This is the name of the stack we'll be creating. It creates a cloudformation stack, allowing for easy and quick deployment.&lt;/span&gt;
    &lt;span class="nt"&gt;--capabilities&lt;/span&gt; CAPABILITY_IAM
Waiting &lt;span class="k"&gt;for &lt;/span&gt;changeset to be created...
Waiting &lt;span class="k"&gt;for &lt;/span&gt;stack create/update to &lt;span class="nb"&gt;complete
&lt;/span&gt;Successfully created/updated stack - aws-ruby-sam
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now your app is live! Open up your AWS API Gateway Console and you should see your new API!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vZzZ1iUx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qs0pyqhfgurbohhm9mj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vZzZ1iUx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qs0pyqhfgurbohhm9mj4.png" alt="API Gateway"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s give our API a test. First we need the endpoint, open up the API and click on one of the stages, Prod or Staging is fine. Your endpoint link will be clearly listed at the top of the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3IOHHoEy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/gf80ssordgh95h1tuhpr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3IOHHoEy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/gf80ssordgh95h1tuhpr.png" alt="API Environments"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open up Postman and fire a request through to your URL. Don’t forget to append your path &lt;em&gt;/hello&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nD-e5j28--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/elgkhjspnjrhblijjjle.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nD-e5j28--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/elgkhjspnjrhblijjjle.png" alt="Postman Success Response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there you have it! A fully functioning Ruby serverless application, deployed on AWS following best practices.&lt;br&gt;
Now you can look at expanding your function, or creating a front-end for it using React, Vue or whatever framework you like.&lt;/p&gt;

&lt;p&gt;All source code can be found &lt;a href="https://github.com/jameshamann/aws-sam-ruby"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ruby</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
