Docker Compose vs. Dockerfile - was ist besser?

384

Ich habe Docker gelesen und gelernt und versuche, das zu verwendende Django-Setup richtig auszuwählen. Bisher gibt es entweder:

Docker Compose oder Dockerfile

Ich verstehe, dass Dockerfilesin verwendet werden Docker Compose, aber ich bin nicht sicher, ob es eine gute Praxis ist, alles in einer großen Docker-Datei mit mehreren FROMBefehlen für die verschiedenen Bilder zu speichern ?

Ich möchte verschiedene Bilder verwenden, darunter:

uwsgi
nginx
postgres
redis
rabbitmq
celery with cron

Bitte geben Sie an, welche Best Practices beim Einrichten dieser Art von Umgebung mit Docker angewendet werden .

Wenn es hilft, bin ich auf einem Mac, also benutze boot2docker .

Einige Probleme, die ich hatte:

  1. Docker Compose ist nicht mit Python3 kompatibel
  2. Ich möchte mein Projekt containerisieren. Wenn also eine große Docker-Datei nicht ideal ist, muss ich sie mit Docker Compose auflösen
  3. Ich bin in Ordnung, um das Projekt Py2 & Py3 kompatibel zu machen, also neige ich zu Django-Compose
Aaron Lelevier
quelle
5
Die Angelegenheit wäre besser formuliert als "Soll ich meine App als ein oder mehrere Container ausführen?" Es scheint, dass es darauf ankommt und dass Fragen der Skalierung und Trennung von Bedenken (ein Container pro Service) berücksichtigt werden sollten. Diese könnten helfen: stackoverflow.com/questions/30534939/… und quora.com/…
Fabien Snauwaert
Die offiziellen Docker- Dokumente "Erste Schritte" .
Jchook

Antworten:

238

Die Antwort ist weder.

Docker Compose (hier als Compose bezeichnet) verwendet die Docker-Datei, wenn Sie den Befehl build zu Ihrem Projekt hinzufügen docker-compose.yml.

Ihr Docker-Workflow sollte darin bestehen, Dockerfilefür jedes Bild, das Sie erstellen möchten , ein geeignetes Bild zu erstellen und dann mit compose die Bilder mit dem buildBefehl zusammenzusetzen.

Sie können den Pfad zu Ihrem individuellen Dockerfiles angeben mit build /path/to/dockerfiles/blahdem , /path/to/dockerfiles/blahwo blah der ist DockerfileLeben.

Booyaa
quelle
10
Verwenden Sie docker-composein der Produktion oder nur Entwickler? Danke für Ihre Hilfe.
Aaron Lelevier
18
@booyaa Könnten Sie das bitte näher erläutern?
Martin Thoma
2
Danke für die Antwort! Dockerfile gibt config für image an und docker-compose.yml setzt Bilder zusammen. Eine Sache, auf die ich hinweisen möchte, ist, dass man, wenn man docker-compose.ymlnur ein öffentliches Image verwendet (Image aus dem Internet / Docker-Hub ziehen), kein benötigt Docker-Datei zum Ausführen des Befehls docker-compose up.
Oldyoung
549

Dockerfile

Geben Sie hier die Bildbeschreibung ein

Eine Docker-Datei ist eine einfache Textdatei, die die Befehle enthält, die ein Benutzer zum Zusammenstellen eines Bildes aufrufen kann.

Beispiel 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

Geben Sie hier die Bildbeschreibung ein

Docker Compose

  • ist ein Tool zum Definieren und Ausführen von Docker-Anwendungen mit mehreren Containern.

  • Definieren Sie die Dienste, aus denen Ihre App besteht, docker-compose.ymldamit sie zusammen in einer isolierten Umgebung ausgeführt werden können.

  • Starten Sie eine App in einem Befehl, indem Sie sie einfach ausführen docker-compose up

Beispiel: docker-compose.yml

version: "3"
services:
  web:
    build: .
    ports:
    - '5000:5000'
    volumes:
    - .:/code
    - logvolume01:/var/log
    links:
    - redis
  redis:
    image: redis
    volumes:
      logvolume01: {}
