Docker Compose対Dockerfile-どちらが良いですか?


384

私はDockerを読んで学び、使用するDjangoセットアップを正しく選択しようとしています。これまでのところ、次のいずれかがあります。

Docker ComposeまたはDockerfile

Dockerfiles使用されていることは理解していますがDocker Compose、すべてを1つの大きなDockerfileに配置しFROMて、さまざまなイメージに対して複数のコマンドを使用するのが良い方法かどうかわかりません。

以下を含むいくつかの異なる画像を使用したいと思います。

uwsgi
nginx
postgres
redis
rabbitmq
celery with cron

Dockerを使用してこのタイプの環境をセットアップする際のベストプラクティスについてアドバイスしてください。

それが役立つ場合、私はMacを使用しているので、boot2dockerを使用します

私が持っていたいくつかの問題:

  1. Docker ComposeはPython3と互換性がありません
  2. プロジェクトをコンテナ化したいので、1つの大きなDockerfileが理想的でない場合は、Docker Composeを使用して分割する必要があると思います
  3. 私はプロジェクトをPy2とPy3に互換性があるようにしてもいいので、django-composeに傾いています

5
問題は「アプリを単一または複数のコンテナーとして実行する必要がありますか?」とより適切に表現されます。それは依存しているようで、懸念事項のスケーリングと分離の問題(サービスごとに1つのコンテナー)を考慮する必要があります。これらのかもしれないのヘルプ:stackoverflow.com/questions/30534939/...quora.com/...
ファビアンSnauwaert

回答:


238

答えはどちらでもありません。

プロジェクトのビルドにビルドコマンドを追加すると、Docker Compose(ここではcomposeと呼びます)はDockerfileを使用します。 docker-compose.yml

DockerワークフローはDockerfile、作成するイメージごとに適切なものをビルドし、composeを使用して、buildコマンドを使用してイメージを組み立てることです。

build /path/to/dockerfiles/blahwhere /path/to/dockerfiles/blahがblahのDockerfile住む場所を使用して、個々のDockerfileへのパスを指定できます。


10
docker-composeプロダクションで使用しますか、それとも開発者のみですか?ご協力いただきありがとうございます。
アーロンLelevier

18
@booyaa詳しく説明していただけますか?
Martin Thoma

2
答えてくれてありがとう!Dockerfileはイメージの構成を指定し、docker-compose.ymlはイメージを一緒にアセンブルします。1つ指摘したいのは、docker-compose.ymlパブリックイメージのみを使用する場合(インターネット/ドッカーハブからイメージをプルする場合)、必要ありません。コマンドを実行するDockerfile docker-compose up
Oldyoung

549

Dockerfile

ここに画像の説明を入力してください

Dockerfileは、ユーザーがイメージを組み立てるために呼び出すことができるコマンドを含む単純なテキストファイルです。

例、 Dockerfile

FROM ubuntu:latest
MAINTAINER john doe 

RUN apt-get update
RUN apt-get install -y python python-pip wget
RUN pip install Flask

ADD hello.py /home/hello.py

WORKDIR /home

Docker Compose

ここに画像の説明を入力してください

Docker Compose

  • マルチコンテナDockerアプリケーションを定義して実行するためのツールです。

  • アプリを構成するサービスを定義docker-compose.ymlして、隔離された環境で一緒に実行できるようにします。

  • 実行するだけで、1つのコマンドでアプリを実行できます docker-compose up

例、 docker-compose.yml

version: "3"
services:
  web:
    build: .
    ports:
    - '5000:5000'
    volumes:
    - .:/code
    - logvolume01:/var/log
    links:
    - redis
  redis:
    image: redis
    volumes:
      logvolume01: {}

43
@sg答えは、Docker対Docker Composeの理解の欠如に基づいて質問の形式が正しくないということです。2つがどのように相互作用するかを簡潔に説明することは、おそらく私が考えることができる最良の答えです。
mpowered

53
この正確な内訳がDockerのホームページに掲載されていない理由はわかりません。ありがとう。
codykochmann

4
最近リリースされたWeb上のツール/ソリューション/フレームワークには、この種のドキュメントがありません。自分ですでにソリューションを知っている/発明した場合に、なぜ誰かがそれを必要とするのかを理解するのは難しいと思います。
Peter Branforn、

36
この回答に欠けているのは、作成に関する詳細情報です。作成スクリプトはdockerfileを呼び出しますか?何を構成するかをどのようにして知るのですか?例は示してimage: redisいますが、それはdockerhubからのものですか?ローカルディレクトリ?etc ...これは、私のような新米が本当に何が起こっているのかを理解するのを混乱させます
Joe Phillips

