alpine 이미지의 Dockerfile에 Go를 install하고 싶을 때 빠졌습니다.



by Renée French CC BY 3.0

소개



안녕하세요. Wano 주식회사 엔지니어의 nari라고 합니다.
이번에는 alpine 이미지에 Go를 설치할 때 빠진 사안에 대해 비망록을 남기고 싶습니다.

TL;DR


  • alpine 기반 이미지에 Go를 설치하고 싶다면 wget이나 curl을 사용하지 않고 apk를 사용하십시오.

    이번에 하고 싶은 일



  • codebuild (CI)에서 hashicorp/terraform 이미지에서 apex 명령으로 lambda를 자동 배포하고 싶습니다.

    이번에는 lambda를 Go 언어로 쓰고 있었기 때문에 hook의 build에 Go의 컴파일 환경이 필요하기 때문에 hashicorp/terraform 이미지에 추가로 Go를 설치할 필요가있다


  • 문제


  • hashicorp/terraform은 alpine 기반입니다. 거기에 Go를 codebuild의 buildspec.yml에 다음과 같이 설치하려고했습니다
  • export GO_VERSION=1.12.4
    wget https://storage.googleapis.com/golang/go{GO_VERSION}.linux-amd64.tar.gz
    tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz
    export PATH=$PATH:/usr/local/go/bin
    go version
    

    그러면 go 버전을 실행할 때 다음과 같은 오류가 발생했습니다.
    sh: go: not found
    

    오류 솔루션



  • docker - How to install Go in alpine linux - Stack Overflow 에 비슷한 케이스가 있었기 때문에 참고했다

  • With Alpine, you have libmusl instead of glibc. Alpine's libmusl is not a 1 for 1 replacement. Code linked against glibc will show a not found error which is actually from the dynamic linker. You can see what libraries are link :

    분명히, glibc 대신에 들어있는 libmusl (linux 표준의 C 라이브러리)의 거동이 다른 것 같습니다.
     # ldd /usr/local/go/bin/go
            /lib64/ld-linux-x86-64.so.2 (0x7f63ceed1000)
            libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7f63ceed1000)
            libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f63ceed1000)
    

    글쎄,/lib64/ld-linux-x86-64.so.2가 alpine에 없기 때문에 거기에 dynamic link가있는/usr/local/go/bin/go는 not found error를 반환합니다. 네

    이 분은 Go 바이너리를 실행하는 형태(go 자체의 다운로드를 하지 않는다)로 하는지, glibc를 넣을까(그렇다면 CentOS라든지 Debian 사용해라)라고 말하고 있습니다만, 어느 쪽의 해결안도 사용하지 않고 이하 처럼 해결했습니다.
    apk add --update --no-cache vim git make musl-dev go curl
    
    # Configure Go
    export GOPATH=/root/go
    export PATH=${GOPATH}/bin:/usr/local/go/bin:$PATH
    export GOBIN=$GOROOT/bin
    mkdir -p ${GOPATH}/src ${GOPATH}/bin
    export GO111MODULE=on
    go version
    

    원래도 아이도 없는 apk에서의 다운로드 작전, ,,apk는 역시 편리하네요 라는 이야기였습니다.

    끝에



    기존의 이미지에 추가로 환경을 넣고 싶을 때에는, 우선 그 이미지의 베이스 이미지를, dockerHub로부터 추적해 Dockerfile로부터 확인하는 것이 중요하네요.

    C 라이브러리군의 지식 등 전혀 없구나와 통감하게 되었습니다만, 지금은 StackOverflow등에 꽤 니어리한 케이스에 빠져 있던 선인의 케이스가 있어 매우 도움이 됩니다.

    이렇게 말한 버터 구이의 솔루션뿐만 아니라 어딘가에서 깊은 곳까지 C 라이브러리의 공부 등도 해 나가고 싶네요.

    참고문헌


  • docker - How to install Go in alpine linux - Stack Overflow
  • Alpine Linux 있다 - Qiita
  • man libc (7) : Linux 표준 C 라이브러리 개요
  • 좋은 웹페이지 즐겨찾기