Abe Estrada

Go Brotli Docker

Estoy trabajando en una función que se ejecutab en AWS Lambda programada con Go, para lo cual necesito comprimir la respuesta con Brotli , el problema es que utlizo macOS para compilar para linux/arm64 y al utilizar la libreria de Google escrita en C, me marca ciertos errores.

El código que utilicé para hacer mis pruebas, es el siguiente:

package main

import (
    "encoding/base64"
    "fmt"
    "github.com/google/brotli/go/cbrotli"
)

func main() {
    enc, err := cbrotli.Encode(
        []byte("Hello world!"),
        cbrotli.WriterOptions{Quality: 6},
    )
    if err != nil {
        panic(err)
    }
    str := base64.StdEncoding.EncodeToString(enc)
    fmt.Println(str)
}

Al intentar compilar en macOS 13 (M2 Max), me informa que necesito los headers de Linux y no estan disponibles en homebrew (por el momento).

❯ CGO_ENABLED=1 GOARCH=arm64 GOOS=linux go build -v -tags lambda.norpc -o bootstrap .
runtime/cgo
# runtime/cgo
linux_syscall.c:67:13: error: call to undeclared function 'setresgid'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
linux_syscall.c:67:13: note: did you mean 'setregid'?
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/unistd.h:593:6: note: 'setregid' declared here
linux_syscall.c:73:13: error: call to undeclared function 'setresuid'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
linux_syscall.c:73:13: note: did you mean 'setreuid'?
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/unistd.h:595:6: note: 'setreuid' declared here

Así que recurrí a Docker para poder compilar el código para linux/arm64 desde una imagen oficial de Go (basada en Debian 12 ‘bookworm’) con el siguiente comando:

docker run --rm \
-v "$PWD":/usr/src/app \
-w /usr/src/app \
-e CGO_ENABLED=1 -e GOARCH=arm64 -e GOOS=linux \
golang:1.21 \
/bin/bash -c "apt update;apt -y install libbrotli-dev;go build -v -tags lambda.norpc -o bootstrap ."

Desglozando el comando anterior:

  • --rm automáticamente elimina el contenedor al salir
  • -v va a crear un volúmen el directorio actual dentro del contenedor
  • -w establece que el volúmen creado sea nuestro directorio de trabajo
  • -e define variables de entorno
  • golang:1.21 la imagen que vamos a utilizar
  • /bin/bash -c "..." es el comando que el contenedor va a ejecutar
  • apt update actualiza los paquetes
  • apt -y install libbrotli-dev instala los archivos necesarios
  • go build -v -tags lambda.norpc -o bootstrap . compila el código

El binario compilado va a aparecer en el directorio de nuestra computadora (gracias a que montamos el directorio con -v) y podemos confirmar que fue compilado para linux/arm64:

❯ file bootstrap
bootstrap: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV),
dynamically linked, interpreter /lib/ld-linux-aarch64.so.1,
BuildID[sha1]=ad6da5ae6e73d8cbbfac5cb9ff569cdceea58a05,
for GNU/Linux 3.7.0, with debug_info, not stripped

Fuentes