2016-09-01 10 views
4

私はgolang単体テストをいくつかの外部サービスに依存しているので、ドッカー作成スクリプトでカプセル化したいと思っています。私のアプリケーションにはかなりの依存関係がありますので、しばらくしてgo getにかかります。ドッカービルドでキャッシュ "go get"

テストするたびにすべての依存関係をダウンロードせずにドッカーコンテナを構築できるようにパッケージをキャッシュする方法を教えてください。

マイ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 

私は私のユニットテストを実行するたびに、私は次のスクリプトでdocker-compose up --build backend-testを実行します。

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

しかし、今go-wrapper downloadは私が実行したいたびに呼び出されますテストが完了するまでには時間がかかります。

ソリューション?前もって感謝します!

+1

依存関係を「キャッシュ」する場合は、それをベンダーディレクトリで実行して、キャッシュしたバージョンを正確に把握してください。 'vendor /'を使いたくない場合は、GOPATHにコピーしてください。 – JimB

+0

この種のタスクを実行する方法として[dobi](http://dnephin.github.io/dobi/)に興味があるかもしれません。 Composeは、dobiがこれらのタイプのビルドタスクに焦点を当てているように、実行中のサービスのためにより多く設計されています。 – dnephin

答えて

4

私は個人的に私はgovendorを使用します。 golangのベンダーコンベンションに従って、プロジェクト内のベンダーディレクトリに依存関係を保持します。これはビルド時にドッカーイメージにコピーする必要があります。

しかし、ベンダーにない理由は非常にあります。例えば、あなたがpkgをビルドしているときには、ベンダーに渡すべきではありません。さまざまなバージョンの依存関係を使用している異なるpkgを使用しているときは、面倒です。これは、実行可能ファイルを分類するだけで解決できます。

ベンダーにない理由がある場合は、いくつかのステップを分けることができます。 それらを正しい順序で並べると、処理が速くなります。

依存関係のためにいくつかのgo getコマンドでシェルスクリプト(get.sh)を作成できます。次に、あなたのDockerfileにあなたが最初のシェルスクリプトをコピーし、実行

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 

を(あなたのDockerfileでこれらを置くことができますが、彼らはラインの制限があります)。 get.shを更新するたびに、完全に再構築されます。すべての依存関係が存在することを確認するためにはまだgot get ./...が実行されています。しかし、すべてがget.shスクリプトに追加されれば、あなたはまともなスピードを得るでしょう。

FROM golang:1.6 

RUN mkdir -p /go/src/app 

COPY get.sh /go/src/app 

WORKDIR /go/src/app 

RUN bash get.sh 

COPY . /go/src/app 

RUN go get ./... 

CMD go test -v 

一般的な考え方では、Dockerfileや頻繁に変更されるコンテンツを頻繁に変更しないようにしています。たとえ別のコマンドを1つまたは2つ追加する必要があるとしても。 Dockerはリビルドを必要とするものが見つかるまでそれを1行ずつ表示し、それ以降はすべての行を実行します。

0

私はあなたの質問に対する答えを探していましたが、皮肉なことに私は答えました(ドッカーテストをすばやく実行する方法)。高速テストが本当に必要な場合は、コンテナの実行時にコンテナを再構築することを避けるのが理想的です。しかし、待って、どのように新しいソースコードをコンテナに入れるのですか?ボリューム、私の友人、ボリューム。

ドッカ-compose.dev.ymlを:

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

/パス/に/ myappのはもちろんの画像でパス、である。ここで私はこれを設定した方法ですあなたは明示的にdevに関するこのイメージに合格する必要があります:

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

しかし、あなたは、あなたのテストを実行するとき、あなたはドッカexecを使用するつもりだ今、あなたはもうドッキングウィンドウは、構成を使用するつもりはありません。

docker exec -it backend-test go test 

これを行うと、実際にマウントされたボリュームであるため、バックエンドテストコンテナのsrcディレクトリは常に最新の状態になります。実行中のコンテナに接続してテストを実行すると、毎回新しいコンテナをスピンアップするよりはるかに高速です。

編集:コメント者は、依存関係が変更されていないときに画像を再構築することを唯一避けていることを正しく指摘しました(必要ありません。go get)。いいことは、再構築を避けるだけでなく、再起動を避けることです。私がこのようなテストをしているときに、依存関係を追加すると、通常は私のテストコンソールから直接go getになります。 go getをコンテナ内で動作させるのはちょっと難しいことですが、1つの方法は、mounting SSH_AUTH_SOCKによってコンテナにsshエージェントを転送することです。悲しいことに、ビルド中にボリュームをマウントすることはできません。そのため、ビルドターゲットがテストを実行する前に新しい依存関係を取得できるようにするには、イメージに何らかの種類の配備キーを含める必要があります。しかし、私の答えの要点は、ビルドとテストを分けて、最終的な成果物を生成する準備が整うまで完全なビルドを避けることでした。

これは、私がかもしれないと言いました。は、私があなたがそれに尋ねたやり方で質問に答えていないことを理解しています。ルビーでは、変更したコードをコピーする前に、GemfileとGemfile.lockをコピーしてbundle install --deployを実行するだけの簡単な答えが得られます。私の変更の99%がまだ再構築を伴わないため、個人的に私は依存関係を追加するときに再構築のコストを気にしません。つまり、golangの新しいBundlerインスピレーション依存マネージャー(dep)を使用することができます。 depをインストールすると、Gopkg.tomlGopkg.lockをworkdirにコピーしてdep ensureを実行し、コードをコピーすることができます。これは、Gopkgが更新されたときにのみ依存関係を引き出します。そうでなければ、ドッカーは以前の依存関係がインストールされた状態でキャッシュされたレイヤーを再利用できます。長い編集のために申し訳ありません!

+0

これはうまくいきますが、私の元の質問の一部を無視しています(ここにはあてはまりません)。依存関係が変わった場合でもコンテナを再構築する必要があります。どちらか、またはゴランバイナリ出力フォルダを(永続性のために)ボリュームに入れます。しかし、これは、私がやろうとしていたものとは違うでしょう。テスト全体をコンテナにカプセル化します。 – PiMaker

関連する問題