Docker Compose vs. Dockerfile - co jest lepsze?

384

Czytam i dowiaduję się o Dockerze i staram się poprawnie wybrać konfigurację Django do użycia. Do tej pory jest albo:

Docker Compose lub Dockerfile

Rozumiem, że Dockerfilessą używane Docker Compose, ale nie jestem pewien, czy dobrą praktyką jest umieszczanie wszystkiego w jednym dużym Dockerfile z wieloma FROMpoleceniami dla różnych obrazów?

Chcę użyć kilku różnych obrazów, które obejmują:

uwsgi
nginx
postgres
redis
rabbitmq
celery with cron

Proszę doradzić, jakie są najlepsze praktyki w konfigurowaniu tego typu środowiska za pomocą Dockera .

Jeśli to pomaga, jestem na komputerze Mac, więc używam boot2docker .

Niektóre problemy, które miałem:

  1. Docker Compose nie jest kompatybilny z Python3
  2. Chcę spenetrować mój projekt, więc jeśli jeden duży plik Docker nie jest idealny, to czuję, że musiałbym go rozbić za pomocą Docker Compose
  3. Mogę uczynić projekt Py2 i Py3 kompatybilnym, więc skłaniam się ku django-compose
Aaron Lelevier
źródło
5
Sprawa byłaby lepiej sformułowana jako „Czy powinienem uruchamiać moją aplikację jako jeden czy wiele kontenerów?” Wydaje się, że to zależy i że należy wziąć pod uwagę kwestie skalowania i rozdzielenia problemów (jeden pojemnik na usługę). Mogą one pomóc: stackoverflow.com/questions/30534939/... i quora.com/…
Fabien Snauwaert
Oficjalne dokumenty Docker „Pierwsze kroki” .
jchook

Odpowiedzi:

238

Odpowiedź nie jest żadna.

Narzędzie Docker Compose (określane tutaj jako compose) użyje pliku Docker, jeśli dodasz polecenie kompilacji do projektu docker-compose.yml.

Twój obieg pracy Dockera powinien polegać na zbudowaniu odpowiedniego Dockerfiledla każdego obrazu, który chcesz utworzyć, a następnie użyj komponowania do złożenia obrazów za pomocą buildpolecenia.

Możesz określić ścieżkę do poszczególnych plików Docker, używając build /path/to/dockerfiles/blahmiejsca, w /path/to/dockerfiles/blahktórym Dockerfilemieszka bla .

booyaa
źródło
10
używasz docker-composew produkcji czy tylko deweloperze? Dzięki za pomoc.
Aaron Lelevier,
18
@booyaa Czy mógłbyś rozwinąć tę kwestię?
Martin Thoma,
2
Dziękuję za odpowiedź! Plik Dockerfile określa konfigurację obrazu, a docker-compose.yml montuje obrazy razem. Jedną rzeczą, na którą chcę zwrócić uwagę, jest to, że jeśli docker-compose.ymlużywasz tylko obrazu publicznego (wyciągając obraz z Internetu / centrum dokowania), to nie potrzebujesz Plik Docker, aby uruchomić polecenie docker-compose up.
Oldyoung,
549

Plik Docker

wprowadź opis zdjęcia tutaj

Plik Docker to prosty plik tekstowy zawierający polecenia, które użytkownik może wywołać w celu złożenia obrazu.

Przykład 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

wprowadź opis zdjęcia tutaj

Docker Compose

  • to narzędzie do definiowania i uruchamiania aplikacji Docker dla wielu kontenerów.

  • zdefiniuj usługi, z których składa się Twoja aplikacja, docker-compose.ymlaby mogły być uruchamiane razem w izolowanym środowisku.

  • uruchom aplikację w jednym poleceniu, po prostu uruchamiając docker-compose up

Przykład : docker-compose.yml

version: "3"
services:
  web:
    build: .
    ports:
    - '5000:5000'
    volumes:
    - .:/code
    - logvolume01:/var/log
    links:
    - redis
  redis:
    image: redis
    volumes:
      logvolume01: {}
