web-dev-qa-db-ja.com

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

Docker を読んで学び、使用するDjangoの設定を正しく選択しようとしています。これまでのところどちらかがあります:

Docker Compose または Dockerfile

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

私はいくつかの異なる画像を使用したいと思います。

uwsgi
nginx
postgres
redis
rabbitmq
celery with cron

Docker を使用して、このタイプの環境を設定する際のベストプラクティスについて教えてください。

それが助けになるなら、私はMacを使っているので、 boot2docker を使います。

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

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

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

プロジェクトのdocker-compose.ymlにbuildコマンドを追加すると、Docker Compose(以下、「作成」と呼びます)はDockerfileを使用します。

Dockerのワークフローでは、作成したいそれぞれの画像に適したDockerfileを作成してから、buildコマンドを使用してcomposeを使用して画像を組み立てます。

build /path/to/dockerfiles/blahを使用して個々のDockerファイルへのパスを指定できます。ここで、/path/to/dockerfiles/blahはblahのDockerfileが存在する場所です。

154
booyaa

Dockerfile

enter image description here

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

enter image description here

Docker Compose

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

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

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

例: docker-compose.yml

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

Composeファイルは実行状態のコンテナを記述し、コンテナを構築するの詳細はDockerfilesに残します。 http://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volumes

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

https://docs.docker.com/v1.11/compose/production/ ではなくなったため、Composeは1.11の時点で生産的に安全と見なされているようです。 https://docs.docker.com/v1.10/compose/production/ のように、本番環境で使用しないように警告があります。

81
Peeter Kokk

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

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

37
n2o

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

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

この機能を削除するという提案があるので、単一の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
23
Akongnwi Devert

docker-composeは、docker-cliを使用して大量のコマンドを記述しなければならないようにするためのものです。

docker-composeを使用すると、複数のコンテナーを同時に起動し、それらを何らかの形態のネットワーキングで自動的に接続することも容易になります。

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

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

あなたはそれらをyamlファイルにコピーペーストするだけではなく、特別な構文があります。

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

それで、あなたは別々のコンテナを持つことになるでしょう。例えば、一つはredis-serverで、もう一つはnode-appで、あなたの現在のディレクトリのDockerfileを使って作成したいとしましょう。

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

それであなたのdocker-compose.ymlファイルのためにあなたはそのように最初の行を始めたいでしょう:

version: '3'

それはあなたが使いたいdocker-composeのバージョンをDockerに伝えます。その後、追加する必要があります。

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

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

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

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"

最初のポートはあなたのローカルマシンで、もう一方のポートはコンテナのポートです。混乱を避けるために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アプリを使って作業していて、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の前は、docker build .docker run myimageの2つの別々のコマンドを扱わなければなりませんでしたが、docker-composeの世界ではイメージを再構築したい場合はdocker-compose up --buildと書きます。それはDockerにコンテナを再起動するように伝えますが、最新の変更を得るためにそれを再構築するようにします。

それでdocker-composeは複数のコンテナを扱うのをより簡単にします。次回このグループのコンテナをバックグラウンドで起動する必要があるときにはdocker-compose up -dを実行し、それらを停止するにはdocker-compose downを実行することができます。

18
Daniel

あなたがソフトウェア会社のマネージャーであり、真新しいサーバーを購入したと想像してください。ハードウェアだけ。

Dockerfileは、システム管理者に指示する一連の指示と考えてくださいインストールするものこの新しいサーバーに。例えば:

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

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

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

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

6
Csongor Halmai

Dockerfilesは、例えば裸の骨Ubuntuから画像を構築するためのものです。1つの画像にmysqlと呼ばれるmySQLを、mywordpressと呼ばれる2番目の画像にmywordpressを追加することができます。

Compose YAMLファイルは、これらの画像を取得してそれらをまとまりなく実行するためのものです。例えばdocker-compose.ymlファイルにサービスコールdbがあるとします。

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

そして、そのようなworpressと呼ばれるサービス:

wordpress: 
    image: mywordpress

それからmywordpressコンテナの中であなたはあなたのmySQLコンテナに接続するためにdbを使うことができます。あなたのdocker Hostがネットワークブリッジ(ネットワークオーバーレイ)を作成するので、この魔法は可能です。

3
Hugo R