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

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 .


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: {}

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.


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.


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.


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

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.


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.)


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ą).


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”.


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ą.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.