cyber8200
źródło
43
@sg odpowiedź brzmi, że pytanie jest źle sformułowane z powodu braku zrozumienia Docker vs. Docker Compose. Zwięzłe wyjaśnienie, w jaki sposób te dwie osoby wchodzą w interakcje, jest prawdopodobnie najlepszą odpowiedzią, jaką mogę wymyślić.
mpowered
53
Nie mam pojęcia, dlaczego ten dokładny podział nie znajduje się na stronie głównej Dockera. Dzięki.
codykochmann
4
Widzę tego rodzaju dokumenty brakujące w ostatnio wydanych narzędziach / rozwiązaniach / frameworkach w Internecie. Wydaje mi się, że trudno jest zrozumieć, dlaczego ktoś tego potrzebuje, jeśli sam już znasz / wymyśliłeś rozwiązanie.
Peter Branforn,
36
Brakuje w tej odpowiedzi więcej informacji o komponowaniu. Czy skrypt tworzenia wywołuje plik dockerfile? Skąd wie, co skomponować? Przykład pokazuje, image: redisale czy pochodzi z dockerhub? lokalny katalog? itd ... to sprawia, że ​​mylące jest dla newb, takiego jak ja, zrozumienie, co się naprawdę dzieje
Joe Phillips
5
Ta odpowiedź kładzie nacisk na wielozakresowy cel komponowania dokowania, ale prawdopodobnie istnieje wiele innych scenariuszy, w których chcesz użyć komponowania dokowania, nawet z tylko jednym kontenerem, na przykład określenie portu, na którym chcesz uruchomić kontener (nie jest to możliwe w afaik pliku dokera).
Pansoul
99

The tworzenia opisuje kontener w stanie uruchomionym , pozostawiając szczegółowe informacje na temat budowania kontenera dla plików Docker . http://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volumes

Po zdefiniowaniu aplikacji pomocą komponowania w fazie projektowania można użyć tej definicji do uruchamiania aplikacji w różnych środowiskach, takich jak CI, przemieszczanie i produkcja . https://docs.docker.com/compose/production/

Wydaje się również, że Compose jest uważany za bezpieczny w produkcji od 1.11 , ponieważ https://docs.docker.com/v1.11/compose/production/ nie ma już ostrzeżenia, aby nie używać go w produkcji, jak https: // docs .docker.com / v1.10 / compose / production / does.

Peeter Kokk
źródło
1
Dzięki za poruszenie problemu. Czy możesz dodać więcej tego, co zostało naprawione dla bezpieczeństwa produkcji w wersji 1.11?
MA Hossain Tonu
92

docker-compose istnieje, abyś musiał pisać mnóstwo poleceń, które musiałbyś zrobić za pomocą docker-cli.

docker-compose ułatwia także uruchamianie wielu kontenerów jednocześnie i automatyczne łączenie ich ze sobą za pomocą jakiejś formy sieci.

Zadaniem kompilowania dokera jest funkcjonowanie jako cli dokera, ale znacznie szybsze wydawanie wielu poleceń.

Aby skorzystać z funkcji dokowania-komponowania, musisz zakodować wcześniej uruchomione polecenia w docker-compose.ymlpliku.

Nie tylko skopiujesz je wklej do pliku yaml, istnieje specjalna składnia.

Po utworzeniu musisz go przesłać do cli dokującej-skomponuj, a zadaniem cli będzie parsowanie pliku i utworzenie wszystkich różnych kontenerów z określoną przez nas poprawną konfiguracją.

Będziesz miał oddzielne kontenery, powiedzmy na przykład, że jeden jest, redis-servera drugi jest node-appi chcesz, aby został utworzony za pomocąDockerfile w bieżącym katalogu.

Ponadto po utworzeniu tego kontenera można zmapować część portu z kontenera na maszynę lokalną, aby uzyskać dostęp do wszystkiego, co w nim działa.