5
この応答は、Docker Composeのマルチコンテナーの目的を主張していますが、コンテナーを実行するポートを指定するなど、コンテナーが1つだけの場合でも、Docker Composeを使用するシナリオは他にもたくさんあります(dockerfile afaikでは不可能)。
Pansoul

99

作曲ファイルには、説明して実行している状態で容器をする方法の詳細残して、コンテナを構築するDockerfilesをhttp://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volumes

開発中にComposeを使用してアプリ定義すると、この定義を使用してCI、ステージング、本番などのさまざまな環境で アプリケーションを実行できますhttps://docs.docker.com/compose/production/

また、作曲が考慮されていないように思われる1.11のような製造安全以来、https://docs.docker.com/v1.11/compose/production/はもはやように生産にそれを使用しないよう警告あります。https://ドキュメント.docker.com / v1.10 / compose / production /にはあります。


1
問題を提起してくれてありがとう。1.11での生産の安全のために修正されたものをさらに追加していただけますか?
MA Hossain Tonu 2017年

93

docker-composeは、docker-cliを使用して大量のコマンドを作成する必要があるために存在します。

docker-composeを使用すると、同時に複数のコンテナーを簡単に起動して、何らかの形のネットワークでそれらを自動的に接続することもできます。

docker-composeの目的は、docker cliとして機能することですが、複数のコマンドをより迅速に発行することです。

docker-composeを使用するには、以前実行していたコマンドをdocker-compose.ymlファイルにエンコードする必要があります。

コピーしてyamlファイルに貼り付けるだけではなく、特別な構文があります。

作成したら、それをdocker-compose cliにフィードする必要があります。ファイルを解析し、指定した正しい構成ですべての異なるコンテナーを作成するのはcliです。

したがって、別々のコンテナが作成されます。たとえば、1つredis-server目は2つ目で、現在のディレクトリのnode-appを使用して作成したいとDockerfileします。

さらに、そのコンテナーを作成した後、コンテナーからローカルマシンにポートをマッピングして、コンテナー内で実行されているすべてにアクセスします。

したがって、docker-compose.ymlファイルの場合、最初の行を次のように開始する必要があります。

version: '3'

これによりdocker-compose、使用するバージョンがDockerに通知されます。その後、追加する必要があります:

version: '3'
services: 
  redis-server: 
    image: 'redis'
  node-app:
    build: .

非常に重要なインデントに注意してください。また、1つのサービスではイメージを取得していますが、別のサービスでdocker-composeは現在のディレクトリ内を調べて、2番目のコンテナーで使用するイメージを構築するように指示しています。

次に、このコンテナーで開くすべての異なるポートを指定します。

version: '3'
services: 
  redis-server: 
    image: 'redis'
  node-app:
    build: .
    ports:
      -

ダッシュに注意してください。yamlファイル内のダッシュは、配列を指定する方法です。この例では8081、ローカルマシンを次の8081ようにコンテナにマッピングしています。

version: '3'
services: 
  redis-server: 
    image: 'redis'
  node-app:
    build: .
    ports:
      - "8081:8081"

したがって、最初のポートはローカルマシンで、もう1つはコンテナのポートです。次のように混乱を避けるために2つを区別することもできます。

version: '3'
services:
  redis-server:
    image: 'redis'
  node-app:
    build: .
    ports:
      - "4001:8081"

このdocker-compose.ymlようにファイルを開発することで、これらのコンテナは基本的に同じネットワーク上に作成され、自由に相互に通信して、好きなだけ情報を交換できます。

2つのコンテナーを使用しdocker-composeて作成する場合、ポート宣言は必要ありません。

ここでの例では、Nodejsアプリで次のようなコード構成を行う必要があります。

const express = require('express');
const redis = require('redis');

const app = express();
const client = redis.createClient({
  host: 'redis-server'
});

上記の例を使用docker-compose.ymlして、プロジェクトに固有のファイルに加えて、実行する必要がある特定の構成が存在する可能性があることを認識させます。

ここで、Nodejsアプリとredisを使用していることに気付いた場合は、Nodejsが使用するデフォルトのポートを知っていることを確認したいので、これを追加します。

const express = require('express');
const redis = require('redis');

const app = express();
const client = redis.createClient({
  host: 'redis-server',
  port: 6379
});

したがって、DockerはNodeアプリがredis-serverその接続を探し、この実行中のコンテナーにリダイレクトすることを確認します。

