bit.ly/serverless-codemash-2018

2 downloads 173 Views 35MB Size Report
Jan 11, 2017 - rememberLastLogin: false, theme: {logo: ..... processing items in a queue inconsistent or unknown traffic
Building Serverless Applications in AWS Workshop bit.ly/serverless-codemash-2018 Christopher M. Judd & Jarred Olson

Christopher M. Judd CTO and Partner at leader

BROUGHT TO YOU BY:

C O NT E NT S

Get More Refcardz! Visit dzone.com/refcardz

221

Getting Started With Docker

» About Docker » Docker Architecture » Getting Started » Typical Local Workflow » Other Helpful Commands

By Christopher M. Judd

» Dockerfile, and more...

A B O U T D O CK E R Almost overnight, Docker has become the de facto standard that developers and system administrators use for packaging, deploying, and running distributed applications. It provides tools for simplifying DevOps by enabling developers to create templates called images that can be used to create lightweight virtual machines called containers, which include their applications and all of their applications’ dependencies. These lightweight virtual machines can be promoted through testing and production environments where sysadmins deploy and run them. Docker Images

Docker makes it easier for organizations to automate infrastructure, isolate applications, maintain consistency, and improve resource utilizations.

A recipe or template for creating Docker containers. It includes the steps for installing and running the necessary software.

Docker Like a tiny virtual machine that is created from Container the instructions found within the Docker image originated

Similar to the popular version control software Git, Docker has a social aspect, in that developers and sysadmins are able to share their images via

Docker Client

Command-line utility or other tool that takes advantage of the Docker API (https://docs.docker. com/reference/api/docker_remote_api) to communicate with a Docker daemon

Docker Host

A physical or virtual machine that is running a Docker daemon and contains cached images as well as runnable containers created from images

G E T T I N G S TA R T E D W I T H D O C K E R

Docker Hub. Docker is an open-source solution that runs natively on Linux but also works on Windows and Mac using a lightweight Linux distribution and VirtualBox. Many

Site24x7 DOCKER MONITORING

tools have also grown up around Docker to make it easier to manage and orchestrate complex distributed applications.

Get Detailed Insight into Docker Containers

DO CK ER A RCHITEC TU R E Docker utilizes a client-server architecture and a remote API to manage and create Docker containers built upon

CPU

Docker images. The relationship between containers and images are analogous to the relationship between objects and classes in object-oriented programming.

© DZONE, INC.

Cache

Memory

Linux containers. Docker containers are created from

|

DZONE.COM

I/O

Serverless

What is Serverless

Serverless computing, also known as Function as a Service (FaaS), is a cloud computing code execution model in which the cloud provider fully manages starting and stopping virtual machines as necessary to serve requests, and requests are billed by an abstract measure of the resources required to satisfy the request, rather than per virtual machine, per hour. Despite the name, it does not actually involve running code without servers. Serverless computing is so named because the business or person that owns the system does not have to purchase, rent or provision servers or virtual machines for the back-end code to run on. Serverless code can either be triggered by specific events (such as user registration with Amazon Cognito), or be configured to run behind an API management platform in order to expose it as a REST API endpoint.

What is Serverless

Serverless computing, also known as Function as a Service (FaaS), is a cloud computing code execution model in which the cloud provider fully manages starting and stopping virtual machines as necessary to serve requests, and requests are billed by an abstract measure of the resources required to satisfy the request, rather than per virtual machine, per hour. Despite the name, it does not actually involve running code without servers. Serverless computing is so named because the business or person that owns the system does not have to purchase, rent or provision servers or virtual machines for the back-end code to run on. Serverless code can either be triggered by specific events (such as user registration with Amazon Cognito), or be configured to run behind an API management platform in order to expose it as a REST API endpoint.

Software as a service (SaaS) - “on-demand” software

Platform as a service (PaaS) - solution stack

Infrastructure as a service (IaaS) - virtual computing infrastructure

Backend as a service (BaaS) - “on-demand” service

Function as a service (FaaS) - hosted event-based functions

SaaS

IaaS

BaaS

PaaS

FaaS

'use strict'; console.log('Loading function'); exports.handler = (event, context, callback) => { //console.log('Received event:', JSON.stringify(event, null, 2)); console.log('value1 =', event.key1); console.log('value2 =', event.key2); console.log('value3 =', event.key3); callback(null, event.key1); // Echo back the first key value //callback('Something went wrong'); };

'use strict'; console.log('Loading function'); exports.handler = (event, context, callback) => { //console.log('Received event:', JSON.stringify(event, null, 2)); console.log('value1 =', event.key1); console.log('value2 =', event.key2); console.log('value3 =', event.key3); callback(null, event.key1); // Echo back the first key value //callback('Something went wrong'); };

Setup

https://nodejs.org/en/

https://aws.amazon.com/cli/

git clone https://github.com/cjudd/giftube-lambda.git

git clone https://github.com/cjudd/giftube.git

Register for your user account

http://escab.juddsolutions.com/ You AWS Credentials will be emailed to you. If you don’t see it check your spam folder.

https://563700736850.signin.aws.amazon.com/console

aws configure —-profile aws-pres AWS Access Key ID [None]: AKIAIUS.... AWS Secret Access Key [None]: lKebCB4... Default region name [None]: us-east-1 Default output format [None]:

aws configure

and/or ~/.aws/config

~/.aws/credentials

[default] output = json region = us-west-2

[default] aws_access_key_id = AKIAIUS… aws_secret_access_key = lKebCB4…

[profile aws-pres] region = us-east-1

[aws-pres] aws_access_key_id = AKIAIS… aws_secret_access_key = cSfaog…

aws lambda list-functions --profile aws-pres { "Functions": [ { "Version": "$LATEST", "CodeSha256": "yZ6eaOIxsXmb9C2eQGnlTVhD520U50q9dRhFeugMoRI=", "FunctionName": "cmjHelloWorld", "VpcConfig": { "SubnetIds": [], "SecurityGroupIds": [] }, "MemorySize": 128, "CodeSize": 243, "FunctionArn": "arn:aws:lambda:us-west-1:563700736850:function:cmjHelloWorld", "Handler": "cmjHelloWorld.handler", "Role": "arn:aws:iam::563700736850:role/lambda_execute_role", "Timeout": 3, "LastModified": "2016-12-05T21:18:58.990+0000", "Runtime": "nodejs4.3", "Description": "First Lambda" } ] }

Lab CLI Configure

1. Install Node 2. Clone giftube & giftube-lambda repos 3. Register (http://escab.juddsolutions.com/) 4. Install & configure AWS CLI 5. List Lambda functions

Lab Save Time

cd giftube sudo npm install -g @angular/cli npm install

First Lambda

exports.handler = (event, context, callback) => {
 console.log('*** CALLED FIRST LAMBDA ***', event);
 callback(null, 'Hello from Lambda');
 };

START RequestId: 0397cd21-d7a3-11e6-8fda-35d4c5ac1dd6 Version: $LATEST 2017-01-11T02:09:42.297Z 0397cd21-d7a3-11e6-8fda-35d4c5ac1dd6 *** CALLED FIRST LAMDA *** { key3: 'value3', key2: 'value2', key1: 'value1' } END RequestId: 0397cd21-d7a3-11e6-8fda-35d4c5ac1dd6 REPORT RequestId: 0397cd21-d7a3-11e6-8fda-35d4c5ac1dd6 Duration: 191.48 ms Billed Duration: 200 ms Memory Size: 128 MB Max Memory Used: 10 MB

aws lambda invoke \ --invocation-type RequestResponse \ --function-name cmjHelloWorld \ --log-type Tail \ --payload '{"key1":"value1"}' \ --profile aws-pres \ outputfile.txt

{ "LogResult": "U1RBUlQgUmVxdWVzdElkOiBkYWEwOWZjMy1iYjMxLTExZTYtOGJjZi02MzIzYzM2MjIxN2EgVmVyc2lvbjo gJExBVEVTVAoyMDE2LTEyLTA1VDIxOjI5OjA3Ljc4N1oJZGFhMDlmYzMtYmIzMS0xMWU2LThiY2YtNjMyM2M zNjIyMTdhCVRoaXMgaXMgYSBsb2dnZWQgZXZlbnQKRU5EIFJlcXVlc3RJZDogZGFhMDlmYzMtYmIzMS0xMWU 2LThiY2YtNjMyM2MzNjIyMTdhClJFUE9SVCBSZXF1ZXN0SWQ6IGRhYTA5ZmMzLWJiMzEtMTFlNi04YmNmLTY zMjNjMzYyMjE3YQlEdXJhdGlvbjogMS42OCBtcwlCaWxsZWQgRHVyYXRpb246IDEwMCBtcyAJTWVtb3J5IFN pemU6IDEyOCBNQglNYXggTWVtb3J5IFVzZWQ6IDkgTUIJCg==", "StatusCode": 200 }

outputfile.txt "Hello from Lambda"

Lab HelloWorld Lambda

1. Create Lambda in console 2. Test Lambda in console 3. Test Lambda via AWS CLI

Rest Lambda

https://www.npmjs.com/package/Faker

cd giftube-lambda cd getGifs vim index.js 'use strict'; var faker = require('Faker') exports.handler = (event, context, callback) => { var gifs = []; for(var i = 0; i < 10; i++) { var gif = {}; gif.id = faker.random.number(100); gif.title = faker.Lorem.sentences(1); gif.url = faker.Image.imageUrl(100, 100, 'sports') + "?" + faker.random.number(200); gifs.push(gif); } callback(null, gifs); }

vim package.json { "name": "getGifs", "version": "1.0.0", "description": "Get Gif Lambda", "repository": { "type":"git", "url":"https://github.com/cjudd/giftube-lambda" }, "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "license": "ISC", "dependencies": { "Faker": "0.7.2" } }

npm install zip -r gifs *

index.js 'use strict'; var faker = require('Faker') exports.handler = (event, context, callback) var gifs = []; for(var i = 0; i < 10; i++) {

var gif = {}; gif.id = faker.random.number(100) gif.title = faker.Lorem.sentences gif.url = faker.Image.imageUrl(10 gifs.push(gif); } callback(null, gifs); }

aws lambda create-function \ --profile aws-pres \ --function-name cmjGetGifs \ --zip-file fileb://gifs.zip \ --role arn:aws:iam::563700736850:role/service-role/simple_microservice_role \ --handler index.handler \ --runtime nodejs6.10 \ --timeout 15 \ --memory-size 128

aws lambda update-function-code \ --function-name cmjGetGifs \ --zip-file fileb://gifs.zip \ --profile aws-pres

Lab getGifs Lambda

1. Add Faker dependency 2. Create JavaScript function file 3. Create zip 4. Create function and upload zip 5. Test Lambda in console 6. Test Lambda via AWS CLI

Gateway API

Create API Create Resource Create Method

Lab Gifs API

1. Create Gifs API 2. Add gifs resource 3. Add GET method 4. Test end point

Deploy API

http/rest

https://6ry0hpz9vk.execute-api.us-west-1.amazonaws.com/cmjDev/gifs

curl -X GET \ "https://6ry0hpz9vk.execute-api.us-west-1.amazonaws.com/cmjDev/gifs" [

{

}, {

}, {

}, {

}, {

{

]

},

}

"id": 59, "title": "porro aperiam quae et incidunt", "url": "http://lorempixel.com/100/100/sports?24" "id": 86, "title": "neque officiis aut consequatur rerum modi hic explicabo qui", "url": "http://lorempixel.com/100/100/sports?68" "id": 34, "title": "nihil ut sed", "url": "http://lorempixel.com/100/100/sports?59" "id": 81, "title": "ipsam dicta molestiae aut temporibus magni", "url": "http://lorempixel.com/100/100/sports?102" "id": 26, "title": "porro non commodi et praesentium est eligendi et", "url": "http://lorempixel.com/100/100/sports?166" "id": 18, "title": "impedit est doloremque nesciunt nemo", "url": "http://lorempixel.com/100/100/sports?104"

Lab Deploy Gifs API

1. Deploy API 2. Test external end point

Create Web App

sudo npm install -g @angular/cli

cd giftube npm install ng serve

http://localhost:4200/

src/app/giftube-api.service.ts

import import import import

{ Injectable } from '@angular/core'; { Http } from '@angular/http'; { Observable } from 'rxjs/Observable'; 'rxjs/add/operator/map';

@Injectable() export class GiftubeApiService { baseUrl: string; constructor(private http: Http) { this.baseUrl = "https://6ry0hpz9vk.execute-api.us-west-1.amazonaws.com/cmjDev" } fetchGifs(): Observable { return this.http.get(`${this.baseUrl}/gifs`) .map(response => response.json()); } }

src/app/gifs/gifs.component.ts import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { GiftubeApiService } from '../giftube-api.service'; @Component({ selector: 'app-gifs', templateUrl: './gifs.component.html', styleUrls: ['./gifs.component.css'] }) export class GifsComponent implements OnInit { gifs; constructor(private _giftubeApiService: GiftubeApiService) { } ngOnInit() { this._giftubeApiService.fetchGifs().subscribe( gifs => this.gifs = gifs, error => console.log('Error fetching gifs')); } }

src/app/gifs/gifs.component.html

  • {{gif.title}}


  • Lab Create Web App

    1. Install angular-cli 2. Update files 1. giftube-api.service.ts 2. gifs.component.ts 3. gifs.component.html 3. Test http://localhost:4200 4. Enable CORS 5. Test http://localhost:4200

    Create Static Website

    { "Statement": [ { "Action": [ "s3:GetObject" ], "Effect": "Allow", "Principal": "*", "Resource": [ "arn:aws:s3:::cmj.giftube.tech/*" ], "Sid": "static-website-policy" } ], "Version": "2012-10-17" }

    ng build

    aws s3 sync dist s3://cmj.giftube.tech \ --acl public-read --profile aws-pres

    Lab Create Static Website

    1. Create S3 bucket (.giftube.tech) 2. Add bucket policy 3. Enable static website hosting 4. Deploy web app 5. Test web app

    Upload

    * GET PUT POST 3000 *

    Create Upload User (only if you are using your own account)

    var accessKey = 'AKIAJDU6MOYKJT6JEEZQ'; var secretKey = 'HrjrxJ4ptkqN5YutFAgGP9RMlzfpOlLmjJ+bzY2h';

    src/app/upload/upload.component.ts import { Component, OnInit } from '@angular/core'; import * as AWS from "aws-sdk"; @Component({ selector: 'app-upload', templateUrl: './upload.component.html', styleUrls: ['./upload.component.css'] }) export class UploadComponent implements OnInit { constructor() { } ngOnInit() { } public upload(event) { var file = event.srcElement.files[0]; if ('image/gif' !== file.type) { alert('You must choose a gif to upload'); return } /** /** var var

    THIS IS NOT A SECURE WAY TO UPLOAD TO S3 **/ THESE CREDENTIALS ARE IN PLAIN TEXT IN THE BROWSER **/ accessKey = ''; secretKey = '';

    var awsCreds = new AWS.Credentials(accessKey, secretKey); var s3 = new AWS.S3({credentials: awsCreds, region:'us-east-1'}); var params = { Bucket: '', Key: 'gifs/' + file.name, ACL: 'public-read', ContentType: 'image/gif', Body: file }; s3.putObject(params, function (err, accept="image/gif" (change)="upload($event)"/>



    src/app/app.component.html

    {{title}}

    "@angular/core": "2.2.3", "@angular/forms": "2.2.3", "@angular/http": "2.2.3", "@angular/platform-browser": "2.2.3", "@angular/platform-browser-dynamic": "2.2.3", "@angular/router": "3.2.3", "core-js": "^2.4.1", "rxjs": "5.0.0-beta.12", "ts-helpers": "^1.1.1", "zone.js": “^0.6.23”, "aws-sdk": "^2.7.21" }, "devDependencies": { "@angular/compiler-cli": "2.2.3", "@types/jasmine": "2.5.38", "@types/node": "^6.0.42", "angular-cli": "1.0.0-beta.22-1", "codelyzer": "~2.0.0-beta.1", "jasmine-core": "2.5.2", "jasmine-spec-reporter": "2.5.0", "karma": "1.2.0", "karma-chrome-launcher": "^2.0.0", "karma-cli": "^1.0.1", "karma-jasmine": "^1.0.2", "karma-remap-istanbul": "^0.2.1", "protractor": "4.0.9", "ts-node": "1.2.1", "tslint": "^4.0.2", "typescript": "~2.0.3", "webdriver-manager": "10.2.5", } }

    package.json

    npm install ng build

    aws s3 sync dist s3://cmj.giftube.tech \ --acl public-read --profile aws-pres

    Lab Upload Gifs

    1. Create S3 bucket (.giftube.gifs) 2. Add CORS Configuration 3. Update upload component 4. Update upload html 5. Update app component 6. Update website

    DynamoDB

    'use strict'; const aws = require('aws-sdk'); const s3 = new aws.S3({ apiVersion: '2006-03-01' }); var dynamodb = new aws.DynamoDB({apiVersion: '2012-08-10'}); exports.handler = (event, context, callback) => { const region = event.Records[0].awsRegion; const bucket = event.Records[0].s3.bucket.name; const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' ')); const params = { Bucket: bucket, Key: key, }; s3.getObject(params, (err, > Giftube Loading...

    src/app/header/header.component.ts

    import { Component, OnInit } from '@angular/core'; import {AuthService} from "../auth.service"; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.css'] }) export class HeaderComponent implements OnInit { constructor(private auth: AuthService) { } ngOnInit() { } }

    src/app/header/header.component.html

    Giftube Log In Log Out

    src/app/app.module.ts import import import import

    { { { {

    BrowserModule } from '@angular/platform-browser'; NgModule } from '@angular/core'; FormsModule } from '@angular/forms'; HttpModule } from '@angular/http';

    import import import import

    { { { {

    AppComponent } from './app.component'; HeaderComponent } from './header/header.component'; FooterComponent } from './footer/footer.component'; GifsComponent } from './gifs/gifs.component';

    import { GiftubeApiService } from './giftube-api.service'; import { UploadComponent } from './upload/upload.component'; import { AuthHttp }

    from 'angular2-jwt';

    @NgModule({ declarations: [ AppComponent, HeaderComponent, FooterComponent, GifsComponent, UploadComponent ], imports: [ BrowserModule, FormsModule, HttpModule ], providers: [GiftubeApiService, AuthHttp], bootstrap: [AppComponent] }) export class AppModule { }

    src/app/app.component.ts

    import { Component } from '@angular/core'; import {AuthService} from "./auth.service"; @Component({ selector: 'app-root', templateUrl: './app.component.html', providers: [ AuthService ], styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Giftube.tech'; constructor(private auth: AuthService) {} }

    { "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1483132738000", "Effect": "Allow", "Action": [ "sts:GetFederationToken" ], "Resource": [ "*" ] }, { "Sid": "Stmt1483130642000", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:PutObjectAcl" ], "Resource": [ "arn:aws:s3:::*" ] } ] }

    package.json

    { "name": "getTemporaryCredentials", "version": "1.0.0", "description": "Get Temporary Credential Lambda", "repository": { "type":"git", "url":"https://github.com/cjudd/giftube-lambda" }, "main": "", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "license": "ISC", "dependencies": { "aws-sdk": "^2.7.21", "jsonwebtoken": "7.1.9" } }

    "use strict";

    getTemporaryCredentials.js

    var AWS = require('aws-sdk'); var sts = new AWS.STS({ accessKeyId: '', secretAccessKey: '' }); var jwt = require('jsonwebtoken'); exports.handler = function (event, context, callback) { console.log('EVENT'); console.log(event); var token = event.authorization; validateAuth(token, '', callback); }; function validateAuth(token, arn, callback) { var secretKey = '9BlidEhRQvXYexZu1HV8HdjFVIB-Nw4bfS0h6tTg1mLcgxbPELxBkMuSixmARWBj'; jwt.verify(token, secretKey, function (err, decoded) { console.log(decoded); console.log(err); if (err) { console.log('Failed jwt verification: ', err, 'auth: ', token); callback('Authorization Failed'); } else { var params = { DurationSeconds: 3600, Name: decoded.aud, Policy: JSON.stringify(generatePolicy(decoded.sub)) }; sts.getFederationToken(params, function (err, data) { if (err) { console.log('ERROR'); console.log(err, err.stack); callback(err) } else { console.log('SUCCESS!!!');

    sts.getFederationToken(params, function (err, data) { if (err) { console.log('ERROR'); console.log(err, err.stack); callback(err) } else { console.log('SUCCESS!!!'); console.log(data); callback(null, data); } });

    getTemporaryCredentials.js

    } }) }

    var generatePolicy = function (userId) { console.log('USER ID: ' + userId); var policy = { "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1483130642000", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:PutObjectAcl" ], "Resource": [ "arn:aws:s3:::/" + userId + "/*" ] } ] }; console.log('Policy:'); console.log(policy); return policy };

    AKIAJEWKWWRB6O5URLRA /Z+xpPDaRz/WNRihjzmyigDOtxA3aJRldyw5reLv

    zip -r tempcreds * aws lambda create-function \ --profile aws-pres \ --function-name cmjGetTemporaryCredentials \ --zip-file fileb://tempcreds.zip \ --role arn:aws:iam::563700736850:role/lambda_execute_role \ --handler getTemporaryCredentials.handler \ --runtime nodejs4.3 \ --timeout 15 \ --memory-size 128

    { "authorization": "$input.params('Authorization')" }

    src/app/giftube-api.service.ts

    import import import import

    { Injectable } from '@angular/core'; { Http, Headers } from '@angular/http'; { Observable } from 'rxjs/Observable'; 'rxjs/add/operator/map';

    @Injectable() export class GiftubeApiService { baseUrl: string; constructor(private http: Http) { this.baseUrl = "https://6ry0hpz9vk.execute-api.us-west-1.amazonaws.com/cmjDev" } fetchGifs(): Observable { return this.http.get(`${this.baseUrl}/gifs`) .map(response => response.json()); } getTemporaryCredentials():Observable { var headers = new Headers(); headers.append('Authorization', localStorage.getItem('token')); return this.http.get(`${this.baseUrl}/gettemporarycredentials`, {headers: headers}) .map(response => response.json()); } }

    src/app/upload/upload.component.ts

    import { Component, OnInit } from '@angular/core'; import * as AWS from "aws-sdk"; import { GiftubeApiService } from '../giftube-api.service'; @Component({ selector: 'app-upload', templateUrl: './upload.component.html', styleUrls: ['./upload.component.css'] }) export class UploadComponent implements OnInit {

    constructor(private _giftubeApiService: GiftubeApiService) { } ngOnInit() { } public upload(event) { var file = event.srcElement.files[0]; if ('image/gif' !== file.type) { alert('You must choose a gif to upload'); return } this._giftubeApiService.getTemporaryCredentials().subscribe( response => this.uploadWithCredentials(file, response.Credentials), error => console.log('Error....' + error) ); } private uploadWithCredentials(file, credentials) { var accessKey = credentials.AccessKeyId; var secretKey = credentials.SecretAccessKey; var sessionToken = credentials.SessionToken; var awsCreds = new AWS.Credentials(accessKey, secretKey, sessionToken); var s3 = new AWS.S3({credentials: awsCreds, region:”us-east-1"}); var params = { Bucket: '', Key: localStorage.getItem('user_id') + '/' + file.name,

    if ('image/gif' !== file.type) { alert('You must choose a gif to upload'); return }

    src/app/upload/upload.component.ts

    this._giftubeApiService.getTemporaryCredentials().subscribe( response => this.uploadWithCredentials(file, response.Credentials), error => console.log('Error....' + error) ); } private uploadWithCredentials(file, credentials) { var accessKey = credentials.AccessKeyId; var secretKey = credentials.SecretAccessKey; var sessionToken = credentials.SessionToken; var awsCreds = new AWS.Credentials(accessKey, secretKey, sessionToken); var s3 = new AWS.S3({credentials: awsCreds, region:"us-east-1"}); var params = { Bucket: '', Key: localStorage.getItem('user_id') + '/' + file.name, ACL: 'public-read', ContentType: "image/gif", Metadata: { user_id: localStorage.getItem('user_id') } Body: file }; s3.putObject(params, function (err, data) { if (err) { alert('Error when uploading to s3'); console.error(err); } else { alert('Uploaded to S3 successfully.’); window.location.reload(); } }); } }

    ng build aws s3 sync dist s3://cmj.giftube.tech \ --acl public-read --profile aws-pres

    Summary

    $0.00001667 (1/60,000 th of a cent) for every GB/s used. $0.20 for every 1 million requests

    Pros save money horizontal scaling focus on business not infrastructure Cons vendor specific testing lack of tooling

    microservices processing items in a queue inconsistent or unknown traffic minimum viable products (MVP) IoT

    Resources

    https://serverless.com/

    https://www.terraform.io

    http://martinfowler.com/articles/serverless.html

    Christopher M. Judd CTO and Partner email: [email protected] web: www.juddsolutions.com blog: juddsolutions.blogspot.com twitter: javajudd BROUGHT TO YOU BY:

    C O NT E NT S

    Get More Refcardz! Visit dzone.com/refcardz

    221

    Getting Started With Docker

    » About Docker » Docker Architecture » Getting Started » Typical Local Workflow » Other Helpful Commands

    By Christopher M. Judd

    » Dockerfile, and more...

    A B O U T D O CK E R Almost overnight, Docker has become the de facto standard that developers and system administrators use for packaging, deploying, and running distributed applications. It provides tools for simplifying DevOps by enabling developers to create templates called images that can be used to create lightweight virtual machines called containers, which include their applications and all of their applications’ dependencies. These lightweight virtual machines can be promoted through testing and production environments where sysadmins deploy and run them. Docker Images

    Docker makes it easier for organizations to automate infrastructure, isolate applications, maintain consistency, and improve resource utilizations.

    A recipe or template for creating Docker containers. It includes the steps for installing and running the necessary software.

    Docker Like a tiny virtual machine that is created from Container the instructions found within the Docker image originated

    Similar to the popular version control software Git, Docker has a social aspect, in that developers and sysadmins are able to share their images via

    Docker Client

    Command-line utility or other tool that takes advantage of the Docker API (https://docs.docker. com/reference/api/docker_remote_api) to communicate with a Docker daemon

    Docker Host

    A physical or virtual machine that is running a Docker daemon and contains cached images as well as runnable containers created from images

    G E T T I N G S TA R T E D W I T H D O C K E R

    Docker Hub. Docker is an open-source solution that runs natively on Linux but also works on Windows and Mac using a lightweight Linux distribution and VirtualBox. Many

    Site24x7 DOCKER MONITORING

    tools have also grown up around Docker to make it easier to manage and orchestrate complex distributed applications.

    Get Detailed Insight into Docker Containers

    D O CK ER A RCHITEC TU R E Docker utilizes a client-server architecture and a remote API to manage and create Docker containers built upon

    CPU

    Docker images. The relationship between containers and images are analogous to the relationship between objects and classes in object-oriented programming.

    © D Z O N E , I NC .

    Cache

    Memory

    Linux containers. Docker containers are created from

    |

    D Z O N E .C O M

    I/O

    Jarred Olson

    Problem Solver email: [email protected] twitter: @JarredOlson