Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiled releases are dynamically linked #83

Closed
keymon opened this issue Jan 5, 2016 · 4 comments
Closed

Compiled releases are dynamically linked #83

keymon opened this issue Jan 5, 2016 · 4 comments
Assignees

Comments

@keymon
Copy link
Contributor

keymon commented Jan 5, 2016

The releases published in this repo are dynamically linked:

$ file spruce
spruce: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped

This can be a problem in scenarios like docker alpine. For instance, this Dockerfile, if you build it:

cat <<EOF > Dockerfile
FROM alpine:3.3

ENV SPRUCE_VERSION 0.13.0

RUN apk add --update wget ca-certificates \
  && wget https://github.com/geofffranks/spruce/releases/download/v${SPRUCE_VERSION}/spruce_${SPRUCE_VERSION}_linux_amd64.tar.gz \
  && tar -xvzf spruce_${SPRUCE_VERSION}_linux_amd64.tar.gz \
  && mv spruce_${SPRUCE_VERSION}_linux_amd64/spruce /usr/local/bin/ \
  && rm -rf spruce_${SPRUCE_VERSION}_linux_amd64* \
  && apk del wget ca-certificates \
  && rm -rf /var/cache/apk/*
EOF
docker build -t alpine-spruce .
docker run -i -t alpine-spruce ldd /usr/local/bin/spruce

It fails:

$ docker run -i -t alpine-spruce ldd /usr/local/bin/spruce
    /lib64/ld-linux-x86-64.so.2 (0x557b2cfc0000)
    libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x557b2cfc0000)
    libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x557b2cfc0000)
Error relocating /usr/local/bin/spruce: __vfprintf_chk: symbol not found

In this thread they discuss the topic and it seems that the magic solution is compile the binary with:

go build -tags netgo -installsuffix netgo .

Which indeed generates a static file:

$ file spruce 
spruce: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), statically linked, not stripped
@keymon keymon changed the title Releases compiled dynamically linked Compiled releases are dynamically linked Jan 5, 2016
@keymon
Copy link
Contributor Author

keymon commented Jan 5, 2016

It seems that go1.5 stabilises this:

$ go version
go version go1.5 linux/amd64
$ CGO_ENABLED=0 go build .
$ file spruce 
spruce: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), statically linked, not stripped

More info: https://golang.org/cmd/cgo/

@jhunt
Copy link
Collaborator

jhunt commented Jan 11, 2016

I believe this is a disparity between how gox and go build do things, and how goxc (used by release pipelines) does things:

$ gox -osarch linux/amd64
...
$ file spruce_linux_amd64
spruce_linux_amd64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

@keymon: what happens if you just go build (without the -tags) on a Linux platform?

@keymon
Copy link
Contributor Author

keymon commented Jan 12, 2016

With both Go 1.4 and Go 1.5 it compiles dynamically:

$ cd $GOPATH/src/github.com/geofffranks/spruce
$ go build ./...
$ file spruce 
spruce: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped

But with GO 1.5, you can get a static binary if you set the environment variable CGO_ENABLED=0:

$ go version
go version go1.5 linux/amd64
$ CGO_ENABLED=0 go build ./...
$ file spruce 
spruce: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), statically linked, not stripped

Instead, with go 1.4, that environment variable does not work, and the workaround is using the -tags

$ go version
go version go1.4 linux/amd64
$ CGO_ENABLED=0 go build ./...
$ file spruce 
spruce: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
$ rm spruce 
$ go build -tags netgo -installsuffix netgo ./...
$ file spruce 
spruce: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), statically linked, not stripped

@keymon
Copy link
Contributor Author

keymon commented Jan 12, 2016

So, basically, if you compile it with Go 1.5 and export CGO_ENABLED=0, we should be fine.

@jhunt jhunt self-assigned this Jan 12, 2016
jhunt added a commit that referenced this issue Jan 12, 2016
keymon added a commit to alphagov/paas-docker-cloudfoundry-tools that referenced this issue Mar 8, 2016
We have been using the version 0.13.0 of spruce, but compiling it
in the Dockerfile because the release binary version did link to
the debian/ubuntu libc. We were not pinning the git commit of the
spruce code.

But the upstream project has some changes that makes fail the build,
probably new dependencies added which require the use of godep.

As since geofffranks/spruce#83 the binary
in the releases is OK and can work in a plain alpine, we can create
a container pulling the binary release. This will simplify our
container, make it smaller and pin the version number.
keymon added a commit to alphagov/paas-docker-cloudfoundry-tools that referenced this issue Mar 8, 2016
We have been using the version 0.13.0 of spruce, but compiling it
in the Dockerfile because the release binary version did link to
the debian/ubuntu libc. We were not pinning the git commit of the
spruce code.

But the upstream project has some changes that makes fail the build,
probably new dependencies added which require the use of godep.

As since geofffranks/spruce#83 the binary
in the releases is OK and can work in a plain alpine, we can create
a container pulling the binary release. This will simplify our
container, make it smaller and pin the version number.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants