Docker Compose vs. Dockerfile: qual è il migliore?


385

Ho letto e imparato Docker e sto provando a scegliere correttamente la configurazione di Django da usare. Finora c'è o:

Docker Compose o Dockerfile

Capisco che Dockerfilessono utilizzati in Docker Compose, ma non sono sicuro se è buona pratica mettere tutto in un grande file Docker con più FROMcomandi per le diverse immagini?

Voglio usare diverse immagini che includono:

uwsgi
nginx
postgres
redis
rabbitmq
celery with cron

Si prega di avvisare su quali sono le migliori pratiche nell'impostazione di questo tipo di ambiente tramite Docker .

Se aiuta, sono su un Mac, quindi uso boot2docker .

Alcuni problemi che ho avuto:

  1. Docker Compose non è compatibile con Python3
  2. Voglio containerizzare il mio progetto, quindi se un grande Dockerfile non è l'ideale, allora sento che dovrei romperlo usando Docker Compose
  3. Sono d'accordo per rendere compatibile il progetto Py2 e Py3, quindi mi spiego verso django-compose

5
La questione sarebbe meglio definita come "Devo eseguire la mia app come un contenitore singolo o multiplo?" Sembra che dipenda e che le questioni di ridimensionamento e separazione delle preoccupazioni (un contenitore per servizio) debbano essere prese in considerazione. Questi potrebbe aiutare: stackoverflow.com/questions/30534939/... e quora.com/...
Fabien Snauwaert

La documentazione ufficiale di Docker "Introduzione" .
Jchook,

Risposte:


239

La risposta è nessuna delle due.

Docker Compose (di seguito denominato compose) utilizzerà il Dockerfile se si aggiunge il comando build al progetto docker-compose.yml.

Il flusso di lavoro Docker dovrebbe essere quello di creare un oggetto adatto Dockerfileper ogni immagine che si desidera creare, quindi utilizzare compose per assemblare le immagini utilizzando il buildcomando.

È possibile specificare il percorso dei singoli Dockerfile utilizzando build /path/to/dockerfiles/blahdove /path/to/dockerfiles/blahsi trova la Dockerfilevita di blah .


10
usi docker-composein produzione o solo sviluppatori? Grazie per l'aiuto.
Aaron Lelevier,

18
@booyaa Potresti approfondire per favore?
Martin Thoma,

2
Grazie per la risposta! Dockerfile specificare config per un'immagine, e finestra mobile-compose.yml assemblare le immagini insieme .. Una cosa che voglio sottolineare è che, se docker-compose.ymlutilizzare solo l'immagine pubblica (che tira da internet / hub finestra mobile), poi uno non hanno bisogno di un File Docker per eseguire il comando docker-compose up.
Oldyoung,

550

Dockerfile

inserisci qui la descrizione dell'immagine

Un file Docker è un semplice file di testo che contiene i comandi che un utente potrebbe chiamare per assemblare un'immagine.

Esempio, 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

inserisci qui la descrizione dell'immagine

Docker Compose

  • è uno strumento per la definizione e l'esecuzione di applicazioni Docker multi-contenitore.

  • definire i servizi che compongono l'app in docker-compose.ymlmodo che possano essere eseguiti insieme in un ambiente isolato.

  • far funzionare un'app con un solo comando docker-compose up

Esempio, 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 la risposta è che la domanda è mal formata in base alla mancanza di comprensione di Docker vs Docker Compose. Spiegare in modo succinto come i due interagiscono è probabilmente la risposta migliore che mi viene in mente.
Potenza del

53
Non ho idea del perché questa suddivisione esatta non si trovi sulla home page di Docker. Grazie.
codykochmann,

4
Vedo questo tipo di documenti mancanti negli strumenti / soluzioni / framework rilasciati più di recente sul Web. Immagino sia difficile capire perché qualcuno ne abbia bisogno nel caso in cui tu abbia già conosciuto / inventato la soluzione da solo.
Peter Branforn,

36
Quello che manca a questa risposta sono ulteriori informazioni su compose. Lo script di composizione chiama il file docker? Come fa a sapere cosa comporre? L'esempio mostra image: redisma viene da dockerhub? directory locale? ecc ... questo rende confuso per un principiante come me capire cosa sta realmente succedendo
Joe Phillips,

