5

I could really use some help here. What I am trying to do is use the standard golang:1.5 Docker image to build a Go binary, then copy that binary out of the container and into a new minimal Docker container based on busybox. The binary is pulled out of the container using a Docker mounted volume. There are two problems so far that I have run into.

  1. The resulting binary on the host (and subsequently copied into the second container) still seems to be a Mach-O 64-bit executable when running the file command. Is the Docker container somehow getting GOOS and GOARCH from the host?

  2. When manually running the container with bash and building the Go binary, it now says it is an ELF executable but it is dynamically linked. I thought by default built statically linked binaries? I could just be wrong in this assumption.

Thanks in advance for any help you can provide.

EDIT: Here are the commands I am using. Hopefully this makes it a bit more clear

## golang:1.5 base image with WORKDIR set to $GOPATH/src/myproject the source
## for the project was added in when creating the 'mybuild_img' docker image
## GOPATH is set automatically in the golang image.
docker run -i -v `pwd`/jenkins/out:$GOPATH/src/myproject/jenkins/out mybuild_img:latest bash -c 'go build && cp myproject ./jenkins/out'

Once the container is done running I have a Mach-O 64-bit executable in ./jenkins/out/. I'm not sure if this is some kind of weird behavior with docker-machine/boot2docker or anything like that. Just seems really weird. I have confirmed that if i set GOOS=linux GOARCH=amd64 before the go build command, then I do get an executable of the correct type. Just trying to figure out what is going on here.

7
  • did you check and ensure that GOPATH is set right in the container? you may be seeing a OSX compiled version from your mac into the container if GOPATH isn't set. look in the dir of the package you are explicitly compiling, see if binary is there. maybe a simple -o /binname will work Commented Nov 5, 2015 at 21:07
  • 1
    You're going to have to show the steps you're using to do this, because it doesn't really make sense. Re #2, binaries are only static by default if there's no cgo, and the stdlib links to libc for name resolution and user lookup. Commented Nov 5, 2015 at 21:10
  • Added an edit including the docker build command, hopefully it helps and doesn't make it more confusing. Commented Nov 5, 2015 at 21:27
  • docker-machine is running a Linux host, and environment variables aren't transferred. Have you just printed out GOOS and GOARCH from within the container to make sure you haven't set those somewhere? (docker run mybuild_img:latest go env) Commented Nov 5, 2015 at 21:40
  • i didn't think to print the go env but i did add && echo $GOARCH && echo $GOOS at the beginning of the command and they were unset (before explicitly adding them in the workaround i mentioned in my edit.) Commented Nov 6, 2015 at 3:17

1 Answer 1

3

It looks like you are still binding to some C libraries. This is a common problem when moving a Go executable to a super minimal container. You can roll these bound libraries into your executable by changing go build to CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . You can find some more information on this problem and how it relates to minimal docker builds at Codeship's blog.

Sign up to request clarification or add additional context in comments.

2 Comments

This works great. Thanks for your help and sharing that link.
This does not "roll" any linked libraries into your executable. This uses a native go implementation when available (i.e. dns name resolution), or disables the functionality (i.e. user lookups and locating ssl certs on OSX)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.