いつも、これDockerfileだけが含まれています:

FROM node:alpine

WORKDIR '/app'

COPY /package.json ./
RUN npm install
COPY . .

CMD ["npm", "start"]

そのdocker run myimageため、ファイル内のすべてのコンテナまたはサービスのインスタンスを作成するために実行する必要がある前に、代わりに実行できdocker-compose upます。Dockerは現在の作業ディレクトリを検索して、docker-compose.ymlそこにファイル。

前にdocker-compose.yml、我々は2つの別々のコマンドで対処しなければならなかったdocker build .docker run myimage、しかしでdocker-compose世界あなたが書くあなたのイメージを再構築したい場合docker-compose up --build。これにより、Dockerはコンテナを再起動し、再構築して最新の変更を取得するように指示します。

そのdocker-composeため、複数のコンテナでの作業が簡単になります。次回、このコンテナのグループをバックグラウンドで開始する必要がある場合は、実行docker-compose up -dして停止することができますdocker-compose down


14
@Chrisこれは、これと承認された回答との間に3年分の知識があるかのようです。
NARUTO-ナルト-センパイ

docker-compose up私の状況で1つのサービスだけを使用するのに十分な理由があるのでしょうか。別の言葉として、と比較してdocker run xxx、私が使用する場合の利点はdocker-compose up何ですか?
atline

@atlineは、単一のコンテナに使用することの利点について、stackoverflow.com / a / 45549372/3366962に対するPansoulの応答を参照docker-compose
go2null

1
@PaulRazvanBergあなたの「または」の部分は正しいです(6379Redisのデフォルトのポートです)。
KrishPrabakar

1
docker-compose.ymlの例は、docker-composeに関する質問のいくつかに答えるのに役立ちました。受け入れられた答えは、特にdockerを初めて使う人にとっては役に立ちません。
maulik13

43

私のワークフローでは、システムの各部分にDockerfileを追加し、各部分を個別に実行できるように構成します。次にdocker-compose.ymlを追加して、それらをまとめてリンクします。

最大の利点(私の意見では):コンテナーをリンクするときに、名前を定義し、この名前でコンテナーをpingできます。したがって、データベースには名前でアクセスできdb、IP でアクセスできなくなる可能性があります。


名前でデータベースにアクセスする方法について詳しく教えてください。
Vedran Maricevic。

どの部分で?docker-composeでは、サービスを定義して名前を付け、構成せずにアクセスできるようにするための通常の方法であるため、それは簡単です。私たちのCIでは、ネットワークを作成しています。このネットワークにコンテナーを作成し、名前を付けます。次に、コンテナ内で(ホストからではなく)名前でアクセスできます
n2o

作曲家ということです。それで、composerで画像をリンクし、IPではなくApp configで、composerファイルで指定した名前でMySQLを圧縮しますか?
Vedran Maricevic。

そのとおりです。リンクを指定する必要すらありません。ネットワークが別に指定されていない場合、デフォルトでリンクされます。この例では、サービス "web"はホスト "redis"にその名前 "redis"
n2oを

37

「良い」は相対的です。それはすべてあなたのニーズが何であるかに依存します。Docker composeは、複数のコンテナをオーケストレーションするためのものです。これらのイメージがすでにdockerレジストリに存在する場合は、作成ファイルにリストすることをお勧めします。これらのイメージまたは他のいくつかのイメージをコンピューター上のファイルからビルドする必要がある場合は、Dockerfileでそれらのイメージをビルドするプロセスを説明できます。

DockerfileがDocker Composeで使用されていることを理解していますが、さまざまなイメージに対して複数のFROMコマンドを使用してすべてを1つの大きなDockerfileに配置するのが良い方法かどうかわかりません。

機能を削除する提案があるため、単一のdockerfileで複数のFROMを使用することはあまりお勧めできません。13026

たとえば、データベースを使用するアプリケーションをドッキングし、アプリケーションファイルをコンピューター上に配置したい場合は、次のように構成ファイルをdockerfileと共に使用できます。

docker-compose.yml

mysql:
  image: mysql:5.7
  volumes:
    - ./db-data:/var/lib/mysql
  environment:
    - "MYSQL_ROOT_PASSWORD=secret"
    - "MYSQL_DATABASE=homestead"
    - "MYSQL_USER=homestead"
  ports:
    - "3307:3306"
app:
  build:
    context: ./path/to/Dockerfile
    dockerfile: Dockerfile
  volumes:
    - ./:/app
  working_dir: /app

