Docker and CGO

CREATED | Created in 2023. 07. 06.

CATEGORY | Dev


개인적으로 제작하던 간단한 Golang 프로젝트의 컨테이너를 배포하던 와중 이러한 문제를 마주쳤습니다:

Checking SQLite3...
2023/07/06 13:01:29 Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub


해당 문제는 프로젝트가 특정한 라이브러리를 쓰고 있기 때문에 발생합니다.
빌드에서 문제가 되는 해당 라이브러리에서 CGO를 사용하고 있기 때문에 빌드가 되지 않을 것을 알 수 있습니다.

CGO는 이름에서 보이는 것 처럼 C + GO, C의 기능을 빠르게 Go로 바인딩할 수 있도록 Go에서 자체적으로 지원하는 기능입니다.

당연하게도 이런 C 코드를 포함하는 코드를 전체적으로 컴파일하기 위해선 CGO를 포함하도록 컴파일 옵션이 지정되어야 합니다.
저는 프로젝트에서 Base Image로 golang-alpine을 사용 중입니다만, 해당 이미지에선 CGO가 기본값으로 켜져있지 않습니다.

해당 옵션을 활성화하기 위해 CGO_ENABLED 값을 1로 설정해줍니다.

RUN CGO_ENABLED=1 GOOS=linux go build -o TARGET_NAME


하지만, 생각과는 달리 해당 오류가 발생해버리게 됩니다:

Removing intermediate container 4b817f1853d5
---> ebc4f80cc34b
Step 7/11 : RUN CGO_ENABLED=1 GOOS=linux go build
---> Running in 294f5372b5cb
# runtime/cgo
cgo: C compiler "gcc" not found: exec: "gcc": executable file not found in $PATH
The command '/bin/sh -c CGO_ENABLED=1 GOOS=linux go build' returned a non-zero code: 1


오류 내용만 봐도 알 수 있습니다. 툴체인이 없어서 발생하는 문제입니다.
툴체인을 설치해줍시다.

RUN apk add --no-cache --update build-base


해당 툴체인을 설치할 시 크게 문제 없이 컴파일이 완료되는 모습을 볼 수 있습니다.

완성된 Dockerfile은 다음과 같습니다:

FROM golang:alpine AS builder
WORKDIR /app

COPY . .
COPY go.mod .
COPY go.sum .

RUN apk add --no-cache --update build-base
RUN go get -u -d -v
RUN CGO_ENABLED=1 GOOS=linux go build -o TARGET_NAME

FROM alpine:latest
WORKDIR /app

COPY --from=builder /app/TARGET_NAME ./
CMD [ "./TARGET_NAME" ]


해당 라이브러리가 요구하는 툴체인을 적절하게 설치해주면 됩니다.