5
Questa risposta insiste sullo scopo multi-container della composizione docker ma ci sono probabilmente molti altri scenari che si desidera utilizzare la composizione docker anche con un solo contenitore come specificare la porta su cui si desidera eseguire il contenitore (impossibile in dockerfile afaik).
Pansoul,

99

Il file Compose descrive il contenitore nel suo stato di esecuzione , lasciando i dettagli su come costruire il contenitore su Dockerfile . http://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volumes

Quando si definisce l'app con Compose in fase di sviluppo, è possibile utilizzare questa definizione per eseguire l'applicazione in diversi ambienti quali CI, gestione temporanea e produzione . https://docs.docker.com/compose/production/

Sembra anche che Compose sia considerato sicuro dalla produzione a partire dall'1.11 , poiché https://docs.docker.com/v1.11/compose/production/ non ha più un avvertimento di non usarlo in produzione come https: // docs .docker.com / v1.10 / compose / production / does.


1
Grazie per aver sollevato il problema. Potete per favore aggiungere un po 'di più di ciò che è stato fissato per la sicurezza della produzione a 1.11?
MA Hossain Tonu,

93

docker-compose esiste per impedirti di scrivere una tonnellata di comandi che dovresti eseguire con docker-cli.

docker-compose semplifica anche l'avvio simultaneo di più contenitori e li collega automaticamente con una qualche forma di rete.

Lo scopo di docker-compose è di funzionare come docker cli ma di emettere più comandi molto più rapidamente.

Per utilizzare docker-compose, è necessario codificare i comandi in esecuzione in un docker-compose.ymlfile.

Non hai intenzione di copiarli incollandoli nel file yaml, c'è una sintassi speciale.

Una volta creato, devi inviarlo al cli di composizione docker e spetterà al cli analizzare il file e creare tutti i diversi contenitori con la configurazione corretta che specifichiamo.

Quindi avrai contenitori separati, diciamo ad esempio, uno è redis-servere il secondo è node-appe vuoi che sia creato usando Dockerfilenella directory corrente.

Inoltre, dopo aver creato quel contenitore, mappereste una porta dal contenitore al computer locale per accedere a tutto ciò che lo esegue al suo interno.

Quindi per il tuo docker-compose.ymlfile vorresti iniziare la prima riga in questo modo:

version: '3'

Questo dice a Docker la versione docker-composeche vuoi usare. Dopo di ciò devi aggiungere:

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

Si prega di notare il rientro, molto importante. Inoltre, nota per un servizio che sto afferrando un'immagine, ma per un altro servizio sto dicendo docker-composedi guardare all'interno della directory corrente per creare l'immagine che verrà utilizzata per il secondo contenitore.

Quindi si desidera specificare tutte le diverse porte che si desidera aprire su questo contenitore.

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

Si noti il ​​trattino, un trattino in un file yaml è il modo in cui si specifica un array. In questo esempio sto mappando 8081sul mio computer locale 8081sul contenitore in questo modo:

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

Quindi la prima porta è il tuo computer locale, e l'altra è la porta sul contenitore, puoi anche distinguere tra i due per evitare confusione in questo modo:

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

Sviluppando il tuo docker-compose.ymlfile in questo modo creerà questi contenitori essenzialmente sulla stessa rete e avranno libero accesso per comunicare tra loro in qualsiasi modo desiderino e scambiare tutte le informazioni che desiderano.

Quando i due contenitori vengono creati utilizzando docker-composenon sono necessarie dichiarazioni di porta.

Ora nel mio esempio, dobbiamo fare una configurazione del codice nell'app Nodejs che assomigli a questo:

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

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

Uso questo esempio sopra per farti sapere che potrebbe esserci qualche configurazione specifica che dovresti fare oltre al docker-compose.ymlfile che potrebbe essere specifico per il tuo progetto.

Ora, se mai ti ritrovi a lavorare con un'app Nodejs e redis vuoi assicurarti di essere a conoscenza della porta predefinita utilizzata da Nodejs, quindi aggiungerò questo:

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

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

Quindi Docker vedrà che l'app Node sta cercando redis-servere reindirizzerà tale connessione verso questo container in esecuzione.

