Original post

I use compiled programs on Alpine Linux by compiling them statically, so that they do not depend on external libraries (which are different on Alpine).
But when I recently tried to run a go “script” directly on an Alpine Linux system, the standard distributed go executable does not run (go 1.13.1). Couldn’t go be compiled statically, so it does not depend on external libraries?

I know there is a go package on Alpine, but I don’t want to install it. I would rather use the go executable from a directory that is shared among several alpine systems (which are actually containers).

Go binaries are statically compiled by default.
but if you are using net or os/user, you will get a dynamically compiled executable (linked against libc)

you will have to provide the netgo and usergo build tags to use the Go-based dns resolver (instead of libc‘s) and the Go-based function to query the Unix user “database” (instead of libc‘s).

So the “go” executable is linked against libc becauses it uses the system’s dns resolver and user database?

I have a go program that uses net/http (it downloads urls, so it uses the dns resolver), and when I link it statically, it runs fine on Alpine. I compile it with this alias:
alias goinstall=‘CGO_ENABLED=0 go install -ldflags ‘’’-extldflags -static’’’’

that works.
but as I said, netgo should accomplish the same:

package main
import _ "net/http"
func main() {}

$> go build -o exe-1 ./main.go
$> go build -o exe-2 -tags netgo ./main.go

$> ldd ./exe-1
        linux-vdso.so.1 (0x00007ffe3abae000)
        libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f4afcdcf000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007f4afcc08000)
        /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f4afce22000)

$> ldd ./exe-2
        not a dynamic executable

Thank you. I didn’t know about -tags netgo, neither about ldd.

I wanted “go”, the Go compiler, to be statically compiled.

I use LXD containers on a host, and I want to use Go on several of them, without installing Go on each one of them. So I unpacked the Go distribution on the host in a directory that is shared with all containers. I then use the same copy of go on all containers. But this only works with containers that have libc (such as ubuntu). It doesn’t work with alpine containers.

I figured out a workaround for alpine linux:

  • Install the alpine version of Go on a temporary alpine/edge container (which has the latest version of go): apk add go
  • Copy /usr/lib/go/ to the host, and share it with all other alpine containers.
  • Delete the container that I originally installed Go to.

I now have one copy of Go for all alpine containers, and one copy of Go for all ubuntu containers (and others with libc).

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.