はじめに
Oracle Function で、独自に作成したDockerImage を使用して Function を実行する方法を書きます。
シンプルな関数を実行する場合であればカスタムする必要はありませんが、複雑なDockerImageを使用しなければならない場合には、とても有効な手段です。
Oracle Functions 自体ののチュートリアルはこちらを参照してください
https://qiita.com/sugimount/items/018e08f575ecefb1546c
独自に作成するDockerImageの概要
今回は、以下の内容のDockerImageを作成します。Dockerコンテナ内に事前に必要なファイルを格納しておきたいニーズに出会ったことがあり、これを想定しています。
- DockerImageに、テスト用のファイルを格納して build する
- DockerImage内で Go言語を動かして、テスト用のファイルの中身を出力し、JSONとしてResponseする
この内容を確認することで、DockerImageを独自に作成して Oracle Functions で実行する流れが掴めると思います。
Function の初期テンプレートを生成
適当な作業ディレクトリへ移動します。自分の場合はGo言語で作成するため、GOPATH が通っているディレクトリを選んでいます。
mkdir /home/ubuntu/go-third-party/src/fn_work
cd /home/ubuntu/go-third-party/src/fn_work
fn init コマンドで、go言語の初期テンプレートを生成します。
fn init --runtime go custom_runtime
自動生成されたディレクトリへ移動します
cd custom_runtime
独自のDockerImage作成
まずは、テスト用のファイルを生成します。
echo 'Hello! I am file!' >> iamfile.txt
Go言語のソースコードを作ります。今回は以下のソースコードを作ります。
環境変数 FUNC_OPEN_FILEPATH
で与えたファイルを読み込み、JSONとしてResponseする内容です。
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"os"
fdk "github.com/fnproject/fdk-go"
)
// BUFSIZE 読み込みバッファーサイズ
const BUFSIZE = 1024
func main() {
fdk.Handle(fdk.HandlerFunc(printFile))
}
func printFile(ctx context.Context, in io.Reader, out io.Writer) {
// file read
file, err := os.Open(os.Getenv("FUNC_OPEN_FILEPATH"))
if err != nil {
fmt.Println("error!")
return
}
defer file.Close()
buf := make([]byte, BUFSIZE)
context := ""
for {
n, err := file.Read(buf)
if n == 0 {
break
}
if err != nil {
// Readエラー処理
break
}
context = string(buf[:n])
}
// make struct
msg := struct {
Message string `json:"message"`
}{}
msg.Message = context
json.NewEncoder(out).Encode(&msg)
}
fn で使用する、定義ファイルを編集します。runtimeを go
から、独自のDockerImageを使用することを意味する docker
へ変更します。
> vim func.yaml
schema_version: 20180708
name: custom_runtime
version: 0.0.1
runtime: docker <======== go から dockerに書き換え
entrypoint: ./func
format: http-stream
Dockerfileを作ります。マルチステージビルドを使っています。マルチステージビルド自体は、こちらを読むとわかりやすいと思います。
今回確認したいポイントは以下の通りです
- 作成したテストファイル
iamfile.txt
を、/function/iamfile.txt
に格納している
vim Dockerfile
FROM golang:1.11.5 as builder
WORKDIR /go/src/funcdir
COPY Gopkg.toml .
COPY func.go .
RUN go get -u github.com/golang/dep/cmd/dep && \
dep ensure
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o func .
FROM alpine:3.9
WORKDIR /function/
COPY --from=builder /go/src/funcdir/func .
COPY iamfile.txt /function/iamfile.txt
ENTRYPOINT ["/function/func"]
以下のファイル構成になっているとよいです
> tree /home/ubuntu/go-third-party/src/fn_work/custom_runtime
/home/ubuntu/go-third-party/src/fn_work/custom_runtime
├── Dockerfile
├── Gopkg.toml
├── func.go
├── func.yaml
└── iamfile.txt
正常にDockerImageをBuild出来るか確認を行います (docker build で直接やってもよいです)
fn -v build
実行例
> fn -v build
Building image phx.ocir.io/sugimount2/oracle-function/custom_runtime:0.0.1
FN_REGISTRY: phx.ocir.io/sugimount2/oracle-function
Current Context: sugi-context
Sending build context to Docker daemon 41.47kB
Step 1/10 : FROM golang:1.11.5 as builder
---> 901414995ecd
Step 2/10 : WORKDIR /go/src/funcdir
---> Using cache
---> 279adebb201e
Step 3/10 : COPY Gopkg.toml .
---> Using cache
---> a0ed62dd646f
Step 4/10 : COPY func.go .
---> Using cache
---> 70919180fbb6
Step 5/10 : RUN go get -u github.com/golang/dep/cmd/dep && dep ensure
---> Using cache
---> 6d10b5c6b642
Step 6/10 : RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o func .
---> Using cache
---> a05adf4cd5e2
Step 7/10 : FROM alpine:3.9
---> caf27325b298
Step 8/10 : WORKDIR /function/
---> Using cache
---> b75514413267
Step 9/10 : COPY --from=builder /go/src/funcdir/func .
---> Using cache
---> d13fa27ed5ba
Step 10/10 : ENTRYPOINT ["/function/func"]
---> Using cache
---> 10382affeec1
Successfully built 10382affeec1
Successfully tagged phx.ocir.io/sugimount2/oracle-function/custom_runtime:0.0.1
Function phx.ocir.io/sugimount2/oracle-function/custom_runtime:0.0.1 built successfully.
正常に build できたら、fn deploy を実行して、Oracle Functions に Deploy します。
fn --verbose deploy --app env-app
環境変数を設定します。FUNC_OPEN_FILEPATH
に、DockerFIleで格納したテスト用ファイルの格納先を示しています
fn config func env-app custom_runtime FUNC_OPEN_FILEPATH /function/iamfile.txt
確認
> fn ls config func env-app custom_runtime
KEY VALUE
FUNC_OPEN_FILEPATH /function/iamfile.txt
Functionを実行します
fn --verbose invoke env-app custom_runtime
以下のように、テスト用のファイルの中身をReadして、JSONとしてResponseしているのが確認できました。
> fn --verbose invoke env-app custom_runtime
{"message":"Hello! I am file!\n"}
参考URL
Creating a Function from a Docker Image
http://fnproject.io/tutorials/ContainerAsFunction/
Packaging your Function
https://github.com/fnproject/docs/blob/master/fn/develop/packaging.md
Fn Tutorial
http://fnproject.io/tutorials/