2016-09-01 3 views
4

Ich möchte meine Golong-Unit-Tests in einem Docker-Compose-Skript kapseln, weil es auf mehrere externe Dienste angewiesen ist. Meine Anwendung hat ziemlich viele Abhängigkeiten, so dass es eine Weile dauert, bis go get.Cache "go get" in docker build

Wie kann ich Pakete so zwischenspeichern, dass der Docker-Container erstellt werden kann, ohne dass jedes Mal, wenn ich testen möchte, alle Abhängigkeiten heruntergeladen werden müssen?

Mein Dockerfile:

FROM golang:1.7 

CMD ["go", "test", "-v"] 

RUN mkdir -p /go/src/app 
WORKDIR /go/src/app 

COPY . /go/src/app 
RUN go-wrapper download 
RUN go-wrapper install 

Jedes Mal, wenn ich möchte, dass meine Unit-Tests laufen Ich betreibe docker-compose up --build backend-test auf dem folgenden Skript:

version: '2' 
services: 
    ... 
    backend-test: 
    build: 
     context: . 
     dockerfile: Dockerfile 
    image: backend-test 
    depends_on: 
     ... 

Aber jetzt go-wrapper download wird jedes Mal, wenn ich will so genannte laufen Tests und es dauert eine lange Zeit zu vervollständigen.

Lösungen? Danke im Voraus!

+1

Wenn Sie die Abhängigkeiten "zwischenspeichern" möchten, tun Sie dies in einem Lieferantenverzeichnis, damit Sie genau wissen, welche Version Sie zwischengespeichert haben. Wenn Sie 'vendor /' nicht verwenden möchten, kopieren Sie einfach in Ihren GOPATH. – JimB

+0