Więc dla swojego docker-compose.ymlpliku chciałbyś rozpocząć pierwszą linię w następujący sposób:

version: '3'

To mówi Dockerowi, której wersji docker-composechcesz użyć. Następnie musisz dodać:

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

Proszę zauważyć wcięcie, bardzo ważne. Zauważ też, że dla jednej usługi pobieram obraz, ale dla innej usługi każę docker-composezajrzeć do bieżącego katalogu, aby zbudować obraz, który będzie używany dla drugiego kontenera.

Następnie chcesz określić wszystkie różne porty, które chcesz otworzyć w tym kontenerze.

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

Zauważ, że myślnik, myślnik w pliku yaml to sposób określania tablicy. W tym przykładzie mapuję 8081na moim komputerze lokalnym do 8081kontenera w następujący sposób:

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

Tak więc pierwszy port to komputer lokalny, a drugi to port w kontenerze, możesz również rozróżnić oba, aby uniknąć nieporozumień:

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

Opracowując docker-compose.ymltaki plik, utworzy on te kontenery w zasadniczo tej samej sieci i będzie miał swobodny dostęp do komunikowania się ze sobą w dowolny sposób i wymiany dowolnych informacji.

Gdy dwa kontenery są tworzone przy użyciu docker-compose, nie potrzebujemy żadnych deklaracji portów.

Teraz w moim przykładzie musimy wykonać konfigurację kodu w aplikacji Nodejs, która wygląda mniej więcej tak:

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

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

Korzystam z tego przykładu powyżej, aby poinformować Cię, że może istnieć pewna konkretna konfiguracja, którą musisz wykonać oprócz docker-compose.yml pliku, który może być specyficzny dla twojego projektu.

Teraz, jeśli kiedykolwiek będziesz pracować z aplikacją Nodejs i redis, chcesz upewnić się, że znasz domyślny port, z którego korzysta Nodejs, więc dodam to:

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

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

Dlatego Docker zobaczy, że aplikacja Node szuka redis-serveri przekieruje to połączenie do tego działającego kontenera.

Cały czas Dockerfiletylko to zawiera:

FROM node:alpine

WORKDIR '/app'

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

CMD ["npm", "start"]

Tak więc, podczas gdy zanim będziesz musiał uruchomić, docker run myimageaby utworzyć instancję wszystkich kontenerów lub usług w pliku, możesz zamiast tego uruchomić docker-compose upi nie musisz określać obrazu, ponieważ Docker będzie szukał w bieżącym katalogu roboczym i szukałdocker-compose.yml plik tam.

Wcześniej docker-compose.ymlmieliśmy do czynienia z dwoma oddzielnymi poleceniami docker build .i docker run myimage, ale na docker-composeświecie, jeśli chcesz odbudować swoje obrazy, piszesz docker-compose up --build. To mówi Dockerowi, aby ponownie uruchomił kontenery, ale odbuduje go, aby uzyskać najnowsze zmiany.

Tak docker-composeułatwia pracę z wieloma pojemnikami. Następnym razem, gdy będziesz musiał uruchomić tę grupę kontenerów w tle, możesz to zrobić docker-compose up -di aby je zatrzymać, możesz to zrobić docker-compose down.

Daniel
źródło
13
@Chris To prawie tak, jakby istniały 3 lata wiedzy między tym a zaakceptowaną odpowiedzią.
Naruto Sempai
Zastanawiam się, czy miałbym dobry powód, aby skorzystać z docker-compose upjednej usługi w mojej sytuacji? Innym słowem, porównaj z docker run xxxjakąś korzyścią, jeśli użyję docker-compose up?
atline
@atline patrz odpowiedź Pansoul na stackoverflow.com/a/45549372/3366962 na temat korzyści z używania docker-composepojedynczych pojemników
go2null
1
@PaulRazvanBerg ci „Lub” część jest poprawna (i 6379jest domyślnym portem Redis).
KrishPrabakar
1
Przykłady docker-compose.yml pomogły mi odpowiedzieć na niektóre pytania na temat docker-compose. Przyjęta odpowiedź nie jest przydatna, szczególnie dla osób, które dopiero zaczynają pracę z dokerem.
maulik13
43