Dockerfile

FROM php:7.1-fpm 
RUN apt-get update && apt-get install -y libmcrypt-dev \
  mysql-client libmagickwand-dev --no-install-recommends \
  && pecl install imagick \
  && docker-php-ext-enable imagick \
  && docker-php-ext-install pdo_mysql \
  && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

30

DockerfileとDocker Composeは、Dockerlandの2つの異なる概念です。Dockerについて話すとき、最初に頭に浮かぶのは、オーケストレーション、OSレベルの仮想化、イメージ、コンテナーなどです。それぞれを以下のように説明していきます。

イメージ: イメージは、Dockerが信頼するレジストリに保存される不変の共有可能なファイルです。Dockerイメージは、一連の読み取り専用レイヤーから構築されます。各レイヤーは、イメージのDockerfileで提供される命令を表します。イメージには、実行に必要なすべてのバイナリが含まれています。

ここに画像の説明を入力してください

コンテナ: 画像のインスタンスはコンテナと呼ばます。コンテナーは、ホストOSによって実行される実行可能イメージのバイナリーです。実行中のイメージはコンテナです。

ここに画像の説明を入力してください

Dockerfile: Dockerfileは、すべてのコマンド/ビルド命令を含むテキストドキュメントです。ユーザーは、コマンドラインで呼び出してイメージを組み立てることができます。これはとして保存されますDockerfile。(小文字の「f」に注意してください。)

ここに画像の説明を入力してください

Docker-Compose: Composeは、マルチコンテナのDockerアプリケーションを定義して実行するためのツールです。Composeでは、YAMLファイルを使用してアプリケーションのサービス(コンテナー)を構成します。次に、1つのコマンドで、構成からすべてのサービスを作成して開始します。作成ファイルはとして保存されdocker-compose.ymlます。


14

あなたがソフトウェア会社のマネージャーで、真新しいサーバーを購入したとしましょう。ハードウェアだけです。

考えてDockerfile、あなたのシステム管理者(DBA)を言うだろう命令のセットとしてインストールするには、どのようなこのブランドの新しいサーバー上で。例えば:

  • Debian linuxが必要です
  • Apache Webサーバーを追加する
  • postgresqlも必要です
  • 真夜中の司令官をインストールする
  • すべて完了したら、プロジェクトのすべての* .php、*。jpgなどのファイルをウェブサーバーのウェブルートにコピーします(/var/www

対照的に、サーバーが他の世界とどのように対話することができるかをdocker-compose.ymlシステム管理者に伝える一連の指示と考えてください。例えば、

  • 別のコンピューターから共有フォルダーにアクセスできる
  • ポート80はホストコンピュータのポート8000​​と同じです。
  • 等々。

(これは正確な説明ではありませんが、開始するには十分です。)


4

Dockerfilesが裸の骨のUbuntuから、例えば、画像を構築することです、あなたは追加できmysql呼ばれるmySQL一枚の画像にしてmywordpressと呼ばれる第二の画像の上にmywordpress

Compose YAMLファイルはこれらのイメージを取得し、それらをまとまって実行します。たとえば、docker-compose.ymlファイルにサービス呼び出しがある場合db

services:
   db:
     image: mySQL  --- image that you built.

次のようなworpressと呼ばれるサービス:

wordpress: 
    image: mywordpress

次に、mywordpressコンテナ内で、dbmySQLコンテナへの接続に使用できます。この魔法は、Dockerホストがネットワークブリッジ(ネットワークオーバーレイ)を作成するために可能です。


0

(共通の共有コードベースを持つ)マイクロサービスの世界では、各マイクロサービスにDockerfileルートレベル(通常はすべてのマイクロサービスの外側で、親POMが存在する場所)で、docker-compose.ymlすべてのマイクロサービスを本格的なアプリにグループ化するように定義します。

あなたのケースでは、「Docker Compose」が「Dockerfile」よりも優先されます。「アプリ」を考える「作成」を考える。


0

Dockerfileは、イメージを組み立てるためのテキストコマンドを含むファイルです。

Docker composeは、マルチコンテナー環境を実行するために使用されます。

特定のシナリオでは、言及したテクノロジーごとに複数のサービスがある場合(reddisを使用するサービス1、rabbit mqを使用するサービス2など)、各サービスのDockerfileと実行する共通のdocker-compose.ymlを設定できますコンテナとしてのすべての「Dockerfile」。

これらすべてを単一のサービスで使用したい場合は、docker-composeが実行可能なオプションになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.