IT Japan

Docker에서 최소 Go 이미지 만들기 (cgo 편) 본문

IT/인프라

Docker에서 최소 Go 이미지 만들기 (cgo 편)

swhwang 2017. 12. 28. 12:13
반응형

"최소 Node.js Docker 이미지 목표 스레 「Java에서도 Docker에서 다단계 빌드 '라는 항목에서는 Node.js와 Java 사용한 어플리케이션 이미지 최대한 작게 재판을했습니다.

이번에는 Go에서 해보고 있습니다. 그러나 Pure Go에서 최소라는 것은 이미 방법이 있고, scratch라는 아무것도 포함되지 않은 이미지 바탕으로 정적 링크 된 바이너리 배치하는 방법입니다.

     Building Minimal Docker Containers for Go Applications

Go 사용하면 일부 cgo 사용 된 패키지 이용하고 싶은 것도있을 것이고, 엉성하게 명령 줄 사용할 수도있을 것이다,라고하는 것으로, 이번 감소 않고 ( 하고 싶은 일에 따라 세밀하게 작전 조정할 필요 없다), 가능한 한 작고한다는 방침으로 가고 싶습니다.




STEP1 : 다단계 빌드



것으로, Node.js에서 강력했다 다단 빌드 사용한 네이티브 컴파일러 환경 전격 투입 해 봅시다.



main/main.go
package main

import (
    "fmt"
)

/*
#include <stdio.h>

void print_from_c() {
    printf("Hello from cgo\n");
}
*/
import "C"

func main() {
    fmt.Println("Hello World")
    C.print_from_c();
}


Go cgo 코드로 Hello합니다.

Dockerfile 이전 node.js 버전과 거의 비슷합니다. Builder 이미지 C 컴파일러 같은 것도 넣고 Go 코드 빌드하고 Runner 최종 결과물만을 입력하여 실행합니다.


Dockerfile
FROM
alpine:latest as builder RUN apk add --no-cache go \ git \ binutils-gold \ curl \ g++ \ gcc \ gnupg \ libgcc \ linux-headers \ make \ python ADD main main WORKDIR main RUN go build FROM alpine:latest as runner RUN apk add --no-cache libc6-compat COPY --from=builder ./main/main ./ CMD ./main



이제 빌드하면 6.53MB입니다. Node.js와 비교하면 1 자리, Java와 비교하면 2 자리 작 네요.

dlopen 사용할 때는 Node.js 항목 참조하십시오.



STEP2 : 작은 명령 줄 옵션

Go 경력 적당히있는 사람이라면 상식

go build -ldflags "-s -w"

시도합니다. Dockerfile에서 빌드하고있는 곳으로 옵션 추가하면됩니다. 이제 조금 작은 바이너리 파일을 만들 수 있습니다.

이제 5.87MB되었습니다. 1 % 가까이 줄어 들었습니다.



STEP3: UPX

upx : Ultimate Packer for eXecutables라는 실행 파일 작게하는 명령 있습니다. Go 단일 바이너리에서 런타임 라이브러리 내장하고 있지만, 적당히 바이너리 커져 버린다 (C 언어에 비해) 단점이 있습니다. upx 바이너리 작게 해 버린다는 명령입니다.

Go 경우 upx 직접 사용하는 것이 아니라 goupx 명령을 통해 사용합니다. 명령 go get으로 가져 올 필요가 있습니다. 이를 위해 GOBIN 환경 변수 설정합니다.



Dockerfile
FROM alpine:latest as builder

RUN apk add --no-cache go \
        git \
        binutils-gold \
        curl \
        g++ \
        gcc \
        gnupg \
        libgcc \
        linux-headers \
        make \
        python \
        upx
RUN mkdir /gobin
ENV GOBIN /gobin
ENV PATH $PATH:/gobin
ADD main main
WORKDIR main
RUN go build -ldflags "-s -w"
RUN go get github.com/pwaller/goupx
RUN goupx main




이제 4.72MB입니다. Go 응용 프로그램 크기 1.5MB 정도에서 500KB 정도가 25 % 정도 감소되었습니다. 덧붙여서, Alpine Linux 본체 크기 4.12MB이므로 절감 효과가 매우 크다는 것을 알 수 있습니다.



정리

다단계 빌드를 사용하면 빌드 분은 이미지 크기를 신경 쓰지 않고 실행 파일의 크기 만 신경 쓰고 Dockerfile를 쓸 수 있습니다. STEP3의 Dockerfile를 보여달라고하면 발견하게 될 것입니다.

지금까지 파일 크기가 작은 이미지를 만들려고하면, RUN 명령 후에는 && \를 부여하여 하나의 명령으로 실행되도록 붓 그리기가 강요되어 버렸습니다. 이것은 확실히 크기 축소는 듣고 있지만, 중간에 캐시되지 않기 때문에 중간에 실패하면 시간의 손실이 큽니다. 또한 어떤 부분에서 오류가 발생했는지를 오류 메시지에서 에스퍼하지 않으면 안됩니다.

다단계되면 명령을 잘게 행당 RUN 있습니다. 이것은 도중에 Docker 이미지 빌드가 실패하고 가운데를보고 싶을 때 매우 도움이됩니다. 또한 자주 캐시되기 때문에 도중에 에러가 발생하고 몇번이나 반복해야한다는 경우도 빌드 시간을 상당히 줄일 수 있습니다. 성능을 위해 작성해 용이성과 유지 보수의 행동을 참을 필요가 없게되었습니다. apk add 등도 1 패키지마다 써도 괜찮을 정도라고 생각합니다 (특히 크기가 큰 gcc 이라든지).

Scratch 이미지를 바탕으로하는 방법과 비교하면 다소 크기는 크지 만 cgo가 유효하고, Alpine이므로, 필요한 도구와 라이브러리를 별도로 다운로드하여 사용할 수 있으며, 네이티브 코드를 사용할 고급 패키지 자유롭게 사용할 수 있습니다. 꽤 Go 생활이 편안하게 게 아닐까요?





반응형

'IT > 인프라' 카테고리의 다른 글

SAN(Storage Area Network)  (0) 2017.12.07
vCenter Server란?  (0) 2017.11.24
ESXi에서 RAC를 구축 [RAC 구축의 사전 작업]  (0) 2017.05.26
Nginx의 로드 밸런서의 구축  (0) 2017.05.26
Redmine과Git의 이행  (0) 2017.05.26
Comments