Per tutto il tempo, l' Dockerfileunico contiene questo:

FROM node:alpine

WORKDIR '/app'

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

CMD ["npm", "start"]

Quindi, mentre prima dovresti eseguire docker run myimageper creare un'istanza di tutti i contenitori o servizi all'interno del file puoi invece eseguire docker-compose upe non devi specificare un'immagine perché Docker cercherà nella directory di lavoro corrente e cercherà un docker-compose.ymlfile all'interno di lì.

Prima docker-compose.yml, dovevamo trattare con due comandi separati di docker build .e docker run myimage, ma nel docker-composemondo se vuoi ricostruire le tue immagini che scrivi docker-compose up --build. Ciò indica a Docker di riavviare i contenitori ma di ricostruirlo per ottenere le ultime modifiche.

Quindi docker-composesemplifica il lavoro con più contenitori. La prossima volta che devi avviare questo gruppo di contenitori in background puoi farlo docker-compose up -de fermarli puoi farlo docker-compose down.


14
@Chris È quasi come se ci fossero 3 anni di conoscenza tra questo e la risposta accettata.
Naruto Sempai,

Mi chiedo se qualche buon motivo per me usare docker-compose upse solo un servizio nella mia situazione? Un'altra parola, confronta con docker run xxx, qualche vantaggio se uso docker-compose up?
atline

@atline vedere la risposta di Pansoul per stackoverflow.com/a/45549372/3366962 sui vantaggi di utilizzare docker-composeper contenitori singoli
go2null

1
@PaulRazvanBerg la parte "O" è corretta (ed 6379è la porta predefinita di Redis).
KrishPrabakar

1
Gli esempi di docker-compose.yml mi hanno aiutato a rispondere ad alcune delle domande che avevo su docker-compose. La risposta accettata non è utile, soprattutto per le persone che non conoscono la finestra mobile.
maulik13

43

Nel mio flusso di lavoro, aggiungo un Dockerfile per ogni parte del mio sistema e lo configuro affinché ogni parte possa essere eseguita singolarmente. Quindi aggiungo un docker-compose.yml per riunirli e collegarli.

Il più grande vantaggio (secondo me): quando si collegano i contenitori , è possibile definire un nome e eseguire il ping dei contenitori con questo nome. Pertanto il database potrebbe essere accessibile con il nome dbe non più tramite il suo IP.


Potresti approfondire di più sull'accesso al db con il nome?
Vedran Maricevic.

Da quale parte? In docker-compose è banale, perché è il modo normale quando si definiscono i propri servizi di assegnargli un nome e renderlo accessibile senza la necessità di configurarlo. Nel nostro CI creo una rete, creo il contenitore in questa rete e gli do un nome. Quindi li hai accessibili anche con il loro nome all'interno dei contenitori (non dall'host)
n2o

Nel compositore intendo. Quindi collego le immagini nel compositore e nella mia configurazione dell'app invece dell'IP, prendo di mira MySQL con qualunque nome le abbia dato nel file del compositore?
Vedran Maricevic.

È corretto. Non è nemmeno necessario specificare un collegamento. Sono collegati per impostazione predefinita se la rete non è specificata diversamente. In questo esempio il servizio "web" può eseguire il ping dell'host "redis" con il nome "redis"
n2o

37

"migliore" è relativo. Tutto dipende da quali sono le tue esigenze. La composizione Docker è per l'orchestrazione di più contenitori. Se queste immagini esistono già nel registro della finestra mobile, è meglio elencarle nel file di composizione. Se queste immagini o alcune altre immagini devono essere costruite da file sul tuo computer, puoi descrivere i processi di costruzione di quelle immagini in un file Docker.

Capisco che i Dockerfile sono usati in Docker Compose, ma non sono sicuro che sia buona prassi mettere tutto in un grande Dockerfile con più comandi FROM per le diverse immagini?

L'uso di più DA in un unico file docker non è un'ottima idea perché esiste una proposta per rimuovere la funzione. 13026

Se, ad esempio, vuoi ancorare un'applicazione che utilizza un database e avere i file dell'applicazione sul tuo computer, puoi utilizzare un file di composizione insieme a un file docker come segue

