Go1.12+go mod로 Docker 컨테이너화

제목



k8s의 공부가 끝나면, Go의 앱에서도 GKE에 실어 보려고 생각하면서, 그러고 보면, 표제의 편성으로 Docker 컨테이너 만든 적이 없다고 깨닫는다.
전회 마지막에 Docker 컨테이너 만들었을 때는, Go1.9+dep 이었다, 분명.
그래서 지식을 업데이트해 둔다.

개발 환경



#OS


$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"

# Docker


$ sudo docker version
Client:
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.4
 Git commit:        6247962
 Built:             Tue Feb 26 23:52:23 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.4
  Git commit:       6247962
  Built:            Wed Feb 13 00:24:14 2019
  OS/Arch:          linux/amd64
  Experimental:     false

실천



Go 앱



뭐, 앱의 내용은 무엇이든 좋기 때문에, 우선 http://localhost:8080/sample 로 액세스 하면 200 OK 를 JSON 형식으로 돌려주는 것을 써 둔다.

[main.go]
package main

import (
    "net/http"

    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    e.GET("/sample", func(c echo.Context) error {
        return c.JSON(
            http.StatusOK,
            struct {
                Code int    `json:"code"`
                Text string `json:"text"`
            }{
                Code: http.StatusOK,
                Text: http.StatusText(http.StatusOK),
            },
        )
    })
    e.Logger.Fatal(e.Start(":8080"))
}

로컬 환경에서 실행하면 ↓과 같이 8080 포트에서 기다린다.
$ go run main.go 

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:8080

덧붙여서, go.mod 는 이런 느낌.

[go.mod]
module t01

require (
    github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
    github.com/labstack/echo v3.3.10+incompatible
    github.com/labstack/gommon v0.2.8 // indirect
    github.com/mattn/go-colorable v0.1.1 // indirect
    github.com/mattn/go-isatty v0.0.7 // indirect
    github.com/valyala/fasttemplate v1.0.1 // indirect
    golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 // indirect
)

Dockerfile



다음을 참고로.
htps : // 메이 m. 코 m / @ ㅎㅎㅎ / 우신 g 고도 d ぉ ぉ 아 d ー ー ぺ え ぺ ぁ
# step 1: build
FROM golang:1.12.4-alpine3.9 as build-step

# for go mod download
RUN apk add --update --no-cache ca-certificates git

RUN mkdir /go-app
WORKDIR /go-app
COPY go.mod .
COPY go.sum .

RUN go mod download
COPY . .

RUN CGO_ENABLED=0 go build -o /go/bin/go-app

# -----------------------------------------------------------------------------
# step 2: exec
FROM scratch
COPY --from=build-step /go/bin/go-app /go/bin/go-app
ENTRYPOINT ["/go/bin/go-app"]

특기사항



■ 베이스 이미지를 「Docker Hub」로부터 취득하고 있으므로 docker login 가 필요



하지 않으면 이렇게 된다.
$ sudo docker build -t sky0621/go-app:v0.1 .
Sending build context to Docker daemon  7.168kB
Step 1/8 : FROM "1.11.9-alpine3.9" AS builder
pull access denied for 1.11.9-alpine3.9, repository does not exist or may require 'docker login'

그래서 docker login 한다.
【참고】
htp // // cs. 도 c r. jp / 도 c 케 루 후 b / 아코 응 ts. HTML
$ sudo docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: sky0621dhub
Password: 
WARNING! Your password will be stored unencrypted in /home/sky0621/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

■ "RUN apk add --update --no-cache ca-certificates git"이 없으면 RUN go mod download가 실패합니다.


Step 6/11 : RUN go mod download
 ---> Running in 1b5ecc7774b5
go: github.com/dgrijalva/[email protected]+incompatible: git init --bare in /go/pkg/mod/cache/vcs/11fb0427c36fe2d22a58c95464426a2d142ff24c438e1248eeb9ff450be5af41: exec: "git": executable file not found in $PATH
  〜〜 省略 〜〜
go: golang.org/x/[email protected]: git init --bare in /go/pkg/mod/cache/vcs/de5fd3af413a4f3f969455ae522b4002fcb7bb4c158f339396dfc77710c9007d: exec: "git": executable file not found in $PATH
go: error loading module requirements
The command '/bin/sh -c go mod download' returned a non-zero code: 1

■ "CGO_ENABLED = 0"이 없으면 docker run이 실패합니다.


