go build
명령어 실행 시 아래와 같이 지정해주면, 시스템 라이브러리 (libstdc
등)에 의존하지 않는 정적 프로그램으로 빌드할 수 있다.
CGO_ENABLED=0 GOOS=linux GOARCH=$(dpkg --print-architecture) go build -a -ldflags '-w -extldflags "-static"' -o executable_name *.go
Environment Variables
CGO_ENABLE
D=0: [필수] 외부 C 라이브러리에 의존하는 CGO를 비활성화한다.GOOS=linux
: linux OS를 타겟으로 빌드한다. (가능한 값 보기)GOARCH=$(dpkg --print-architecture)
: 현재 빌드하는 시스템 아키텍쳐를 대상으로 빌드한다 (가능한 값 보기)dpkg
명령어에 의존하므로 빌드하는 시스템은 Debian-based여야 한다. Ubuntu OS나 일반적인golang
latest Docker image의 경우 Debian-based이므로 문제가 없다.
Build Arguments
-a
: 이미 빌드된 패키지라고 해도 다시 빌드한다.-ldflags '-w'
: DWARF 디버깅 정보를 삭제(strip)한다.-ldflags '-extldflags "-static"'
: [필수] 외부 링커 (ld
)에게 정적 빌드를 진행함을 알린다.
(Optional) Extra Arguments
-tags netgo
: 시스템 Network 라이브러리 (C-based)를 사용하지 않고 Go 내부의 Network 구현을 사용한다.CGO_ENABLED=0
을 세팅하지 않을 경우 개별 라이브러리를 비활성화할 수 있는듯 하다.
Advantages
정적 프로그램으로 빌드할 경우 libc
를 포함한 외부 라이브러리에 대한 의존이 없어서 단독으로 실행이 가능하다.
예를 들어, 위에서 빌드한 프로그램 ./main
을 아래와 같이 Docker scratch
이미지에 넣고 단독으로 실행이 가능하다 (scratch
이미지의 경우 내용물이 빈 이미지이다.)
mkdir build
cd build
CGO_ENABLED=0 GOOS=linux GOARCH=$(dpkg --print-architecture) \
go build -a -ldflags '-w -extldflags "-static"' -o main ../main.go
cat > Dockerfile <<EOF
FROM scratch
COPY main /main
ENTRYPOINT /main
EOF
docker build . -t my-image:latest
docker run -it --rm my-image:latest