Go-kompilierte binary wird nicht in einer alpinen docker-container auf dem Ubuntu-host
Gegeben eine binäre, kompilierte mit Gehen mit GOOS=linux
und GOARCH=amd64
bereitgestellt, um eine docker
container basierend auf alpine:3.3
den binären wird nicht ausgeführt, wenn die docker-engine host ist Ubuntu (15.10):
sh: /bin/artisan: not found
Diese gleichen binary (kompiliert für das gleiche OS und arch) wird laufen nur feine wenn die docker-engine host ist busybox
(die die Basis für alpine
) die Bereitstellung innerhalb einer VirtualBox-VM unter Mac OS X.
Diese selben binäre laufen auch völlig in Ordnung, wenn der container basiert auf einem Ubuntu-images.
Idee, an was das binary fehlt?
Dies ist, was ich getan habe, zu reproduzieren (erfolgreichen Lauf in VirtualBox/busybox auf OS X nicht abgebildet):
Bauen (Gebäude explizit mit Fahnen, obwohl der Bogen entspricht):
➜ artisan git:(master) ✗ GOOS=linux GOARCH=amd64 go build
Überprüfen Sie es ausführen können, auf dem host:
➜ artisan git:(master) ✗ ./artisan
10:14:04.925 [ERROR] artisan: need a command, one of server, provision or build
Kopieren, um das Andockfenster 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
Nun ändern Sie die Basis-image zu 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
- Wirkt sich das hinzufügen CGO_ENABLED=0 helfen?
- Magic, das tut es. Könntest du bitte erläutern Sie in eine Antwort und ich werde Sie akzeptieren.
- Könnten Sie bitte versuchen
go build -tags netgo -a -v std
mit CGO_ENABLED=1? Ich denke, es könnte Probleme mit dem net-Paket, wodurch eine dynamische Verbindung. - Als Sie schlug das half
CGO_ENABLED=1 go build -tags netgo -a -v
. Wenn ich das richtig verstanden habe im Gegensatz zu CGO_ENABLED=0 dadurch wird auch die Erhaltung der TLS-Funktionen im net-Paket, die sonst verloren gehen würden, ist das richtig? Kann ich irgendwie was mit binären statisch und bleibt für dynamic linking? - Standardmäßig CGO kann verwendet werden, für die Netz-Paket - mit den oben genannten tag oder CGO_ENABLED=0 Kräfte der Go-std-Implementierung für lookups verwendet werden - was Sie tun können, ist zu tun:
ldd output.bin
auf jede build-Variante zu sehen, ob Sie wirklich sind statisch kompiliert, oder wenn es keine dynamische Verlinkung geht. - Cool, vielen Dank für die Hilfe und Erklärung!
- Wenn Sie CGO, das binary gelinkt gegen glibc, aber alpine nutzt musl libc. (auch das tls-Paket nicht verwenden, cgo, außer, um root-certs auf darwin)
- Dies scheint ähnlich wie das Problem, das ich hatte und gelöst hier: stackoverflow.com/questions/34729748/...
- Danke für den Tipp. Ich werde es mal ausprobieren, obwohl die Verknüpfung alles, was statisch wäre meine Präferenz.
- Es gibt auch einige alpine glibc Basis von Bildern, die Sie ausprobieren könnten, der sollte sich eine Lösung für Ihr Problem
Du musst angemeldet sein, um einen Kommentar abzugeben.
Standardmäßig, wenn Sie mit der
net
Paket eine bauen, wird wahrscheinlich produzieren eine binäre mit einigen dynamischen Verknüpfung, z.B. auf libc. Sie können prüfen, dynamisch vs. statisch verknüpft werden, indem das Ergebnis derldd output.bin
Gibt es zwei Lösungen, denen ich begegnet bin:
CGO_ENABLED=0
go build -tags netgo -a -v
dies implementiert ist, für eine bestimmte PlattformenVom https://golang.org/doc/go1.2:
Oben davon ausgegangen, dass die nur CGO Abhängigkeit ist die standard-Bibliothek
net
Paket.CGO_ENABLED=0
auch behoben, mein problem: beim ausführen von alpine gebauten go-Programm auf nicht-alpine Andockfenster. Der Fehler in meinem Fall gerade gesagtdocker: Error response from daemon: Container command not found or does not exist..
--features=static --features=pure
flags.Ich hatte das gleiche Problem mit einem go-binary, und ich habe es zu arbeiten, nachdem Sie das hinzufügen dieser auf meine docker-Datei:
RUN apk add --no-cache \
libc6-compat
error relocating ...: fprintf chk: symbol not found
Go-compiler aus dem build-Maschine wahrscheinlich links Ihr binary mit Bibliotheken an anderen Ort als in der alpinen. In meinem Fall war es der Kompilierung mit Abhängigkeiten unter /lib64, aber Alpine nicht verwenden, die Ordner.
Arbeite ich auf Artikel über dieses Problem. Finden Sie den Entwurf mit dieser Lösung hier http://kefblog.com/2017-07-04/Golang-ang-docker .