$ sudo docker run -p 80:8080 sky0621/go-app:v0.1
standard_init_linux.go:207: exec user process caused "no such file or directory"
cgo 라는 것은 Go에서 C의 코드를 호출하는 명령인 것 같다.
이것을 유효하게 하는 ( =1 ) 인가 무효로 하는 ( =0 )의 지정이 「 CGO_ENABLED 」로 디폴트에서는 유효인 것.
(단, 크로스 컴파일시는 디폴트로 무효)
유효하면 빌드 제약 조건으로 cgo가 설정됩니다.
【참고】
htps : /// g g. rg/cmd/c고/
standard_init_linux.go 의 내용은 쫓고 있지 않기 때문에, 여기에서 에러가 된 원인이라고 단정은 ​​할 수 없지만, 빌드 제약 cgo 를 제외하는 것으로 docker run 때의 실패는 회피되었다.

빌드



사전에 docker 프로세스도 이미지도 없는 것을 확인.
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
$
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

그럼 실행.
$ ls -l
total 16
-rw-r--r-- 1 sky0621 sky0621  464 Apr 20 08:52 Dockerfile
-rw-r--r-- 1 sky0621 sky0621  420 Apr 19 08:00 go.mod
-rw-r--r-- 1 sky0621 sky0621 1895 Apr 19 08:00 go.sum
-rw-r--r-- 1 sky0621 sky0621  375 Apr 19 09:23 main.go
$
$ date
Sat Apr 20 09:11:41 JST 2019
$
$ sudo docker build -t sky0621/go-app:v0.1 .
Sending build context to Docker daemon  6.656kB
Step 1/12 : FROM golang:1.12.4-alpine3.9 as build-step
1.12.4-alpine3.9: Pulling from library/golang
bdf0201b3a05: Pull complete 
38f114998adb: Pull complete 
21134b1a9e68: Pull complete 
cff36310a8c5: Pull complete 
02f293f0b51b: Pull complete 
Digest: sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Status: Downloaded newer image for golang:1.12.4-alpine3.9
 ---> b97a72b8e97d
Step 2/12 : RUN apk add --update --no-cache ca-certificates git
 ---> Running in 0c5bb1e980c9
fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/community/x86_64/APKINDEX.tar.gz
(1/6) Installing nghttp2-libs (1.35.1-r0)
(2/6) Installing libssh2 (1.8.2-r0)
(3/6) Installing libcurl (7.64.0-r1)
(4/6) Installing expat (2.2.6-r0)
(5/6) Installing pcre2 (10.32-r1)
(6/6) Installing git (2.20.1-r0)
Executing busybox-1.29.3-r10.trigger
OK: 20 MiB in 21 packages
Removing intermediate container 0c5bb1e980c9
 ---> 0625379ca405
Step 3/12 : RUN mkdir /go-app
 ---> Running in 82c9e6be294d
Removing intermediate container 82c9e6be294d
 ---> 0e99542d29eb
Step 4/12 : WORKDIR /go-app
 ---> Running in 7929d16e6ce4
Removing intermediate container 7929d16e6ce4
 ---> 2bb8099a90aa
Step 5/12 : COPY go.mod .
 ---> 77a7fb906751
Step 6/12 : COPY go.sum .
 ---> da9177c9aaa1
Step 7/12 : RUN go mod download
 ---> Running in a60a8f304669
go: finding github.com/labstack/echo v3.3.10+incompatible
go: finding github.com/mattn/go-colorable v0.1.1
go: finding github.com/dgrijalva/jwt-go v3.2.0+incompatible
go: finding github.com/labstack/gommon v0.2.8
go: finding github.com/mattn/go-isatty v0.0.7
go: finding github.com/valyala/fasttemplate v1.0.1
go: finding golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480
go: finding github.com/mattn/go-isatty v0.0.5
go: finding github.com/valyala/bytebufferpool v1.0.0
go: finding golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e
go: finding golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223
Removing intermediate container a60a8f304669
 ---> 44992184e9e2
Step 8/12 : COPY . .
 ---> 8e8041d6ff86
Step 9/12 : RUN CGO_ENABLED=0 go build -o /go/bin/go-app
 ---> Running in 1baafdb9189b
Removing intermediate container 1baafdb9189b
 ---> 51d15d46907b
Step 10/12 : FROM scratch
 ---> 
Step 11/12 : COPY --from=build-step /go/bin/go-app /go/bin/go-app
 ---> 6031f71f0586