cyber8200
quelle
43
@sg die Antwort ist, dass die Frage aufgrund des Unverständnisses von Docker vs Docker Compose schlecht formuliert ist. Es ist wahrscheinlich die beste Antwort, die ich mir vorstellen kann, kurz und bündig zu erklären, wie die beiden interagieren.
mpowered
53
Ich habe keine Ahnung, warum diese genaue Aufschlüsselung nicht auf der Docker-Homepage steht. Vielen Dank.
Codykochmann
4
Ich sehe, dass diese Art von Dokumenten in den zuletzt veröffentlichten Tools / Lösungen / Frameworks im Web fehlt. Ich denke, es ist schwer zu verstehen, warum jemand es braucht, falls Sie die Lösung bereits selbst kennen / erfunden haben.
Peter Branforn
36
Was in dieser Antwort fehlt, sind weitere Informationen zum Verfassen. Ruft das Erstellungsskript die Docker-Datei auf? Woher weiß es, was es komponieren soll? Das Beispiel zeigt image: redisaber ist das von Dockerhub? lokales Verzeichnis? etc ... das macht es für einen Neuling wie mich verwirrend zu verstehen, was wirklich los ist
Joe Phillips
5
Diese Antwort besteht auf dem Mehrcontainer-Zweck von Docker Compose, aber es gibt wahrscheinlich viele andere Szenarien, in denen Sie Docker Compose verwenden möchten, selbst wenn nur ein Container vorhanden ist, z. B. die Angabe des Ports, auf dem Ihr Container ausgeführt werden soll (in Dockerfile Afaik nicht möglich).
Pansoul
99

Die Compose - Datei beschreibt den Behälter in seinem Betriebszustand , so dass die Details, wie man die Behälter bauen zu Dockerfiles . http://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volumes

Wenn Sie Ihre App mit Compose in der Entwicklung definieren, können Sie diese Definition verwenden, um Ihre Anwendung in verschiedenen Umgebungen wie CI, Staging und Produktion auszuführen . https://docs.docker.com/compose/production/

Es scheint auch, dass Compose ab 1.11 als produktionssicher gilt , da https://docs.docker.com/v1.11/compose/production/ keine Warnung mehr enthält, es nicht in der Produktion wie https: // docs zu verwenden .docker.com / v1.10 / komponieren / Produktion / tut.

Peeter Kokk
quelle
1
Vielen Dank, dass Sie das Problem angesprochen haben. Können Sie bitte noch etwas hinzufügen, was für die Produktionssicherheit bei 1.11 festgelegt wurde?
MA Hossain Tonu
93

Docker-Compose ist vorhanden, damit Sie nicht jede Menge Befehle schreiben müssen, die Sie mit Docker-CLI ausführen müssten.

Docker-Compose macht es auch einfach, mehrere Container gleichzeitig zu starten und sie automatisch mit einer Art Netzwerk zu verbinden.

Der Zweck von Docker-Compose besteht darin, als Docker-CLI zu fungieren, aber mehrere Befehle viel schneller auszugeben.

Um Docker-Compose verwenden zu können, müssen Sie die zuvor ausgeführten Befehle in eine docker-compose.ymlDatei codieren .

Sie werden sie nicht nur kopieren, sondern in die yaml-Datei einfügen, es gibt eine spezielle Syntax.

Einmal erstellt, müssen Sie es der Docker-Compose-CLI zuführen. Es liegt an der CLI, die Datei zu analysieren und alle verschiedenen Container mit der von uns angegebenen korrekten Konfiguration zu erstellen.

Sie haben also separate Container, zum Beispiel einen redis-serverund den zweiten, node-appund Sie möchten, dass diese mit dem Dockerfilein Ihrem aktuellen Verzeichnis erstellt werden.

Nachdem Sie diesen Container erstellt haben, ordnen Sie außerdem einen Port vom Container dem lokalen Computer zu, um auf alles zuzugreifen, was darin ausgeführt wird.

Für Ihre docker-compose.ymlDatei möchten Sie also die erste Zeile folgendermaßen beginnen:

version: '3'

Dadurch wird Docker mitgeteilt, welche Version docker-composeSie verwenden möchten. Danach müssen Sie hinzufügen:

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

