Docker Compose vs. Dockerfile - hangisi daha iyi?


384

Docker'ı okuyup öğreniyorum ve kullanmak için Django kurulumunu doğru seçmeye çalışıyorum. Şimdiye kadar ya:

Docker Compose veya Dockerfile

İçinde Dockerfileskullanıldığını anlıyorum Docker Compose, ancak her şeyi FROMfarklı görüntüler için birden fazla komutla büyük bir Dockerfile'a koymanın iyi bir uygulama olup olmadığından emin değilim ?

Aşağıdakileri içeren birkaç farklı resim kullanmak istiyorum:

uwsgi
nginx
postgres
redis
rabbitmq
celery with cron

Lütfen Docker kullanarak bu tür ortamların kurulumunda en iyi uygulamaların neler olduğu konusunda tavsiyelerde bulunun .

Eğer yardımcı olursa, ben Mac'liyim , bu yüzden boot2docker kullanıyorum .

Yaşadığım Bazı Sorunlar:

  1. Docker Compose, Python3 ile uyumlu değil
  2. Projemi kapsayıcılaştırmak istiyorum, bu yüzden büyük bir Dockerfile ideal değilse, Docker Compose kullanarak onu parçalamam gerektiğini hissediyorum
  3. Projeyi Py2 ve Py3 uyumlu hale getirmeye hazırım, bu yüzden django-compose'a doğru eğildim

5
Konu, "Uygulamamı tek veya birden fazla kapsayıcı olarak çalıştırmalı mıyım?" Şeklinde daha iyi ifade edilir. Görünüşe göre değişir ve endişelerin ölçeklenmesi ve ayrılması (hizmet başına bir kap) hususları dikkate alınmalıdır. Bunlar yardımcı olabilir: stackoverflow.com/questions/30534939/… ve quora.com/…
Fabien Snauwaert

Resmi Docker "Başlarken" belgeleri .
jchook

Yanıtlar:


238

Cevap da değil.

Docker Compose (burada compose olarak anılacaktır), projenize build komutunu eklerseniz Dockerfile öğesini kullanır docker-compose.yml.

Docker iş akışınız, oluşturmak Dockerfileistediğiniz her görüntü için uygun bir yapı oluşturmak ve ardından buildkomutu kullanarak görüntüleri birleştirmek için compose komutunu kullanmak olmalıdır .

Falanın hayatının build /path/to/dockerfiles/blahnerede /path/to/dockerfiles/blaholduğunu kullanarak Docker dosyalarınızın yolunu belirleyebilirsiniz Dockerfile.


10
kullanıyorsunuz docker-composeüretimi veya sadece dev? Yardımın için teşekkürler.
Aaron Lelevier

18
@booyaa Bunu biraz açıklayabilir misiniz?
Martin Thoma