W moim przepływie pracy dodaję plik Docker dla każdej części mojego systemu i konfiguruję go tak, aby każda część mogła działać indywidualnie. Następnie dodaję docker-compose.yml, aby je połączyć i połączyć.

Największa zaleta (moim zdaniem): łącząc kontenery , możesz zdefiniować nazwę i pingować swoje kontenery tą nazwą. Dlatego twoja baza danych może być dostępna pod nazwą, dba nie z adresu IP.

n2o
źródło
Czy możesz rozwinąć więcej informacji na temat uzyskiwania dostępu do bazy danych według nazwy?
Vedran Maricevic.
W której części? W docker-compose jest to trywialne, ponieważ jest to normalny sposób definiowania usług, aby nadać mu nazwę i mieć do niej dostęp bez konieczności jej konfigurowania. W naszym CI tworzę sieć, utwórz kontener w tej sieci i nadaj im nazwę. Następnie masz je również dostępne po nazwie w kontenerach (nie od hosta)
n2o
Mam na myśli kompozytora. Więc łączę obrazy w kompozytorze, a w konfiguracji mojej aplikacji zamiast IP kieruję MySQL pod jakąkolwiek nazwą, którą nadałem w pliku kompozytora?
Vedran Maricevic.
To jest poprawne. Nie musisz nawet podawać linku. Są one domyślnie połączone, jeśli sieć nie jest inaczej określona. W tym przykładzie usługa „web” może pingować hosta „redis” pod nazwą „redis”
n2o
37

„lepszy” jest względny. Wszystko zależy od twoich potrzeb. Komponent Docker służy do organizowania wielu kontenerów. Jeśli te obrazy już istnieją w rejestrze dokera, lepiej umieścić je w pliku tworzenia. Jeśli te obrazy lub niektóre inne obrazy muszą zostać zbudowane z plików na twoim komputerze, możesz opisać procesy budowania tych obrazów w Dockerfile.

Rozumiem, że Dockerfiles są używane w Docker Compose, ale nie jestem pewien, czy dobrą praktyką jest umieszczanie wszystkiego w jednym dużym Dockerfile z wieloma poleceniami FROM dla różnych obrazów?

Używanie wielu FROM w jednym pliku dokera nie jest zbyt dobrym pomysłem, ponieważ istnieje propozycja usunięcia tej funkcji. 13026

Jeśli na przykład chcesz dokować aplikację, która korzysta z bazy danych i mieć pliki aplikacji na komputerze, możesz użyć pliku tworzenia razem z plikiem dokowania w następujący sposób

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

Plik Docker

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
źródło
30

Dockerfile i Docker Compose to dwie różne koncepcje w Dockerland. Kiedy mówimy o Dockerze, pierwsze rzeczy, które przychodzą na myśl, to aranżacja, wirtualizacja na poziomie systemu operacyjnego, obrazy, kontenery itp. Spróbuję wyjaśnić każde z nich w następujący sposób:

Obraz: obraz jest niezmiennym, udostępnialnym plikiem, który jest przechowywany w rejestrze zaufanym w Docker. Obraz Dockera jest zbudowany z szeregu warstw tylko do odczytu. Każda warstwa reprezentuje instrukcję podaną w pliku Docker obrazu. Obraz zawiera wszystkie wymagane pliki binarne do uruchomienia.

wprowadź opis zdjęcia tutaj

Kontener: instancja obrazu nazywana jest kontenerem . Kontener to tylko plik binarny wykonywalny, który ma być uruchamiany przez system operacyjny hosta. Obraz bieżący to kontener.

wprowadź opis zdjęcia tutaj

