Given a binary, compiled with Go using GOOS=linux
and GOARCH=amd64
, deployed to a docker
container based on alpine:3.3
, the binary will not run if the docker engine host is Ubuntu (15.10):
sh: /bin/artisan: not found
This same binary (compiled for the same OS and arch) will run just fine if the docker engine host is busybox
(which is the base for alpine
) deployed within a VirtualBox VM on Mac OS X.
This same binary will also run perfectly fine if the container is based on one of Ubuntu images.
Any idea what this binary is missing?
This is what I've done to reproduce (successful run in VirtualBox/busybox on OS X not shown):
Build (building explicitly with flags even though the arch matches):
➜ artisan git:(master) ✗ GOOS=linux GOARCH=amd64 go build
Check it can run on the host:
➜ artisan git:(master) ✗ ./artisan 10:14:04.925 [ERROR] artisan: need a command, one of server, provision or build
Copy to docker dir, build, run:
➜ artisan git:(master) ✗ cp artisan docker/build/bin/ ➜ artisan git:(master) ✗ cd docker ➜ docker git:(master) ✗ cat Dockerfile FROM docker:1.10 COPY build/ / ➜ docker git:(master) ✗ docker build -t artisan . Sending build context to Docker daemon 10.15 MB Step 1 : FROM docker:1.10 ... ➜ docker git:(master) ✗ docker run -it artisan sh / # /bin/artisan sh: /bin/artisan: not found
Now changing the image base to phusion/baseimage
:
➜ docker git:(master) ✗ cat Dockerfile #FROM docker:1.10 FROM phusion/baseimage COPY build/ / ➜ docker git:(master) ✗ docker build -t artisan . Sending build context to Docker daemon 10.15 MB Step 1 : FROM phusion/baseimage ... ➜ docker git:(master) ✗ docker run -it artisan sh # /bin/artisan 08:16:39.424 [ERROR] artisan: need a command, one of server, provision or build
To install Docker on Alpine Linux, run apk add --update docker openrc. The Docker package is available in the Community repository. Therefore, if apk add fails because of unsatisfiable constraints error, you need to edit the /etc/apk/repositories file to add (or uncomment) a line.
By default, bash is not included with BusyBox and Alpine Linux. The postmarketOS project, which is designed to run on mobile devices, is based on Alpine Linux. Many Docker images are also based upon Alpine, and you may install bash shell in Docker-based images too.
By default, if using the net
package a build will likely produce a binary with some dynamic linking, e.g. to libc. You can inspect dynamically vs. statically link by viewing the result of ldd output.bin
There are two solutions I've come across:
CGO_ENABLED=0
go build -tags netgo -a -v
, this is implemented for a certain platformsFrom https://golang.org/doc/go1.2:
The net package requires cgo by default because the host operating system must in general mediate network call setup. On some systems, though, it is possible to use the network without cgo, and useful to do so, for instance to avoid dynamic linking. The new build tag netgo (off by default) allows the construction of a net package in pure Go on those systems where it is possible.
The above assumes that the only CGO dependency is the standard library's net
package.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With