aws sam initを試してみた(Go)
はじめに
Goに興味が湧いたので、Goで試してみました。
実行環境はAWSのCloud9です。
開発環境準備
Cloud9使います!
Go
以下の手順にそってGoの環境を構築する。
sam initを試す (Go)
$ sam init --runtime go1.x --name hello-sam Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Quick start templates may have been updated. Do you want to re-download the latest [Y/n]: Y # 以下のファイルが生成される └── hello-sam ├── hello-world │ ├── main.go # lambda function │ └── main_test.go # unit test ├── Makefile ├── README.md └── template.yaml $ cd hello-sam # go.mod作成 $ go mod init sample # install $ go get github.com/aws/aws-sdk-go # test $ go test ./... ok hello-sam/hello-world (0.852s) # build $ GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world # Lambda実行(HelloWorldFuntion) $ sam local invoke HelloWorldFunction # APIサーバ起動 $ sam local start-api $ curl 127.0.0.1:3000/hello
まとめ
Shimane.goもあるから、この調子でどんどんGo(&SAM)やってくぞ!
手っ取り早く取り組めて素晴らしい。
参考サイト
Hello SAM: AWS Golang Quickstart
Goの開発環境にAWS Cloud9をつこうてみる
GOPATH は適当に決めて問題ない
Go備忘録 -struct周辺-
Go備忘録 -struct周辺-
- Goにはクラスがない。代わりにstructを使用する
- structはクラスのように関数定義できない(初めての経験)
Example
struct定義
type Person struct { FirstName string LastName string } // 変数定義 // フィールド値なし var person Person person := Person{} // フィールド値順 person := Person{"Taro", "Sato"} // KeyValue指定 person := Person{FirstName: "Taro", LastName: "Sato"}
struct継承
import "fmt" type Creature struct { Age int Sex string } func (c Creature) AgeAge() int { return c.Age * 2 } type Person struct { // CreatureStructのフィールド値を埋め込み Creature FirstName string LastName string } person := Person{ Creature: Creature{ Age: 1, Sex: "man", }, FirstName: "Taro", LastName: "Sato", } fmt.Println(person) fmt.Println(person.Creature) // PersonでAgeが定義されているようにアクセスできる fmt.Println(person.Age) // Creatureで定義した関数もPersonに継承される fmt.Println(person.AgeAge())
// 実行結果 {{1 man} Taro Sato} {1 man} 1 2
struct関数定義
import "fmt" type Person struct { FirstName string LastName string } func (p *Person) Name() string { return p.FirstName + " " + p.LastName } person := &Person{"Taro", "Yamada"} fmt.Println(person.Name())
// 実行結果 Taro Yamada
NG
type Machine struct { Name string } func (m Machine) Name() string { return m.Name }
// 実行結果 // (ERROR: Structで定義している属性と同名の関数は定義できない) type Machine has both field and method named Name
interface(ダックタイピング)
import "fmt" type Person struct { FirstName string LastName string } func (p *Person) Name() string { return p.FirstName + " " + p.LastName } type Machine struct { Name string } type Named interface { Name() string } func printName(named Named) { fmt.Println(named.Name()) } // ケース1 person := &Person{"Taro", "Yamada"} printName(person) // ケース2 machine := &Machine{"PC"} printName(machine)
// 実行結果 // ケース1 Taro Yamada // ケース2 (ERROR: MachineStructにName関数が定義されてない) *Machine does not implement Named (missing Name method)
Go備忘録 -defer-
Go備忘録 -defer-
- 呼び出し元関数が終了(return)するまで
defer
に与えた関数は評価されない。 defer
に与えた関数の引数などは、その時点の値で実行される。- 呼び出し元関数で
defer
を複数実行している場合は、あとで呼ばれたdefer
が先に評価される。
実行
package main import "fmt" func main() { i := 1 defer fmt.Println(i) i ++ defer fmt.Println(i) i ++ fmt.Println("func return") }
// 実行結果 func return 2 1
参考
Go備忘録 -for-
Go備忘録 -for-
Goで繰り返し処理を行う場合はfor
を使うしかありません。
forの色々
sum := 0 // 初期化; 条件(真の間繰り返し); 後処理 for i := 0; i < 10; i++ { sum += i } fmt.Println(sum)
sum := 1 // 初期化と後処理を省略 for sum < 1000 { sum += sum } fmt.Println(sum)
// すべて省略すると無限ループ for { // 無限ループで実行する処理を記述 fmt.Println("Running...") }
strArray := [3]string{"hoge", "fuga", "buzz"} // 要素を1つずつ取り出す(iにはidx値が格納される) // rubyでいうとeach.with_index for i, s := range strArray { fmt.Printf("index: %d, name: %s\n", i, s) }
参考
ほぼこの記事に書いてありました。
Go備忘録 -ポインタ-
Go備忘録 -ポインタ-
詳しい説明はこの記事に書いてありました。
ポインタ使い方
// 適当なオブジェクト(int型) obj := 100 // int型のポインタ格納用変数定義 var pointer *int // int型のポインタ格納用変数定義+objのポインタを代入 var pointer *int = &obj // 同上 pointer := &obj // ポインタ領域に格納されている値を参照 *pointer // => 100
ポインタを使ってない場合
func add_num(num int){ num++ } num := 1 add_num(num) add_num(num) num // => 1
ポインタを使った場合
func add_num(pointer *int){ *pointer++ } num := 1 add_num(&num) add_num(&num) num // => 3
ポインタ領域確保
GCが組み込まれているので手動で領域解放する必要はない
// int型のポインタ領域を確保 var pointer *int = new(int) // 同上 pointer := new(int)
Question (保留事項)
- ポインタ領域を確保しておく事で何が嬉しいの?
- 領域が足りていない場合にどんな問題が起こり得るの?
lambdaからpsqlおよびpg_dumpを実行する
lambdaからpsqlおよびpg_dumpを実行する
Dockerコンテナ起動
- 目的はpostgresqlソースを取得すること
- lambda実行環境を再現したDockerImageじゃないとOS依存部分でコケる
FROM lambci/lambda:build-ruby2.5 # postgresql install RUN yum install -y postgresql-devel CMD "/bin/bash"
$ docker build -t lambda-ruby2.5-psql . $ docker run --rm -it -v $PWD:/var/task -w /var/task lambda-ruby2.5-psql
postgresqlソース取得
/var/task
にソースを集約させる- デプロイされるlambdaのソース一式は
/var/task
に配置される
$ mkdir /var/task/lib $ mkdir /var/task/lib64 # デフォルトでpostgresql9.2がインストールされたためpgsql92 $ cp -a /usr/lib64/pgsql92 /var/task/lib64/pgsql92 # pgsql92で使用しているのがlibpq.so.5.5 $ cp -a /usr/lib64/libpq.so.5.5 /var/task/lib/libpq.so.5.5
libpq.soへのシンボリックリンク作成【ハマりポイント】
libpq.so
とlibpq.so.5
のシンボリックリンクを作成するpsql
やpg_dump
が内部でlibpq.so
を呼び出しているため
/var/task/lib
に作成する- 環境変数
LD_LIBRARY_PATH
に/var/task/lib
が含まれるため
- 環境変数
# シンボリックリンク作成 $ ln -s /var/task/lib64/pgsql92/libpq.so /var/task/lib/libpq.so $ ln -s /var/task/lib/libpq.so.5.5 /var/task/lib/libpq.so.5
lambdaから呼び出し
- 上で
/var/task
に配置/作成したソースと下のrbファイルを一緒にlambdaにデプロイして実行する /var/task/lib64/pgsql92/bin/psql
もシンボリックリンク作ればpsql
で呼び出せそうです
require 'json' def handler(event:, context:) # psqlコマンドの確認としてバージョン出力させます { statusCode: 200, body: JSON.generate(`/var/task/lib64/pgsql92/bin/psql --version`) } end # => {"statusCode":200,"body":"\"psql (PostgreSQL) 9.2.24\\n\""}
まとめ
Linuxのフォルダ構成やライブラリ読み込みについて初めて調べました。
途中投げ出しかけましたが、実現できてよかった。
成果物
ECSデプロイにECRを使ってみた(1/2:ECRにImage作成)
はじめに
以前はオンプレ環境のDockerを想定した使い方を記事にしましたが、
今回はECR(ECS)の使い方について記事にしていこうと思います。
- ECS/ECRとは
- ECRにリポジトリ作成
- DockerfileからDockerイメージ作成
- Containerデプロイの流れ(ECS)
ECS/ECRとは
ECS(Elastic Container Service)
- コンテナオーケストレーションサービス
- DockerコンテナをAWS上で管理する
- ホストサーバの準備も不要
- 他のAWSサービスとの連携も容易に行える
【公式】Amazon Elastic Container Service とは
Amazon EC2 Container Service(ECS)の概念整理
AWS Black Belt Online Seminar 2016 Amazon EC2 Container Service
ECR(Elastic Container Registry)
- Dockerレジストリサービス
- Dockerイメージ(Dockerfileやら諸々)をAWS上で管理する
- ECSと統合されているのでコンテナ用のイメージをECRから取得できる
- AWSに限らずローカルマシンやオンプレ環境からも容易にアクセスできる
【公式】Amazon Elastic Container Registry とは
【公式】Amazon Elastic Container Registry の特徴
ECRにリポジトリ作成
DockerfileからDockerイメージ作成
Dockerfileの作成についてはこちらを参照してください。
ECRリポジトリ画面右上の「プッシュコマンドの表示」から
以下の手順について確認することができます。
# sample/nginx = ECRリポジトリ名 # Dockerfile配置フォルダに移動 $ cd ecr/sample-nginx # Dockerのログインコマンド取得&実行 $ (aws ecr get-login --no-include-email --region ap-northeast-1) $ docker login -u AWS -p xxxxxxxx https://xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com # Dockerイメージをbuild $ docker build -t sample/nginx . # buildしたイメージをECRにpushできるようにタグ付け $ docker tag sample/nginx:latest xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/sample/nginx:latest # タグ付けしたイメージをECRにpush $ docker push ********.dkr.ecr.ap-northeast-1.amazonaws.com/sample/nginx:latest # ECRからイメージをlocalにpull $ docker pull ************.dkr.ecr.us-east-1.amazonaws.com/sample/nginx:latest
Containerデプロイの流れ
(キャプチャを使って説明する予定)
未着手
まとめ
未着手