Sie könnten an [dobi] (http://dnephin.github.io/dobi/) interessiert sein, um diese Art von Aufgaben auszuführen. Compose ist eher für die Ausführung von Diensten gedacht, wobei sich dobi auf diese Art von Build-Aufgaben konzentriert. – dnephin

Antwort

4

Persönlich verwende ich govendor. Es hält Ihre Abhängigkeiten in einem Vendor-Verzeichnis in Ihrem Projekt gemäß den Konventionen des Golfang-Anbieters. Dies muss beim Build weiterhin in das Docker-Image kopiert werden.

Aber es gibt sehr gute Gründe, nicht zu verkaufen. Zum Beispiel, wenn Sie ein Paket erstellen, sollten Sie nicht Anbieter. Wenn Sie verschiedene Pakete verwenden, die verschiedene Versionen von Abhängigkeiten verwenden, werden die Dinge unordentlich. Dies kann dadurch behoben werden, dass nur ausführbare Dateien verkauft werden.

Also, wenn Sie einen guten Grund haben, nicht zu verkaufen, können Sie ein paar Schritte trennen. Wenn Sie sie in die richtige Reihenfolge bringen, wird die Sache beschleunigt.

Sie können ein Shell-Skript (get.sh) mit einigen go get Befehlen für Abhängigkeiten erstellen. (Sie können diese in Ihrem Dockerfile setzen, aber sie haben eine Linie Grenze)

go get github.com/golang/protobuf/proto 
go get github.com/pborman/uuid 
go get golang.org/x/net/context 
go get golang.org/x/net/http2 
go get golang.org/x/net/http2/hpack 

Dann in Ihrem Dockerfile Sie erste Kopie und führen Sie das Shell-Skript. Jedes Mal, wenn Sie get.sh aktualisieren, wird es vollständig neu erstellt. Es läuft immer noch , um sicherzustellen, dass alle Abhängigkeiten vorhanden sind. Aber wenn alles im Skript get.sh hinzugefügt wird, erhalten Sie einen ordentlichen Geschwindigkeitsschub.

Die allgemeine Idee ist, dass Sie häufig ändern Inhalt in Ihrer Dockerfile und Sachen, die ziemlich konstant an der Spitze ist. Selbst wenn Sie ein oder zwei weitere Befehle hinzufügen müssen. Docker wird Zeile für Zeile gehen, bis es etwas findet, das eine Neuerstellung benötigt, und danach alle Zeilen bearbeiten wird.

0

Ich war auf der Suche nach einer Antwort auf Ihre Frage, aber ironisch fand eine Frage, ich habe eine Antwort auf (wie Docker Tests schnell ausführen). Wenn Sie wirklich schnelle Tests wünschen, sollten Sie idealerweise vermeiden, den Container neu aufzubauen, wenn Sie ihn ausführen. Aber warte, wie bekomme ich den neuen Quellcode auf den Container? Volumes mein Freund, Bände. Hier ist, wie ich dies eingerichtet haben:

Docker-compose.dev.yml:

backend-test: 
    volumes: 
    - .:/path/to/myapp 

Wo/path/to/myapp den Pfad im Bild ist, natürlich.

docker-compose up -f docker-compose.dev.yml 

Aber jetzt, wenn Sie Ihre Tests ausführen, sind Sie nicht mehr Docker-komponieren nicht benutzen wollen, Sie gehen Docker exec verwenden: Sie werden explizit in diesem Bild für Entwickler passieren müssen:

docker exec -it backend-test go test 

Wenn Sie dieses Recht tun, Sie src dir im Container Backend-Tests wird immer auf dem neuesten Stand sein, weil es in der Tat ist ein bereitgestelltes Volume. Das Anhängen an einen laufenden Container und das Ausführen von Tests sollten sich als viel schneller erweisen, als jedes Mal ein neues zu erstellen.

EDIT: Commenter richtig darauf hingewiesen, dass dies nur Neuaufbau des Bildes vermeidet, wenn Ihre Abhängigkeiten nicht geändert haben (keine Notwendigkeit go get). Das Schöne ist, dass es nicht nur den Wiederaufbau vermeidet, sondern auch den Neustart verhindert. Wenn ich so teste, und ich eine Abhängigkeit hinzufüge, ich normalerweise nur go get direkt von meiner Testkonsole. Es kann ein bisschen schwierig sein, go get in Ihrem Container zu arbeiten, aber eine Möglichkeit besteht darin, Ihren ssh-Agenten durch mounting SSH_AUTH_SOCK an Ihren Container weiterzuleiten. Leider können Sie während des Builds keine Volumes bereitstellen. Daher müssen Sie möglicherweise einen Bereitstellungsschlüssel in Ihr Image einfügen, wenn das Build-Ziel vor dem Ausführen von Tests neue Abhängigkeiten abrufen soll. Der Hauptpunkt meiner Antwort war jedoch, den Build und Test zu trennen, um den vollständigen Build zu vermeiden, bis Sie bereit sind, das endgültige Artefakt zu generieren.

Das sagte, ich denke, ich könnte verstehen, dass ich die Frage nicht in der Art beantworte, wie Sie es gefragt haben. In Ruby ist die Antwort so einfach wie das Kopieren der Dateien Gemfile und Gemfile.lock und das Ausführen von bundle install --deploy, bevor Sie den Code kopieren, den Sie geändert haben. Persönlich stört es mich nicht die Kosten für den Wiederaufbau, wenn ich Abhängigkeiten hinzufüge, da 99% meiner Änderungen immer noch keine Wiederherstellung beinhalten. Das heißt, Sie könnten den neuen von Bundan inspirierten Abhängigkeitsmanager verwenden: dep. Wenn dep installiert ist, bin ich mir ziemlich sicher, dass Sie einfach Ihre Gopkg.toml und Gopkg.lock in Ihr workdir kopieren, dep ensure ausführen und dann Ihren Code kopieren können. Dadurch werden nur Abhängigkeiten gezogen, wenn Gopkg aktualisiert wurde. Anderenfalls kann docker die zwischengespeicherte Ebene mit den zuvor installierten Abhängigkeiten wiederverwenden. Entschuldigung für die lange Bearbeitung!

+0

Das funktioniert, aber ignoriert einen Teil meiner ursprünglichen Frage (so nicht sicher, dass es hier passt): Ihre Lösung beinhaltet überhaupt nicht "gehen". Wenn sich Abhängigkeiten ändern, müssen Sie den Container noch neu erstellen. Entweder das oder du legst den Golan-Binary-Output-Ordner auch in ein Volume (für Persistence) - aber das wäre gegen das, was ich versucht habe zu tun, indem ich die Gesamtheit des Tests in den Container kapsle. – PiMaker