Bitte beachten Sie die Einrückung, sehr wichtig. Beachten Sie auch, dass ich für einen Dienst ein Bild greife, für einen anderen Dienst jedoch docker-composein das aktuelle Verzeichnis schaue, um das Bild zu erstellen, das für den zweiten Container verwendet wird.

Anschließend möchten Sie alle verschiedenen Ports angeben, die für diesen Container geöffnet werden sollen.

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

Bitte beachten Sie den Bindestrich. Ein Bindestrich in einer Yaml-Datei gibt an, wie wir ein Array angeben. In diesem Beispiel ordne ich 8081auf meinem lokalen Computer 8081dem Container Folgendes zu:

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

Der erste Port ist also Ihr lokaler Computer, und der andere ist der Port auf dem Container. Sie können auch zwischen den beiden unterscheiden, um Verwechslungen wie folgt zu vermeiden:

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

Wenn Sie Ihre docker-compose.ymlDatei so entwickeln, werden diese Container im Wesentlichen im selben Netzwerk erstellt und sie haben freien Zugriff, um nach Belieben miteinander zu kommunizieren und so viele Informationen auszutauschen, wie sie möchten.

Wenn die beiden Container mit erstellt werden docker-compose, benötigen wir keine Portdeklarationen.

In meinem Beispiel müssen wir eine Codekonfiguration in der Nodejs-App vornehmen, die ungefähr so ​​aussieht:

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

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

Ich verwende dieses Beispiel oben, um Sie darauf aufmerksam zu machen, dass Sie möglicherweise zusätzlich zu der docker-compose.ymlfür Ihr Projekt spezifischen Datei eine bestimmte Konfiguration vornehmen müssen .

Wenn Sie jemals mit einer Nodejs-App und Redis arbeiten, möchten Sie sicherstellen, dass Sie über den Standardport informiert sind, den Nodejs verwendet, und ich werde Folgendes hinzufügen:

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

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

Docker wird also feststellen, dass die Node-App redis-serverdiese Verbindung sucht, und diese Verbindung zu diesem laufenden Container umleiten.

Die ganze Zeit Dockerfileenthält das einzige Folgendes:

FROM node:alpine

WORKDIR '/app'

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

CMD ["npm", "start"]

Während Sie also zuvor ausführen müssen docker run myimage, um eine Instanz aller Container oder Dienste in der Datei zu erstellen, können Sie diese stattdessen ausführen, docker-compose upund Sie müssen kein Image angeben, da Docker im aktuellen Arbeitsverzeichnis nach einem sucht docker-compose.ymlDatei innerhalb von dort.

Früher docker-compose.ymlmussten wir uns mit zwei separaten Befehlen von docker build .und befassen docker run myimage, aber in der docker-composeWelt, wenn Sie Ihre Bilder neu erstellen möchten, schreiben Sie docker-compose up --build. Dadurch wird Docker angewiesen, die Container erneut zu starten, sie jedoch neu zu erstellen, um die neuesten Änderungen zu erhalten.

Dies docker-composeerleichtert das Arbeiten mit mehreren Containern. Wenn Sie das nächste Mal diese Gruppe von Containern im Hintergrund starten müssen, können Sie dies tun docker-compose up -dund sie stoppen docker-compose down.

Daniel
quelle
14
@ Chris Es ist fast so, als ob zwischen dieser und der akzeptierten Antwort 3 Jahre Wissen liegen.
Naruto Sempai
Ich frage mich, ob es einen guten Grund für mich gibt, docker-compose upnur einen Dienst in meiner Situation zu nutzen. Ein anderes Wort, vergleiche mit docker run xxx, irgendeinen Vorteil, wenn ich benutze docker-compose up?
atline
@atline siehe Pansouls Antwort auf stackoverflow.com/a/45549372/3366962 über die Vorteile der Verwendung docker-composefür einzelne Container
go2null
1
@PaulRazvanBerg Ihr "Oder" Teil ist korrekt (und 6379ist der Standardport von Redis).
KrishPrabakar
1
Die Beispiele für docker-compose.yml halfen mir, einige der Fragen zu beantworten, die ich zu docker-compose hatte. Die akzeptierte Antwort ist nicht nützlich, insbesondere für Leute, die Docker noch nicht kennen.
maulik13
43

