For the sake of simplicity, I added a new profile to the file

~/.aws/credentials

with the name

serverless

By adding the credentials to the AWS credentials file, I can use any AWS command using the desired profile.

Example:

aws s3 cp my_file s3://my_bucket --profile serverless

Installing and Configuring Serverless Framework

You can install Serverless using a single command:

sudo npm install -g serverless

Let’s configure Serverless:

serverless config credentials --provider aws --key <ACCESS KEY ID> --secret <SECRET KEY>

If you stored the key/secret to the credential files, we can use the different Serverless commands by designtating the profile at each command:

serverless deploy --aws-profile serverless

We can also export the profile as well as the region to environement variables:

export AWS_PROFILE="serverless" && export AWS_REGION=eu-west-1

Initializing our Project

In the app folder, we need to create a serverless.yml file. This file is needed to configure how our application will behave.

We need also to create our Python function (called handler.py):

In order to do this, let’s execute this command:

serverless create --template aws-python3 --name hello-world

This will create the handler file, the configuration file and the .gitignore file:

.

├── .gitignore

├── handler.py

└── serverless.yml

This is how our serverless.yml file looks like:

provider:

name: aws

runtime: python3.6 functions:

hello:

handler: handler.hello

This is how the handler.py file looks like:

import json def hello(event, context):

body = {

"message": "Go Serverless v1.0! Your function executed successfully!",

"input": event

} response = {

"statusCode": 200,

"body": json.dumps(body)

} return response # Use this code if you don't use the http event with the LAMBDA-PROXY

# integration

"""

return {

"message": "Go Serverless v1.0! Your function executed successfully!",

"event": event

}

"""

Deploying our Project

Once the template files are created, we have a working AWS Lambda function, we need to deploy it:

export AWS_PROFILE="serverless"

serverless deploy

Note: You need to change the profile name to use your own one.

The deployment output looks like this. You can see that our code is zipped and deployed to a S3 bucket before being deployed to Lambda.

Serverless: Packaging service...

Serverless: Excluding development dependencies...

Serverless: Creating Stack...

Serverless: Checking Stack create progress...

.....

Serverless: Stack create finished...

Serverless: Uploading CloudFormation file to S3...

Serverless: Uploading artifacts...

Serverless: Uploading service .zip file to S3 (390 B)...

Serverless: Validating template...

Serverless: Updating Stack...

Serverless: Checking Stack update progress...

................

Serverless: Stack update finished...

Service Information

service: hello-world

stage: dev

region: us-east-1

stack: hello-world-dev

api keys:

None

endpoints:

None

functions:

hello: hello-world-dev-hello

The function is now deployed.

Adding Events to our Function

While you do already have a function defined called hello that's linked to a function handler, you currently have no way of triggering that function. That's why we need to add an event to the function defined in serverless.yml . Update it as follows:

We defined a function called hello but we did not define a way to trigger the function, this is when adding an “event” is useful. Edit the serverless.yml file:

provider:

name: aws

runtime: python3.6 functions:

hello:

handler: handler.hello

events:

- http:

path: hello

method: get

According to our configuration, the function will be called using the /hello url.

Note: You can choose your own url.

Let’s deploy:

serverless deploy -v

Serverless: Excluding development dependencies...

Serverless: Uploading CloudFormation file to S3...

Serverless: Uploading artifacts...

Serverless: Uploading service .zip file to S3 (390 B)...

Serverless: Validating template...

Serverless: Updating Stack...

Serverless: Checking Stack update progress...

CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - hello-world-dev

CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi

CloudFormation - UPDATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction

CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi

CloudFormation - UPDATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction

CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::RestApi - ApiGatewayRestApi

CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHello

CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway

CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHello

CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway

CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceHello

CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloGet

CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloGet

CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodHelloGet

CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1534113893559

CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1534113893559

CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Deployment - ApiGatewayDeployment1534113893559

CloudFormation - CREATE_COMPLETE - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway

CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - hello-world-dev

CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - hello-world-dev

Serverless: Stack update finished...

Service Information

service: hello-world

stage: dev

region: us-east-1

stack: hello-world-dev

api keys:

None

endpoints:

GET -

functions:

hello: hello-world-dev-hello Serverless: Packaging service...Serverless: Excluding development dependencies...Serverless: Uploading CloudFormation file to S3...Serverless: Uploading artifacts...Serverless: Uploading service .zip file to S3 (390 B)...Serverless: Validating template...Serverless: Updating Stack...Serverless: Checking Stack update progress...CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - hello-world-devCloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApiCloudFormation - UPDATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunctionCloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApiCloudFormation - UPDATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunctionCloudFormation - CREATE_COMPLETE - AWS::ApiGateway::RestApi - ApiGatewayRestApiCloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHelloCloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGatewayCloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHelloCloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGatewayCloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceHelloCloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloGetCloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloGetCloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodHelloGetCloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1534113893559CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1534113893559CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Deployment - ApiGatewayDeployment1534113893559CloudFormation - CREATE_COMPLETE - AWS::Lambda::Permission - HelloLambdaPermissionApiGatewayCloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - hello-world-devCloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - hello-world-devServerless: Stack update finished...Service Informationservice: hello-worldstage: devregion: us-east-1stack: hello-world-devapi keys:Noneendpoints:GET - https://x7o0xwsbkd.execute-api.us-east-1.amazonaws.com/dev/hello functions:hello: hello-world-dev-hello