Step 12/12 : ENTRYPOINT ["/go/bin/go-app"]
 ---> Running in a27a508d1102
Removing intermediate container a27a508d1102
 ---> 1ecb02037408
Successfully built 1ecb02037408
Successfully tagged sky0621/go-app:v0.1
$
$ date
Sat Apr 20 09:12:23 JST 2019

걸린 시간은, 대략 「42」초. 꽤 걸립니다. .
Sat Apr 20 09:11:41 JST 2019
Sat Apr 20 09:12:23 JST 2019

이미지 확인



Go의 빌드 등에 사용한 이미지는 나름대로 크기이지만 실제로 움직이는 Go 앱의 이미지는 "8.43MB"로 경량.
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
sky0621/go-app      v0.1                1ecb02037408        13 minutes ago      8.43MB
<none>              <none>              51d15d46907b        13 minutes ago      413MB
golang              1.12.4-alpine3.9    b97a72b8e97d        7 days ago          350MB

실행


$ sudo docker run -p 80:8080 sky0621/go-app:v0.1

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:8080

시작했다.
그럼 액세스.


좋아.

캐시 확인



Dockerfile의 제작에 의한 캐쉬의 효과를 확인하기 위해서, Go 앱을 미정정해 재빌드해 보자.
빌드 시간이 짧아질 것으로 기대.

Go 앱 미세 수정



접수하는 패스를 「/sample」→「/sample2」로 바꾼 만큼.
$ git diff
diff --git a/chXX_try/app/main.go b/chXX_try/app/main.go
index acb93c1..522a0e4 100644
--- a/chXX_try/app/main.go
+++ b/chXX_try/app/main.go
@@ -8,7 +8,7 @@ import (

 func main() {
        e := echo.New()
-       e.GET("/sample", func(c echo.Context) error {
+       e.GET("/sample2", func(c echo.Context) error {
                return c.JSON(
                        http.StatusOK,
                        struct {

재빌드


$ date
Sat Apr 20 09:43:21 JST 2019
$
$ sudo docker build -t sky0621/go-app:v0.2 .
Sending build context to Docker daemon  6.656kB
Step 1/12 : FROM golang:1.12.4-alpine3.9 as build-step
 ---> b97a72b8e97d
Step 2/12 : RUN apk add --update --no-cache ca-certificates git
 ---> Using cache
 ---> 0625379ca405
Step 3/12 : RUN mkdir /go-app
 ---> Using cache
 ---> 0e99542d29eb
Step 4/12 : WORKDIR /go-app
 ---> Using cache
 ---> 2bb8099a90aa
Step 5/12 : COPY go.mod .
 ---> Using cache
 ---> 77a7fb906751
Step 6/12 : COPY go.sum .
 ---> Using cache
 ---> da9177c9aaa1
Step 7/12 : RUN go mod download
 ---> Using cache
 ---> 44992184e9e2
Step 8/12 : COPY . .
 ---> c9a3ca188d54
Step 9/12 : RUN CGO_ENABLED=0 go build -o /go/bin/go-app
 ---> Running in 4aaa5be99f06
Removing intermediate container 4aaa5be99f06
 ---> f3ab3206497a
Step 10/12 : FROM scratch
 ---> 
Step 11/12 : COPY --from=build-step /go/bin/go-app /go/bin/go-app
 ---> fa6b7e4787a8
Step 12/12 : ENTRYPOINT ["/go/bin/go-app"]
 ---> Running in d17c0c300e5b
Removing intermediate container d17c0c300e5b
 ---> 0b607262dca1
Successfully built 0b607262dca1
Successfully tagged sky0621/go-app:v0.2
$
$ date
Sat Apr 20 09:43:33 JST 2019

빨라지고 있다. "12"초. (첫회는 「42」초였다.)
캐시 효과, 크네요.
Sat Apr 20 09:43:21 JST 2019
Sat Apr 20 09:43:33 JST 2019

요약



단순한 앱으로 시도했을 뿐이지만, 일단 Go1.12+go mod에서의 Docker 컨테이너화는 완료.
Dockerfile에 관해서는 정기적으로 ↓ 등 재확인하지 않는다고 생각했다.
htp // // cs. 도 c r. jp/v1.9/엔기네/아르치 ぇs/도 c케 r후ぃぇ_베 stp등 c치세. HTML

좋은 웹페이지 즐겨찾기