개요

golang으로 간단한 REST API 서버를 작성하고, 다중 스테이지(Multi stage) Dockerfile로 빌드하여 컨테이너로 배포한다. 

 


API 서버

모듈 임포트

REST API 서버를 생성하기 위해 gorilla/mux 모듈이 필요하다. 

import (
   "log"
   "net/http"
   "net"
   "fmt"
   "os"
   "time"
   "github.com/gorilla/mux"
)

 

apiServer 작성

path에 따라 response 할 수 있는 api server를 mux를 통해 구현한다. 

router.HandleFunc의 인자로 function을 주면, 해당 Path로 요청이 왔을 때 function을 실행할 수 있다. 

//REST API Section
func apiServer(){
   fmt.Printf("[API Server Section]\n")
   router := mux.NewRouter().StrictSlash(true)
   router.HandleFunc("/", apiServerStatus)
   router.HandleFunc("/lookup", ipLookUp).Methods("GET")
   log.Fatal(http.ListenAndServe(":28080", router))
   fmt.Println("["+time.Now().Format(time.RFC3339)+"]API Server Started")
}
func apiServerStatus(w http.ResponseWriter, r *http.Request){
   message :="["+time.Now().Format(time.RFC3339)+"][API Server Is Online]\n"
   fmt.Fprintf(w,message)
}

main function

main을 통해 api server를 실행시킨다. 

func main() {
   fmt.Printf("[Application Started]\n")
   apiServer()
   fmt.Printf("[Application Exit]\n")
}
 

 


Dockerfile 작성

go의 장점 중 하나는 실행 파일로 만들었을 때 매우 가볍게 실행 가능하다는 것이다. 이러한 장점을 살리기 위해 멀티 스테이지로 빌드하여 가벼운 컨테이너 이미지를 생성한다. 

Build Stage

Build Stage에서는 golang 이미지를 pull 하고, 필요한 모듈을 다운받아 실행파일로 빌드하는 과정을 수행한다. 

빌드된 파일을 ./app으로 저장하였다. 

Build Stage에서 생성된 컨테이너는 빌드를 완료한 후 함께 이미지로 생성되지 않는다.

## Build Stage
FROM golang:1.14 AS build
COPY . /app
WORKDIR /app
RUN go get -d github.com/gorilla/mux/
RUN go build -o app

Runtime Stage

Runtime Stage에서는, 위의 컨테이너에서 빌드한 바이너리파일을 가져와 가벼운 alpine 이미지에 넣고 기동한다.

## Runtime Stage
FROM alpine:latest AS runtime
WORKDIR /app
COPY --from=build /app .
CMD ["./app"]

 

컨테이너 이미지 빌드 

docker build를 수행하면 컨테이너 이미지가 빌드된다. 
$ docker build -t heover1cks/apiserver:latest .
Sending build context to Docker daemon  89.09kB
Step 1/10 : FROM golang:1.14 AS build
 ---> 05feda542433
Step 2/10 : COPY . /app
 ---> 6fcc7b74833c
Step 3/10 : WORKDIR /app
 ---> Running in 425f39357a62
Removing intermediate container 425f39357a62
 ---> e1068f552a8d
Step 4/10 : RUN go get -d github.com/gorilla/mux/
 ---> Running in 4944764fc5f7
Removing intermediate container 4944764fc5f7
 ---> 66cc39521ae5
Step 5/10 : RUN go build -o app
 ---> Running in 22796d00c4fc
Removing intermediate container 22796d00c4fc
 ---> 06f9a7a6bc82
Step 6/10 : FROM alpine:latest AS runtime
 ---> a24bb4013296
Step 7/10 : RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
 ---> Using cache
 ---> db20b6e3c77a
Step 8/10 : WORKDIR /app
 ---> Using cache
 ---> edbe43ffd5ed
Step 9/10 : COPY --from=build /app .
 ---> ee4eaff66fe3
Step 10/10 : CMD ["./app"]
 ---> Running in 8a6394eab7b3
Removing intermediate container 8a6394eab7b3
 ---> e4288cee1849
Successfully built e4288cee1849
Successfully tagged heover1cks/apiserver:latest

 

컨테이너 기동 및 테스트

위에서 빌드한 컨테이너를 기동한다. 

$ docker run -d -p 8080:28080 heover1cks/apiserver:latest
a2bd97cdade566d01ae098e5573a4cd4324a05ed03b31b4fca6d462ffd1f6845
api 서버에 요청을 보내면 정상적인 응답이 오는 것을 확인할 수 있다. 
$ docker ps
CONTAINER ID        IMAGE                         COMMAND             CREATED              STATUS              PORTS                     NAMES
a2bd97cdade5        heover1cks/apiserver:latest   "./app"             About a minute ago   Up About a minute   0.0.0.0:8080->28080/tcp   elastic_rosalind
$ curl http://localhost:8080/
[2020-06-16T14:50:35Z][API Server Is Online]

컨테이너 이미지의 사이즈는 13.5MB로, alpine 이미지와 큰 차이가 없다.

$ docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
heover1cks/apiserver     latest              e4288cee1849        4 minutes ago       13.5MB

apiserver 컨테이너의 리소스 사용량을 확인해보면, cpu/memory를 효율적으로 사용하고 있음을 확인할 수 있다. 

$ docker top $(docker ps -q)
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                5314                5291                0                   14:49               ?                   00:00:00            ./app

$ top -bc | grep 5314
 5314 root      20   0  691m 4388 3824 S  0.0  0.4   0:00.02 ./app