Dockerfile: Dockerfile to dokument tekstowy, który zawiera wszystkie polecenia / instrukcje budowania, użytkownik może wywołać w wierszu polecenia, aby złożyć obraz. Zostanie to zapisane jako Dockerfile. (Uwaga małe litery „f”.)

wprowadź opis zdjęcia tutaj

Docker-Compose: Compose to narzędzie do definiowania i uruchamiania aplikacji Docker dla wielu kontenerów. Za pomocą funkcji Komponuj używasz pliku YAML do konfigurowania usług aplikacji (kontenerów). Następnie za pomocą jednego polecenia możesz utworzyć i uruchomić wszystkie usługi z konfiguracji. Plik tworzenia zostanie zapisany jako docker-compose.yml.

Waqas Ahmed
źródło
14

Wyobraź sobie, że jesteś menedżerem firmy programistycznej i właśnie kupiłeś nowy serwer. Tylko sprzęt.

Myśleć o Dockerfile zestawie instrukcji, które powinieneś powiedzieć administratorowi systemu, co zainstalować na tym nowym serwerze. Na przykład:

  • Potrzebujemy Linuksa Debiana
  • dodaj serwer WWW Apache
  • potrzebujemy również postgresql
  • zainstaluj dowódcę północy
  • po zakończeniu skopiuj wszystkie pliki * .php, * .jpg itp. naszego projektu do katalogu głównego webserver ( /var/www)

Dla porównania, pomyśl o docker-compose.ymlzestawie instrukcji, które powiedziałbyś administratorowi systemu, w jaki sposób serwer może współpracować z resztą świata. Na przykład,

  • ma dostęp do folderu współdzielonego z innego komputera,
  • jego port 80 jest taki sam jak port 8000 komputera hosta,
  • i tak dalej.

(To nie jest dokładne wyjaśnienie, ale wystarczająco dobre na początek.)

Csongor Halmai
źródło
4

Pliki dokujące mają zbudować obraz na przykład z gołej kości Ubuntu, możesz dodać mysqlwywołany mySQLna jednym obrazie i mywordpressna drugim obrazie o nazwie mywordpress.

Skomponuj pliki YAML, aby zrobić te zdjęcia i uruchomić je spójnie. na przykład, jeśli masz w docker-compose.ymlpliku zgłoszenie serwisowe db:

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

oraz usługę o nazwie worpress, taką jak:

wordpress: 
    image: mywordpress

następnie w kontenerze mywordpress możesz użyć dbdo połączenia z kontenerem mySQL. Ta magia jest możliwa, ponieważ host dokera tworzy mostek sieciowy (nakładkę sieciową).

Hugo R.
źródło
0

W świecie Microservices (posiadającym wspólną współużytkowaną bazę kodów) każda Microservice miałaby Dockerfilepodczas gdy na poziomie głównym (ogólnie poza wszystkimi Microservices i tam, gdzie mieszka twoja nadrzędna POM) zdefiniowałbyśdocker-compose.yml aby pogrupować wszystkie Microservices w pełni funkcjonalną aplikację.

W twoim przypadku „Docker Compose” jest lepsze niż „Dockerfile”. Pomyśl „Aplikacja” Pomyśl „Utwórz”.

KrishPrabakar
źródło
0

Plik Docker to plik zawierający polecenia tekstowe do złożenia obrazu.

Komponent Docker służy do uruchamiania środowiska z wieloma kontenerami.

W konkretnym scenariuszu, jeśli masz wiele usług dla każdej wspomnianej technologii (usługa 1 używa Reddis, usługa 2 używa króliczego mq itp.), Możesz mieć plik Docker dla każdej z usług i wspólny docker-compose.yml do uruchomienia wszystkie „Dockerfile” jako kontenery.

Jeśli chcesz je wszystkie w ramach jednej usługi, dokowanie-komponowanie będzie realną opcją.

Mudassir Shahzad
źródło