web-dev-qa-db-ja.com

Dockerイメージを1つのコンテナーに結合する方法はありますか?

現在、いくつかのDockerfileがあります。

1つはCassandra 3.5用で、FROM cassandra:3.5です

また、KafkaのDockerfileもありますが、tはかなり複雑です。これはFROM Java:openjdk-8-freであり、KafkaとZookeeperをインストールする長いコマンドを実行します。

最後に、SBTを使用するScalaで記述されたアプリケーションがあります。

そのDockerfileの場合、Java 8、Scala 2.11.7、およびSTB 0.13.9を取得するFROM broadinstitute/scala-baseimageが必要です。

おそらく、私はDockerがどのように機能するか理解していませんが、私のScalaプログラムには、依存関係としてCassandraおよびKafkaがあり、開発目的のために、 Dockerfileを使用してレポジトリを複製し、Cassandra、Kafka、Scala、JavaおよびSBTを使用してビルドして、ソースをコンパイルできるようにします。しかし、これには多くの問題があります。

これらのDockerfileを結合するにはどうすればよいですか?これらのものを焼き付けた環境を単純に作成するにはどうすればよいですか?

45
David

Docker 1.17で導入されたマルチステージビルド機能を使用すると、

これを見てください:

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM Alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

その後、通常どおりイメージをビルドします。

docker build -t alexellis2/href-counter:latest

From: https://docs.docker.com/develop/develop-images/multistage-build/

最終的な結果は、以前と同じ小さな生産イメージであり、複雑さが大幅に削減されます。中間画像を作成する必要も、ローカルシステムにアーティファクトを抽出する必要もありません。

どのように機能しますか? 2番目のFROM命令は、Alpine:latestイメージをベースとして新しいビルドステージを開始します。 COPY --from = 0行は、ビルドされたアーティファクトのみを前のステージからこの新しいステージにコピーします。 Go SDKおよび中間成果物はすべて残され、最終イメージには保存されません。

56

競合が発生する可能性があるため、dockerfileを結合することはできません。やりたいことは、新しいdockerfileを作成するか、カスタムイメージを作成することです。

TL; DR;現在の開発コンテナに必要なすべてのツールが含まれており、動作している場合は、それをイメージとして保存し、リポジトリに保存し、そのイメージからそのリポジトリからプルするdockerfileを作成します。

詳細:カスタムイメージの構築は、公開画像を使用してdockerfileを作成するよりもはるかに簡単です。ハックやmodを画像に保存できるからです。そのためには、基本的なLinuxイメージ(またはbroadinstitute/scala-baseimage)で空のコンテナーを起動し、必要なツールをインストールして、すべてが正しく機能するまでそれらを構成し、イメージ(コンテナー)として保存します。このイメージから新しいコンテナーを作成し、docker-composeを使用してその上にコードをビルドできるかどうかをテストします(または、実行/ビルドを行います)。それが機能する場合、他の人がそれをプルできるようにレポにアップロードできる作業ベース画像を持っているよりも。

パブリックイメージを使用してdockerfileを構築するには、すべてのハック、MOD、およびセットアップをdockerfile自体に配置する必要があります。つまり、使用したすべてのコマンドラインをテキストファイルに配置し、ハック、改造、セットアップをコマンドラインに減らす必要があります。最後に、dockerfileは自動的に画像を作成します。この画像をレポジトリに保存する必要はありません。他の人にdockerfileを与えるだけで、自分のdockerで画像をスピンアップできます。

作業用のdockerfileを作成したら、dockerfileを使用するたびに新しいイメージが作成されるため、簡単に調整できます。カスタムイメージを使用すると、競合のためにイメージを再構築する必要がある問題が発生する場合があります。たとえば、動作しないツールをインストールするまで、すべてのツールはopenjdkで動作します。修正には、openjdkのアンインストールとOracleの使用が含まれる場合がありますが、インストールしたすべてのツールに対して行ったすべての構成が壊れています。

20
Hin Fan Chan

はい、あなたはすべてのソフトウェアを単一のDockerイメージに(ロールできます( GitLab はこれを行い、Postgresと他のすべてを含む1つのイメージで)、しかし、 generalhenry は正しい-Dockerを使用する一般的な方法ではありません。

あなたが言うように、CassandraとKafkaはScalaアプリのdependenciesです。それらはアプリの一部ではないため、すべてが同じイメージに属しているわけではありません。

Docker Composeを使用して多くのコンテナをオーケストレーションする必要があるため、追加の管理レイヤーが追加されますが、柔軟性が大幅に向上します。

  • コンテナのライフスパンは異なる可能性があるため、デプロイするアプリの新しいバージョンがある場合、新しいアプリコンテナを実行するだけで、依存関係を実行したままにすることができます。
  • 依存関係に異なる設定を使用して、あらゆる環境で同じアプリイメージを使用できます。開発では、基本的なKafkaコンテナを実行できます。また、多くのノードでクラスタ化されている場合、アプリコンテナは同じです。
  • 依存関係は他のアプリでも使用できるため、複数のコンシューマーを異なるコンテナーで実行でき、すべてが同じKafkaおよびCassandraコンテナーで動作します。
  • さらに、前述のすべてのスケーラビリティ、ロギングなども含まれます。
4
Elton Stoneman

次の回答は、Docker 1.7以降に適用されます。

--from=NAMEfrom image as NAMEを使用したいのはなぜですか? --from=0以上を使用できますが、dockerfileに多数のdockerステージがある場合、これを管理するのはほとんど難しくなりません。

サンプル例:

FROM golang:1.7.3 as backend
WORKDIR /backend
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN  #install some stuff, compile assets....

FROM golang:1.7.3 as assets
WORKDIR /assets
RUN ./getassets.sh

FROM nodejs:latest as frontend 
RUN npm install
WORKDIR /assets
COPY --from=assets /asets .
CMD ["./app"] 

FROM Alpine:latest as mergedassets
WORKDIR /root/
COPY --from=merge ./
COPY --from=backend ./backend .
CMD ["./app"]

注:dockerfileを適切に管理することは、Dockerイメージをより速く構築するのに役立ちます。イメージを再構築する必要がある場合に備えて、内部でdockerはこのプロセスを支援するためにDockerレイヤーキャッシングを使用します。

3
РАВИ

Dockerイメージを1つのコンテナに結合できませんでした。 Mobyの問題の詳細な説明を参照してください Dockerfileで複数の画像を1つに結合する方法

あなたの場合、CassandraとKafkaの画像全体を含めない方が良いでしょう。アプリケーションには、Cassandra ScalaドライバーとKafka Scalaドライバーのみが必要です。コンテナにはドライバーのみを含める必要があります。

1
CloudStax

Dockerはイメージのマージを行いませんが、利用可能な場合はdockerfilesを結合し、ビルドする必要のある太いイメージにロールインすることを止めるものは何もありません。ただし、これが理にかなっている場合がありますが、コンテナで複数のプロセスを実行する場合、ほとんどのDockerドグマは、特にマイクロサービスアーキテクチャではこれをあまり望ましくないと指摘します(ただし、ルールは正しくありませんか?)

1
Amos Folarin