HelloLambdaFunctionQualifiedArn: arn:aws:lambda:us-east-1:998335703874:function:hello-world-dev-hello:1

ServiceEndpoint:

ServerlessDeploymentBucketName: hello-world-dev-serverlessdeploymentbucket-qqgrblrjprhu Stack OutputsHelloLambdaFunctionQualifiedArn: arn:aws:lambda:us-east-1:998335703874:function:hello-world-dev-hello:1ServiceEndpoint: https://x7o0xwsbkd.execute-api.us-east-1.amazonaws.com/dev ServerlessDeploymentBucketName: hello-world-dev-serverlessdeploymentbucket-qqgrblrjprhu

As you may see in the deployment logs that the AWS lambda function has a new URL:

We can test our function using the browser, tools like Postman, the CLI or Serverless invoke command.

Using CURL:

Output:

{

"message":"Go Serverless v1.0! Your function executed successfully!",

"input":{

"resource":"/hello",

"path":"/hello",

"httpMethod":"GET",

"headers":{

"Accept":"*/*",

"CloudFront-Forwarded-Proto":"https",

"CloudFront-Is-Desktop-Viewer":"true",

"CloudFront-Is-Mobile-Viewer":"false",

"CloudFront-Is-SmartTV-Viewer":"false",

"CloudFront-Is-Tablet-Viewer":"false",

"CloudFront-Viewer-Country":"FR",

"Host":"x7o0xwsbkd.execute-api.us-east-1.amazonaws.com",

"User-Agent":"curl/7.47.0",

"Via":"1.1 xxx.cloudfront.net (CloudFront)",

"X-Amz-Cf-Id":"",

"X-Amzn-Trace-Id":"Root=1-5b70bbe0-f318b862a8dfdb1e38fc337e",

"X-Forwarded-For":"",

"X-Forwarded-Port":"443",

"X-Forwarded-Proto":"https"

},

"queryStringParameters":null,

"pathParameters":null,

"stageVariables":null,

"requestContext":{

"resourceId":"bsk6aq",

"resourcePath":"/hello",

"httpMethod":"GET",

"extendedRequestId":"LiJLDHe3oAMF7kQ=",

"requestTime":"12/Aug/2018:22:59:44 +0000",

"path":"/dev/hello",

"accountId":"xxx",

"protocol":"HTTP/1.1",

"stage":"dev",

"requestTimeEpoch":1534114784336,

"requestId":"6727b590-9e83-11e8-a9cc-61641c6c77ac",

"identity":{

"cognitoIdentityPoolId":null,

"accountId":null,

"cognitoIdentityId":null,

"caller":null,

"sourceIp":"",

"accessKey":null,

"cognitoAuthenticationType":null,

"cognitoAuthenticationProvider":null,

"userArn":null,

"userAgent":"curl/7.47.0",

"user":null

},

"apiId":"x7o0xwsbkd"

},

"body":null,

"isBase64Encoded":false

}

}

Using serverless invoke:

sls invoke -f hello

Output:

{

"statusCode": 200,

"body": "{\"message\": \"Go Serverless v1.0! Your function executed successfully!\", \"input\": {}}"

}

Tailing Logs

Sometimes, you need to see the execution or the deployment logs. This is the command to tail the logs:

sls logs -f hello --tail

Deleting the Function

Using sls remove command, we can delete the deployed service from AWS Lambda.

serverless remove

We can add other options like:

--stage or -s The name of the stage in service.

or The name of the stage in service. --region or -r The name of the region in stage.

or The name of the region in stage. --verbose or -v Shows all stack events during deployment.

Note: Removing a service will also remove the S3 bucket.

Connect Deeper

We have seen how to deploy our first Lambda function using the Serverless Framework. Stay in touch as the upcoming posts will go more in depth.

I am creating a series of blog posts to help you develop, deploy and run (mostly) Python applications on AWS Lambda using Serverless Framwork. You can find the 2nd part here:

You can also find my other articles about the same topic but using other frameworks like Creating a Serverless Uptime Monitor & Getting Alerted by SMS — Lambda, Zappa & Python or Creating a Serverless Python API Using AWS Lambda & Chalice

Don’t forget to subscribe to Shipped: An Independent Newsletter Focused On Serverless, Containers, FaaS & Other Interesting Stuff.