In meinem Workflow füge ich für jeden Teil meines Systems eine Docker-Datei hinzu und konfiguriere sie so, dass jeder Teil einzeln ausgeführt werden kann. Dann füge ich eine docker-compose.yml hinzu, um sie zusammenzuführen und zu verknüpfen.

Größter Vorteil (meiner Meinung nach): Wenn Sie die Container verknüpfen , können Sie einen Namen definieren und Ihre Container mit diesem Namen pingen. Daher ist Ihre Datenbank möglicherweise mit dem Namen dbund nicht mehr über die IP- Adresse zugänglich .

n2o
quelle
Könnten Sie näher auf den Zugriff auf die Datenbank mit dem Namen eingehen?
Vedran Maricevic.
Auf welchem ​​Teil? In Docker-Compose ist dies trivial, da es bei der Definition Ihrer Dienste die normale Methode ist, ihm einen Namen zu geben und ihn zugänglich zu machen, ohne ihn konfigurieren zu müssen. In unserem CI erstelle ich ein Netzwerk, erstelle den Container in diesem Netzwerk und gebe ihnen einen Namen. Dann haben Sie sie auch unter ihrem Namen in den Containern zugänglich (nicht vom Host)
n2o
Mit Komponist meine ich. Also verknüpfe ich die Bilder in Composer und ziele in meiner App-Konfiguration anstelle von IP auf MySQL mit dem Namen, den ich ihm in der Composer-Datei gegeben habe?
Vedran Maricevic.
Das ist richtig. Sie müssen nicht einmal einen Link angeben. Sie sind standardmäßig verknüpft, wenn das Netzwerk nicht anders angegeben ist. In diesem Beispiel kann der Dienst "web" den Host "redis" mit seinem Namen "redis"
anpingen
37

"besser" ist relativ. Es hängt alles davon ab, was Ihre Bedürfnisse sind. Docker Compose dient zum Orchestrieren mehrerer Container. Wenn diese Bilder bereits in der Docker-Registrierung vorhanden sind, ist es besser, sie in der Erstellungsdatei aufzulisten. Wenn diese oder einige andere Bilder aus Dateien auf Ihrem Computer erstellt werden müssen, können Sie die Prozesse zum Erstellen dieser Bilder in einer Docker-Datei beschreiben.

Ich verstehe, dass Dockerfiles in Docker Compose verwendet werden, bin mir aber nicht sicher, ob es sinnvoll ist, alles in einer großen Dockerfile mit mehreren FROM-Befehlen für die verschiedenen Bilder abzulegen.

Die Verwendung mehrerer FROM in einer einzelnen Docker-Datei ist keine sehr gute Idee, da vorgeschlagen wird, die Funktion zu entfernen. 13026

Wenn Sie beispielsweise eine Anwendung andocken möchten, die eine Datenbank verwendet und die Anwendungsdateien auf Ihrem Computer hat, können Sie eine Erstellungsdatei zusammen mit einer Docker-Datei wie folgt verwenden

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
Akongnwi Devert
quelle
30

Dockerfile und Docker Compose sind zwei verschiedene Konzepte in Dockerland. Wenn wir über Docker sprechen, fallen uns als Erstes Orchestrierung, Virtualisierung auf Betriebssystemebene, Bilder, Container usw. ein. Ich werde versuchen, diese wie folgt zu erklären:

Bild: Ein Bild ist eine unveränderliche, gemeinsam nutzbare Datei, die in einer Docker-vertrauenswürdigen Registrierung gespeichert ist. Ein Docker-Image besteht aus einer Reihe von schreibgeschützten Ebenen. Jede Ebene stellt eine Anweisung dar, die in der Docker-Datei des Bildes gegeben wird. Ein Image enthält alle erforderlichen Binärdateien, die ausgeführt werden sollen.

Geben Sie hier die Bildbeschreibung ein

Container: Eine Instanz eines Bildes wird als Container bezeichnet . Ein Container ist nur eine ausführbare Image-Binärdatei, die vom Host-Betriebssystem ausgeführt werden soll. Ein laufendes Image ist ein Container.

Geben Sie hier die Bildbeschreibung ein