2
Cevap için teşekkürler! Dockerfile görüntü için yapılandırma belirtmek ve docker-compose.yml görüntüleri birleştirin .. Belirtmek istediğim bir şey şu ki, docker-compose.ymlsadece genel görüntü (internet / docker hub'dan görüntü çekerek) kullanıyorsanız, o zaman bir Dockerfile komutunu çalıştırır docker-compose up.
Oldyoung

549

Dockerfile

resim açıklamasını buraya girin

Dockerfile, kullanıcının bir görüntüyü birleştirmek için arayabileceği komutları içeren basit bir metin dosyasıdır.

Örnek, 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 Oluştur

resim açıklamasını buraya girin

Docker Oluştur

  • çok kaplamalı Docker uygulamalarını tanımlamak ve çalıştırmak için bir araçtır.

  • uygulamanızı oluşturan hizmetleri tanımlayın docker-compose.ymlizole bir ortamda birlikte çalışabilmeleri .

  • bir uygulamayı tek komutta çalıştırarak çalıştırabilirsiniz docker-compose up

Örnek, docker-compose.yml

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

43
Bu sorunun cevabı, Docker ve Docker Compose arasındaki anlayış eksikliğine dayanarak sorunun yanlış biçimlendirilmiş olmasıdır. İki etkileşimin muhtemelen aklıma gelen en iyi cevap olduğunu kısa bir şekilde açıklamak.
mpowered

53
Bu kesin arızanın neden Docker'ın ana sayfasında yer almadığı hakkında hiçbir fikrim yok. Teşekkürler.
codykochmann

4
Bu tür belgelerin web üzerinde en son yayınlanan araçlarda / çözümlerde / çerçevelerde eksik olduğunu görüyorum. Çözümü zaten biliyor / icat etmiş olmanız durumunda neden birinin ihtiyaç duyduğunu görmek zor.
Peter Branforn

36
Bu cevapta eksik olan beste hakkında daha fazla bilgi. Oluşturma komut dosyası dockerfile'ı çağırıyor mu? Ne yazacağını nereden biliyor? Bu örnek image: redisdockerhub'dan geliyor mu? yerel dizin? vs ... Bu benim gibi yeni bir insanın gerçekten neler olduğunu anlamasını kafa karıştırıcı yapıyor
Joe Phillips

5
Bu yanıt, docker oluşturmanın çok kapsayıcı amacında ısrar eder, ancak docker oluşturmayı kullanmak istediğiniz başka birçok senaryo vardır, hatta konteynerinizin çalışmasını istediğiniz bağlantı noktasını belirtmek gibi (dockerfile afaik'te mümkün değildir).
Pansoul

99

Oluştur dosya açıklar onun çalışır durumda kabı nasıl ayrıntıları bırakarak konteyner inşa etmek Dockerfiles . http://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volumes

Uygulamanızı geliştirmede Oluştur ile tanımladığınızda, uygulamanızı CI, evreleme ve üretim gibi farklı ortamlarda çalıştırmak için bu tanımı kullanabilirsiniz . https://docs.docker.com/compose/production/

Ayrıca Oluştur kabul edilir gibi görünüyor 1.11 gibi üretim güvenli beri https://docs.docker.com/v1.11/compose/production/ artık gibi üretimde kullanmak değil bir uyarı vardır https: // docs .docker.com / v1.10 / compose / production / yapar.


1
Sorunu gündeme getirdiğin için teşekkürler. 1.11'de üretim güvenliği için düzeltilmiş olanlardan biraz daha ekleyebilir misiniz?
MA Hossain Tonu

93

docker-compose, docker-cli ile yapmanız gereken bir ton komut yazmak zorunda kalmanızı sağlar.

docker-compose aynı zamanda birden fazla kapsayıcıyı aynı anda başlatmayı ve bunları bir ağ türüyle otomatik olarak birbirine bağlamayı kolaylaştırır.

Docker-compose'un amacı, docker cli olarak işlev görmektir, ancak birden çok komutu çok daha hızlı bir şekilde vermektir.

Docker-compose'den yararlanmak için, daha önce çalıştırdığınız komutları bir docker-compose.ymldosyaya kodlamanız gerekir .

Sadece onları yaml dosyasına yapıştırmakla kalmayacaksınız, özel bir sözdizimi var.

Oluşturulduktan sonra, docker-compose cli'ye beslemeniz gerekir ve dosyayı ayrıştırmak ve belirttiğimiz doğru yapılandırmayla tüm farklı kapları oluşturmak klibe bağlıdır.

Böylece ayrı kapsayıcılarınız olacak, diyelim ki biri diğeri redis-serverikincisi node-appve Dockerfileşu anki dizininizdeki kullanılarak yaratılmasını istiyorsunuz .

Ayrıca, bu kapsayıcıyı yaptıktan sonra, içinde çalışan her şeye erişmek için kapsayıcıdan yerel makineye bir bağlantı noktası eşlersiniz.

Yani için docker-compose.ymldosyanın bunu gibi ilk satırı başlatmak isteyeyim:

version: '3'

Bu, Docker'a docker-composekullanmak istediğiniz sürümü söyler . Bundan sonra şunları eklemelisiniz:

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

Lütfen girintiye dikkat edin, çok önemli. Ayrıca, bir hizmet için bir resim alıyorum, ancak başka bir hizmet için söylüyorumdocker-compose için ikinci kapsayıcı için kullanılacak görüntüyü oluşturmak için geçerli dizinin içine bakmak .

Ardından, bu kapsayıcıda açmak istediğiniz tüm farklı bağlantı noktalarını belirtmek istersiniz.

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

Lütfen tire işaretini, yaml dosyasındaki tire diziyi nasıl belirlediğimize dikkat edin. Bu örnekte 8081, yerel makinemde 8081kapsayıcıya şu şekilde eşleme yapıyorum :

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

Yani ilk port yerel makineniz, diğeri konteynırdaki porttur, karışıklığı önlemek için ikisi arasında ayrım yapabilirsiniz:

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

docker-compose.ymlDosyanızı bu şekilde geliştirerek, bu kapsayıcıları esas olarak aynı ağ üzerinde oluşturacak ve birbirleriyle istedikleri şekilde iletişim kurmak ve istedikleri kadar bilgi alışverişinde bulunmak için ücretsiz erişime sahip olacaklar.

İki kap kullanılarak oluşturulduğunda docker-composeherhangi bir bağlantı noktası bildirimine ihtiyacımız yoktur.

Şimdi örneğimde, Nodejs uygulamasında şuna benzer bir kod yapılandırması yapmamız gerekiyor:

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

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

Bu örneği, aşağıdakilere ek olarak yapmanız gereken belirli bir yapılandırma olabileceğini bildirmek için kullanıyorum. docker-compose.ymlProjenize özel olabilecek dosyaya .

Şimdi, kendinizi bir Nodejs uygulamasıyla çalışırken bulursanız ve Nodejs'in kullandığı varsayılan bağlantı noktasının farkında olduğunuzdan emin olmak istiyorsanız, bunu ekleyeceğim:

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

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

Docker, Düğüm uygulamasının aradığını görecek redis-serverve bu bağlantıyı çalışan kapsayıcıya yeniden yönlendirecektir.

Tüm zaman boyunca, Dockerfilesadece bunu içerir:

FROM node:alpine

WORKDIR '/app'

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

CMD ["npm", "start"]

Bu nedenle, docker run myimagedosyanın içindeki tüm kapsayıcıların veya hizmetlerin bir örneğini oluşturmak için çalıştırmanız gerekmeden , bunun yerine çalıştırabilirsiniz docker-compose upve Docker geçerli çalışma dizinine bakacak ve docker-compose.ymldosya içinde.

Önce docker-compose.ymlbiz iki ayrı komutlarla uğraşmak zorunda kaldı docker build .ve docker run myimageancak içinde docker-composedünyada size yazmak resimlerinizi yeniden istiyorsanız docker-compose up --build. Bu, Docker'a kapları yeniden başlatmasını ancak en son değişiklikleri almak için yeniden oluşturmasını söyler.

Böylece docker-composebirden fazla kapla çalışmayı kolaylaştırır. Bir dahaki sefere bu kapsayıcı grubunu arka planda başlatmanız gerektiğinde docker-compose up -dve bunları durdurmak için yapabilirsiniz docker-compose down.


14
@Chris Neredeyse bu ve kabul edilen cevap arasında 3 yıllık bir bilgi varmış gibi.
Naruto Sempai

Durumumda docker-compose upsadece bir hizmet varsa kullanmam için iyi bir neden var mı acaba ? Başka bir kelime, karşılaştırmak docker run xxx, kullanırsam herhangi bir yarar docker-compose up?
atline

@atline için Pansoul tepkisini bakın stackoverflow.com/a/45549372/3366962 kullanmanın yararları üzerinde docker-composetek konteynerler için
go2null

1
@PaulRazvanBerg size "Or" kısmı doğrudur (ve Redis'in 6379varsayılan bağlantı noktasıdır).
KrishPrabakar

1
Docker-compose.yml için örnekler, docker-compose hakkında sahip olduğum bazı soruları yanıtlamama yardımcı oldu. Kabul edilen cevap, özellikle liman işçiliğinde yeni olan kişiler için yararlı değildir.
maulik13

43

İş akışımda, sistemimin her parçası için bir Dockerfile ekliyorum ve her parçanın ayrı ayrı çalışabileceği şekilde yapılandırıyorum. Sonra onları bir araya getirmek ve bağlamak için bir docker-compose.yml ekliyorum.

En büyük avantaj (bence): kapları bağlarken, bir ad tanımlayabilir ve kaplarınıza bu adla ping atabilirsiniz. Bu nedenle veritabanınıza dbIP ile erişilip artık IP adresinden erişilemeyebilir .


Db'ye adıyla erişme konusunda daha fazla ayrıntı verebilir misiniz?
Vedran Maricevic.

Hangi tarafta? Docker-compose'de bu çok önemlidir, çünkü hizmetlerinizi tanımlamak için bir ad vermek ve yapılandırmaya gerek kalmadan erişilebilir olmasını sağlamak normal bir yoldur. Bizim CI bir ağ oluşturmak, bu ağda kapsayıcı oluşturmak ve onlara bir ad vermek. Daha sonra, kapsayıcıların içindeki adlarıyla da erişilebilir (ana bilgisayardan değil)
n2o

Bestecide kastediyorum. Bu yüzden görüntüleri besteciye bağlarım ve IP yerine Uygulama yapılandırmamda, MySQL'i besteci dosyasında verdiğim adla hedeflerim?
Vedran Maricevic.

Bu doğru. Bir bağlantı belirtmeniz bile gerekmez. Ağ farklı bir şekilde belirtilmezse, varsayılan olarak bağlanırlar. Bu örnekte hizmet "web" ana makineye ping atabiliyor adıyla "REDIS" "REDIS"
n2o

37

"daha iyi" görecelidir. Her şey ihtiyaçlarınızın ne olduğuna bağlıdır. Docker oluşturma, birden fazla kapsayıcıyı düzenlemek içindir. Bu görüntüler docker kayıt defterinde zaten varsa, bunları oluşturma dosyasında listelemek daha iyidir. Bu görüntülerin veya başka bazı görüntülerin bilgisayarınızdaki dosyalardan oluşturulması gerekiyorsa, bu görüntüleri bir Dockerfile dosyasında oluşturma işlemlerini açıklayabilirsiniz.

Dockerfiles'ın Docker Compose içinde kullanıldığını anlıyorum, ancak her şeyi farklı görüntüler için birden fazla FROM komutuyla büyük bir Dockerfile'a koymanın iyi bir uygulama olup olmadığından emin değilim?

Tek bir dockerfile dosyasında birden fazla FROM kullanmak çok iyi bir fikir değildir, çünkü özelliği kaldırmak için bir teklif vardır. 13026

Örneğin, bir veritabanı kullanan bir uygulamayı dockerize etmek ve uygulama dosyalarının bilgisayarınızda olmasını istiyorsanız, aşağıdaki şekilde bir dockerfile ile birlikte bir oluşturma dosyası kullanabilirsiniz

liman işçisi-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 ve Docker Compose, Dockerland'daki iki farklı kavramdır. Docker hakkında konuştuğumuzda, akla ilk gelen şey düzenleme, işletim sistemi düzeyinde sanallaştırma, görüntüler, kapsayıcılar vb. Her birini aşağıdaki gibi açıklamaya çalışacağım:

Resim: Görüntü, Docker tarafından güvenilen bir kayıt defterinde depolanan değişmez, paylaşılabilir bir dosyadır. Docker görüntüsü bir dizi salt okunur katmandan oluşur. Her katman, görüntünün Dockerdosyasında verilen bir talimatı temsil eder. Bir görüntü çalıştırmak için gerekli tüm ikili dosyaları tutar.

resim açıklamasını buraya girin

Kapsayıcı: Görüntünün bir örneğine kap adı verilir . Kapsayıcı, ana bilgisayar işletim sistemi tarafından çalıştırılacak olan yürütülebilir bir ikili dosyadır. Çalışan görüntü bir kaptır.

resim açıklamasını buraya girin

Dockerfile: Dockerfile, tüm komutları / derleme talimatlarını içeren bir metin belgesidir; bir kullanıcı bir görüntüyü birleştirmek için komut satırını arayabilir. Bu a olarak kaydedilecektir Dockerfile. (Küçük harf 'f'ye dikkat edin.)

resim açıklamasını buraya girin

Docker-Compose: Compose, çok kapsayıcı Docker uygulamalarını tanımlamak ve çalıştırmak için bir araçtır. Compose ile uygulamanızın hizmetlerini (kapsayıcılarını) yapılandırmak için bir YAML dosyası kullanırsınız. Ardından, tek bir komutla, tüm hizmetleri yapılandırmanızdan oluşturur ve başlatırsınız. Compose dosyası olarak kaydedilir docker-compose.yml.


14

Bir yazılım şirketinin yöneticisi olduğunuzu ve yeni bir sunucu satın aldığınızı düşünün. Sadece donanım.

DockerfileSistem yöneticinize bu yeni sunucuya ne yükleyeceğini söyleyeceğiniz bir dizi talimat olarak düşünün . Örneğin:

  • Debian Linux'a ihtiyacımız var
  • apache web sunucusu ekle
  • postgresql'e de ihtiyacımız var
  • gece yarısı komutanını kur
  • her şey bittiğinde, projemizin tüm * .php, * .jpg vb. dosyalarını web sunucusunun web köküne kopyalayın ( /var/www)

Bunun aksine, docker-compose.ymlsistem yöneticinize sunucunun dünyanın geri kalanıyla nasıl etkileşim kurabileceğini söyleyeceğiniz bir dizi talimatı düşünün . Örneğin,

  • başka bir bilgisayardan paylaşılan bir klasöre erişimi var,
  • 80 numaralı bağlantı noktası, ana bilgisayarın 8000 numaralı bağlantı noktası ile aynıdır,
  • ve bunun gibi.

(Bu kesin bir açıklama değil, başlamak için yeterince iyi.)


4

Dockerfiles çıplak kemik Ubuntu örneğin bir görüntü oluşturmak için, sen ekleyebilirler mysqldenilen mySQLbir görüntü üzerinde ve mywordpressdenilen ikinci bir görüntü üzerinde mywordpress.

Oluştur YAML dosyaları bu görüntüleri almak ve bunları uyumlu bir şekilde çalıştırmak içindir. örneğin docker-compose.ymldosyanızda bir servis çağrısı varsa db:

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

ve worpress adı verilen bir hizmet:

wordpress: 
    image: mywordpress

daha sonra mywordpress kapsayıcısının içinde dbmySQL kapsayıcısına bağlanmak için kullanabilirsiniz . Bu sihirbaz, docker ana makineniz bir ağ köprüsü (ağ yerleşimi) oluşturduğundan mümkündür.


0

Microservices dünyasında (ortak bir ortak kod tabanına sahip olan), her bir Microservice Dockerfilekök düzeyinde (genellikle tüm Microservices dışında ve ana POM'nuzun bulunduğu yerde) bir olacaktır docker-compose.yml.

Sizin durumunuzda "Docker Oluştur", "Dockerfile" yerine tercih edilir. "App" Düşün "Oluştur" düşünün.


0

Dockerfile, görüntüyü birleştirmek için metin komutları içeren bir dosyadır.

Docker compose, çoklu kap ortamını çalıştırmak için kullanılır.

Özel senaryoda, bahsettiğiniz her teknoloji için birden fazla hizmetiniz varsa (reddis kullanarak hizmet 1, tavşan mq kullanarak hizmet 2), o zaman hizmetlerin her biri için bir Dockerfile ve çalıştırmak için ortak bir docker-compose.yml dosyası olabilir. kaplar olarak tüm "Dockerfile".

Hepsinin tek bir hizmette olmasını istiyorsanız, docker-compose uygun bir seçenek olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.