finestra mobile-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 e Docker Compose sono due concetti diversi in Dockerland. Quando parliamo di Docker, le prime cose che mi vengono in mente sono l'orchestrazione, la virtualizzazione a livello di sistema operativo, le immagini, i contenitori, ecc. Cercherò di spiegare ciascuno come segue:

Immagine: un'immagine è un file immutabile e condivisibile archiviato in un registro sicuro di Docker. Un'immagine Docker viene creata da una serie di livelli di sola lettura. Ogni livello rappresenta un'istruzione che viene data nel file Docker dell'immagine. Un'immagine contiene tutti i file binari necessari per l'esecuzione.

inserisci qui la descrizione dell'immagine

Contenitore: un'istanza di un'immagine è chiamata contenitore . Un contenitore è solo un file binario di immagine eseguibile che deve essere eseguito dal sistema operativo host. Un'immagine in esecuzione è un contenitore.

inserisci qui la descrizione dell'immagine

Dockerfile: un Dockerfile è un documento di testo che contiene tutti i comandi / le istruzioni di costruzione, che un utente può chiamare sulla riga di comando per assemblare un'immagine. Questo verrà salvato come a Dockerfile. (Nota la 'f' minuscola.)

inserisci qui la descrizione dell'immagine

Docker-Compose: Compose è uno strumento per la definizione e l'esecuzione di applicazioni Docker multi-container. Con Compose, si utilizza un file YAML per configurare i servizi (contenitori) dell'applicazione. Quindi, con un solo comando, crei e avvii tutti i servizi dalla tua configurazione. Il file di composizione verrà salvato come docker-compose.yml.


14

Immagina di essere il gestore di una società di software e di aver appena acquistato un server nuovo di zecca. Solo l'hardware.

Pensa Dockerfilea un insieme di istruzioni che diresti al tuo amministratore di sistema cosa installare su questo nuovissimo server. Per esempio:

  • Abbiamo bisogno di un Debian Linux
  • aggiungi un web server apache
  • abbiamo bisogno anche di postgresql
  • installa il comandante di mezzanotte
  • quando tutto è fatto, copia tutti i file * .php, * .jpg, ecc. del nostro progetto nella webroot del webserver ( /var/www)

Al contrario, pensa docker-compose.ymla un insieme di istruzioni che diresti al tuo amministratore di sistema come il server può interagire con il resto del mondo. Per esempio,

  • ha accesso a una cartella condivisa da un altro computer,
  • la sua porta 80 è la stessa della porta 8000 del computer host,
  • e così via.

(Questa non è una spiegazione precisa ma abbastanza buona per iniziare.)


4

I file docker devono creare un'immagine, ad esempio da un Ubuntu a osso nudo, è possibile aggiungere mysqlchiamati mySQLsu un'immagine e mywordpresssu una seconda immagine chiamata mywordpress.

Componi i file YAML per acquisire queste immagini ed eseguirle in modo coerente. ad esempio se hai nel tuo docker-compose.ymlfile una chiamata di servizio db:

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

e un servizio chiamato worpress come:

wordpress: 
    image: mywordpress

quindi all'interno del contenitore mywordpress è possibile utilizzare dbper connettersi al contenitore mySQL. Questa magia è possibile perché l'host docker crea un bridge di rete (overlay di rete).


0

Nel mondo dei microservizi (con una base di codice condivisa comune), ogni microservizio avrebbe un Dockerfileconsiderando a livello di root (generalmente al di fuori di tutti i microservizi e dove risiede il POM principale) si definirebbe undocker-compose.yml gruppo per raggruppare tutti i microservizi in un'app completa.

Nel tuo caso "Docker Compose" è preferito "Dockerfile". Pensa "App" Pensa "Componi".


0

Dockerfile è un file che contiene comandi di testo per assemblare un'immagine.

La composizione Docker viene utilizzata per eseguire un ambiente multi-contenitore.

Nel tuo scenario specifico, se hai più servizi per ogni tecnologia che hai citato (servizio 1 usando reddis, servizio 2 usando coniglio mq ecc.), Puoi avere un file Docker per ciascuno dei servizi e un docker comune-compose.yml da eseguire tutto il "Dockerfile" come contenitori.

Se li vuoi tutti in un unico servizio, la finestra mobile-compose sarà un'opzione praticabile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.