Docker-Datei: Eine Docker-Datei ist ein Textdokument, das alle Befehle / Erstellungsanweisungen enthält, die ein Benutzer über die Befehlszeile aufrufen kann, um ein Bild zusammenzustellen. Dies wird als gespeichert Dockerfile. (Beachten Sie das Kleinbuchstaben 'f'.)

Geben Sie hier die Bildbeschreibung ein

Docker-Compose: Compose ist ein Tool zum Definieren und Ausführen von Docker-Anwendungen mit mehreren Containern. Mit Compose verwenden Sie eine YAML-Datei, um die Dienste (Container) Ihrer Anwendung zu konfigurieren. Anschließend erstellen und starten Sie mit einem einzigen Befehl alle Dienste in Ihrer Konfiguration. Die Compose-Datei wird als gespeichert docker-compose.yml.

Waqas Ahmed
quelle
14

Stellen Sie sich vor, Sie sind der Manager eines Softwareunternehmens und haben gerade einen brandneuen Server gekauft. Nur die Hardware.

Denken Sie an , Dockerfilewie eine Reihe von Anweisungen , die Sie Ihrem System sagen würde adminstrator was installieren auf diesem brandneuen Server. Zum Beispiel:

  • Wir brauchen ein Debian-Linux
  • Fügen Sie einen Apache-Webserver hinzu
  • wir brauchen auch postgresql
  • Installieren Sie den Mitternachtskommandanten
  • Wenn alles erledigt ist, kopiere alle * .php, * .jpg usw. Dateien unseres Projekts in die Webroot des Webservers ( /var/www)

Stellen Sie sich im Gegensatz dazu docker-compose.ymleine Reihe von Anweisungen vor, die Sie Ihrem Systemadministrator mitteilen würden, wie der Server mit dem Rest der Welt interagieren kann . Zum Beispiel,

  • Es hat Zugriff auf einen freigegebenen Ordner von einem anderen Computer aus.
  • Der Port 80 entspricht dem Port 8000 des Host-Computers.
  • und so weiter.

(Dies ist keine genaue Erklärung, aber zunächst gut genug.)

Csongor Halmai
quelle
4

Dockerfiles sind ein Bild zum Beispiel aus einem blanken Knochen Ubuntu zu bauen, können Sie hinzufügen mysqlgenannt mySQLauf ein Bild und mywordpressauf einem zweiten Bild genannt mywordpress.

Beim Erstellen von YAML-Dateien sollen diese Bilder aufgenommen und zusammenhängend ausgeführt werden. Wenn Sie beispielsweise docker-compose.ymleinen Serviceabruf in Ihrer Datei haben db:

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

und ein Dienst namens worpress wie:

wordpress: 
    image: mywordpress

Anschließend können Sie im mywordpress-Container dbeine Verbindung zu Ihrem mySQL-Container herstellen. Diese Magie ist möglich, weil Ihr Docker-Host eine Netzwerkbrücke erstellt (Netzwerk-Overlay).

Hugo R.
quelle
0

In der Microservices-Welt (mit einer gemeinsamen Codebasis) würde jeder Microservice eine haben, Dockerfilewährend Sie auf der Root-Ebene (im Allgemeinen außerhalb aller Microservices und wo sich Ihr übergeordnetes POM befindet) eine definieren würden, um docker-compose.ymlalle Microservices in einer vollständigen App zu gruppieren.

In Ihrem Fall wird "Docker Compose" gegenüber "Dockerfile" bevorzugt. Denken Sie "App" Denken Sie "Verfassen".

KrishPrabakar
quelle
0

Dockerfile ist eine Datei, die Textbefehle zum Zusammenstellen eines Bildes enthält.

Docker Compose wird zum Ausführen einer Umgebung mit mehreren Containern verwendet.

Wenn Sie in Ihrem speziellen Szenario mehrere Dienste für jede von Ihnen erwähnte Technologie haben (Dienst 1 mit reddis, Dienst 2 mit rabbit mq usw.), können Sie für jeden der Dienste eine Docker-Datei und eine gemeinsame docker-compose.yml ausführen alle "Dockerfile" als Container.

Wenn Sie alle in einem einzigen Dienst haben möchten, ist Docker-Compose eine praktikable Option.

Mudassir Shahzad
quelle