Docker Compose vs. Dockerfile - mana yang lebih baik?

384

Saya telah membaca dan belajar tentang Docker , dan saya mencoba memilih dengan benar pengaturan Django untuk digunakan. Sejauh ini ada:

Docker Compose atau Dockerfile

Saya mengerti yang Dockerfilesdigunakan Docker Compose, tapi saya tidak yakin apakah itu praktik yang baik untuk meletakkan semuanya dalam satu Dockerfile besar dengan beberapa FROMperintah untuk gambar yang berbeda?

Saya ingin menggunakan beberapa gambar berbeda yang meliputi:

uwsgi
nginx
postgres
redis
rabbitmq
celery with cron

Mohon saran tentang apa praktik terbaik dalam mengatur jenis lingkungan ini menggunakan Docker .

Jika ini membantu, saya menggunakan Mac, jadi gunakan boot2docker .

Beberapa Masalah yang saya alami:

  1. Susun Docker tidak kompatibel dengan Python3
  2. Saya ingin menampung proyek saya, jadi jika satu Dockerfile besar tidak ideal, maka saya merasa saya perlu memecahnya menggunakan Docker Compose
  3. Saya ok untuk membuat proyek Py2 & Py3 kompatibel, jadi saya condong ke django-compose
Aaron Lelevier
sumber
5
Masalahnya akan lebih baik diungkapkan sebagai "Haruskah saya menjalankan aplikasi saya sebagai satu atau beberapa wadah?" Tampaknya itu tergantung dan bahwa masalah penskalaan dan pemisahan masalah (satu wadah per layanan) harus diperhitungkan. Ini mungkin membantu: stackoverflow.com/questions/30534939/… dan quora.com/…
Fabien Snauwaert
Dok Dokumentasi "Persiapan Awal" resmi .
jchook

Jawaban:

239

Jawabannya adalah tidak.

Docker Compose (di sini disebut sebagai compose) akan menggunakan Dockerfile jika Anda menambahkan perintah build ke proyek Anda docker-compose.yml.

Alur kerja Docker Anda harus berupa bangunan yang cocok Dockerfileuntuk setiap gambar yang ingin Anda buat, lalu gunakan menulis untuk merakit gambar menggunakan buildperintah.

Anda dapat menentukan jalur ke Dockerfiles pribadi Anda menggunakan build /path/to/dockerfiles/blahdi /path/to/dockerfiles/blahmana bla Dockerfiletinggal.

booyaa
sumber
10
apakah Anda menggunakan docker-composedalam produksi atau hanya dev? Terima kasih atas bantuan Anda.
Aaron Lelevier
18
@ booyaa Bisakah Anda jelaskan tentang itu?
Martin Thoma
2
Terima kasih atas jawabannya! Dockerfile menentukan konfigurasi untuk gambar, dan docker-compose.yml merakit gambar bersama-sama .. Satu hal yang ingin saya tunjukkan adalah, Jika docker-compose.ymlhanya menggunakan gambar publik (menarik gambar dari hub internet / buruh pelabuhan), maka seseorang tidak memerlukan Dockerfile untuk menjalankan perintah docker-compose up.
Oldyoung
549

Dockerfile

masukkan deskripsi gambar di sini

Dockerfile adalah file teks sederhana yang berisi perintah yang bisa dipanggil pengguna untuk merakit gambar.

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

Susun Docker

masukkan deskripsi gambar di sini

Susun Docker

  • adalah alat untuk mendefinisikan dan menjalankan aplikasi Docker multi-kontainer.

  • mendefinisikan layanan yang membentuk aplikasi Anda docker-compose.ymlsehingga mereka dapat dijalankan bersama di lingkungan yang terisolasi.

  • menjalankan aplikasi dalam satu perintah dengan hanya menjalankan docker-compose up

Contoh, docker-compose.yml

version: "3"
services:
  web:
    build: .
    ports:
    - '5000:5000'
    volumes:
    - .:/code
    - logvolume01:/var/log
    links:
    - redis
  redis:
    image: redis
    volumes:
      logvolume01: {}
cyber8200
sumber
43
@sg jawabannya adalah bahwa pertanyaannya kurang lengkap karena kurangnya pemahaman tentang Docker vs Docker Compose. Menjelaskan dengan singkat bagaimana keduanya berinteraksi mungkin merupakan jawaban terbaik yang dapat saya pikirkan.
mpowered
53
Saya tidak tahu mengapa rincian yang tepat ini tidak ada di halaman utama Docker. Terima kasih.
codykochmann
4
Saya melihat dokumen semacam ini hilang di alat / solusi / kerangka kerja yang paling baru dirilis di web. Saya kira sulit untuk melihat mengapa seseorang membutuhkannya jika Anda sudah tahu / menemukan solusinya sendiri.
Peter Branforn
36
Apa yang hilang dari jawaban ini adalah info lebih lanjut tentang menulis. Apakah skrip penulisan memanggil dockerfile? Bagaimana ia tahu apa yang harus disusun? Contohnya menunjukkan image: redistetapi apakah itu dari dockerhub? direktori lokal? dll ... ini membuatnya membingungkan bagi seorang pemula seperti saya untuk memahami apa yang sebenarnya terjadi
Joe Phillips
5
Tanggapan ini menekankan pada tujuan multi-kontainer dari komposisi buruh pelabuhan, tetapi mungkin ada banyak skenario lain yang ingin Anda gunakan untuk menulis komposisi buruh pelabuhan bahkan dengan hanya satu wadah seperti menentukan port tempat Anda ingin wadah Anda dijalankan (tidak mungkin dalam dockerfile afaik).
Pansoul
99

File Compose menggambarkan wadah dalam kondisi berjalan , meninggalkan detail tentang cara membuat wadah ke Dockerfiles . http://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volume

Ketika Anda mendefinisikan aplikasi Anda dengan Compose dalam pengembangan, Anda dapat menggunakan definisi ini untuk menjalankan aplikasi Anda di lingkungan yang berbeda seperti CI, pementasan, dan produksi . https://docs.docker.com/compose/production/

Tampaknya juga Compose dianggap aman untuk produksi sejak 1.11 , karena https://docs.docker.com/v1.11/compose/production/ tidak lagi memiliki peringatan untuk tidak menggunakannya dalam produksi seperti https: // docs .docker.com / v1.10 / compose / produksi / tidak.

Peeter Kokk
sumber
1
Terima kasih telah mengemukakan masalah ini. Bisakah Anda menambahkan lebih banyak dari apa yang diperbaiki untuk keamanan produksi di 1,11?
MA Hossain Tonu
93

docker-compose ada untuk membuat Anda harus menulis banyak perintah yang harus Anda lakukan dengan docker-cli.

docker-compose juga memudahkan untuk memulai beberapa wadah pada saat yang sama dan secara otomatis menghubungkannya bersama dengan beberapa bentuk jaringan.

Tujuan dari docker-compose adalah untuk berfungsi sebagai docker cli tetapi untuk mengeluarkan banyak perintah dengan lebih cepat.

Untuk menggunakan komposisi buruh pelabuhan, Anda harus menyandikan perintah yang Anda jalankan sebelum menjadi docker-compose.ymlfile.

Anda tidak hanya akan menyalinnya ke file yaml, ada sintaks khusus.

Setelah dibuat, Anda harus mengumpankannya ke cli-compose docker dan tergantung pada cli untuk mengurai file dan membuat semua wadah berbeda dengan konfigurasi yang benar yang kami tentukan.

Jadi Anda akan memiliki wadah yang terpisah, katakanlah misalnya, satu adalah redis-serverdan yang kedua adalah node-appdan Anda ingin yang dibuat menggunakan Dockerfiledi direktori Anda saat ini.

Selain itu, setelah membuat wadah itu, Anda akan memetakan beberapa port dari wadah ke mesin lokal untuk mengakses semua yang berjalan di dalamnya.

Jadi untuk docker-compose.ymlfile Anda, Anda ingin memulai baris pertama seperti:

version: '3'

Itu memberi tahu Docker versi docker-composeyang ingin Anda gunakan. Setelah itu Anda harus menambahkan:

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

Harap perhatikan indentasi, sangat penting. Juga, perhatikan untuk satu layanan saya mengambil gambar, tetapi untuk layanan lain saya mengatakan docker-composeuntuk melihat ke dalam direktori saat ini untuk membangun gambar yang akan digunakan untuk wadah kedua.

Kemudian Anda ingin menentukan semua port yang berbeda yang ingin Anda buka pada wadah ini.

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

Harap perhatikan tanda hubung, tanda hubung dalam file yaml adalah cara kami menentukan array. Dalam contoh ini saya memetakan 8081pada mesin lokal saya ke 8081wadah seperti:

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

Jadi port pertama adalah mesin lokal Anda, dan yang lainnya adalah port pada wadah, Anda juga bisa membedakan keduanya untuk menghindari kebingungan seperti:

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

Dengan mengembangkan docker-compose.ymlfile Anda seperti ini, itu akan membuat wadah ini pada dasarnya jaringan yang sama dan mereka akan memiliki akses bebas untuk berkomunikasi satu sama lain dengan cara apa pun yang mereka suka dan bertukar informasi sebanyak yang mereka inginkan.

Ketika dua kontainer dibuat menggunakan docker-composekita tidak perlu deklarasi port.

Sekarang dalam contoh saya, kita perlu melakukan beberapa konfigurasi kode di aplikasi Nodejs yang terlihat seperti ini:

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

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

Saya menggunakan contoh ini di atas untuk membuat Anda sadar bahwa mungkin ada beberapa konfigurasi khusus yang harus Anda lakukan selain docker-compose.ymlfile yang mungkin spesifik untuk proyek Anda.

Sekarang, jika Anda pernah menemukan diri Anda bekerja dengan aplikasi Nodejs dan redis Anda ingin memastikan Anda mengetahui port default yang digunakan Nodejs jadi saya akan menambahkan ini:

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

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

Jadi Docker akan melihat bahwa aplikasi Node sedang mencari redis-serverdan mengarahkan kembali koneksi itu ke wadah yang sedang berjalan ini.

Sepanjang waktu, Dockerfilehanya berisi ini:

FROM node:alpine

WORKDIR '/app'

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

CMD ["npm", "start"]

Jadi, padahal sebelumnya Anda harus menjalankan docker run myimageuntuk membuat instance dari semua wadah atau layanan di dalam file yang dapat Anda jalankan, docker-compose updan Anda tidak harus menentukan gambar karena Docker akan mencari di direktori kerja saat ini dan mencari docker-compose.ymlFile di dalam sana.

Sebelumnya docker-compose.yml, kami harus berurusan dengan dua perintah terpisah dari docker build .dan docker run myimage, tetapi di docker-composedunia jika Anda ingin membangun kembali gambar yang Anda tulis docker-compose up --build. Itu memberitahu Docker untuk memulai kembali wadah tetapi membangun kembali untuk mendapatkan perubahan terbaru.

Jadi docker-composemembuatnya lebih mudah untuk bekerja dengan banyak wadah. Lain kali Anda harus memulai kelompok wadah ini di latar belakang yang dapat Anda lakukandocker-compose up -d dan menghentikannya, Anda dapat melakukannya docker-compose down.

Daniel
sumber
14
@ Chris Hampir seperti ada 3 tahun pengetahuan antara ini dan jawaban yang diterima.
Naruto Sempai
Saya ingin tahu apakah ada alasan bagus untuk saya gunakan docker-compose upjika hanya satu layanan dalam situasi saya? Kata lain, bandingkan dengan docker run xxx, apakah ada manfaatnya jika saya gunakan docker-compose up?
atline
@atline lihat respons Pansoul terhadap stackoverflow.com/a/45549372/3366962 tentang manfaat menggunakan docker-composewadah tunggal
go2null
1
@PaulRazvanBerg Anda "Atau" bagian sudah benar (dan 6379merupakan port default Redis).
KrishPrabakar
1
Contoh untuk docker-compose.yml membantu saya menjawab beberapa pertanyaan yang saya miliki tentang docker-compose. Jawaban yang diterima tidak berguna, terutama bagi orang yang baru mengenal buruh pelabuhan.
maulik13
43

Dalam alur kerja saya, saya menambahkan Dockerfile untuk setiap bagian dari sistem saya dan mengkonfigurasinya agar setiap bagian dapat berjalan secara individual. Lalu saya menambahkan buruh pelabuhan-compose.yml untuk menyatukan mereka dan menghubungkan mereka.

Keuntungan terbesar (menurut saya): saat menautkan wadah , Anda dapat menentukan nama dan ping wadah Anda dengan nama ini. Karena itu basis data Anda mungkin dapat diakses dengan nama dbdan tidak lagi dengan IP-nya.

n2o
sumber
Bisakah Anda menguraikan lebih lanjut tentang mengakses db dengan namanya?
Vedran Maricevic.
Di bagian mana? Dalam komposisi buruh pelabuhan itu sepele, karena itu adalah cara normal ketika mendefinisikan layanan Anda untuk memberikan nama dan membuatnya dapat diakses tanpa perlu mengkonfigurasinya. Dalam CI kami, saya membuat jaringan, membuat wadah di jaringan ini dan memberi mereka nama. Maka Anda juga dapat
mengaksesnya
Dalam komposer yang saya maksud. Jadi saya menautkan gambar dalam komposer, dan dalam konfigurasi App saya, bukan IP, saya memperbesar MySQL dengan nama apa pun yang saya berikan dalam file komposer?
Vedran Maricevic.
Itu benar. Anda bahkan tidak perlu menentukan tautan. Mereka terhubung secara default jika jaringan tidak ditentukan secara berbeda. Dalam contoh ini layanan "web" dapat melakukan ping ke host "redis" dengan namanya "redis"
n2o
37

"lebih baik" adalah relatif. Itu semua tergantung pada apa kebutuhan Anda. Tulisan Docker adalah untuk mengatur banyak wadah. Jika gambar-gambar ini sudah ada dalam register buruh pelabuhan, maka lebih baik untuk mendaftarkannya dalam file penulisan. Jika gambar-gambar ini atau beberapa gambar lain harus dibangun dari file di komputer Anda, maka Anda dapat menggambarkan proses membangun gambar-gambar itu di Dockerfile.

Saya mengerti bahwa Dockerfiles digunakan dalam Docker Compose, tetapi saya tidak yakin apakah itu praktik yang baik untuk meletakkan semuanya dalam satu Dockerfile besar dengan beberapa perintah FROM untuk gambar yang berbeda?

Menggunakan multiple FROM dalam satu dockerfile bukan ide yang sangat bagus karena ada proposal untuk menghapus fitur. 13026

Jika misalnya, Anda ingin melakukan dockerize aplikasi yang menggunakan database dan memiliki file aplikasi di komputer Anda, Anda dapat menggunakan file penulisan bersama dengan dockerfile sebagai berikut

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
sumber
30

Dockerfile dan Docker Compose adalah dua konsep berbeda di Dockerland. Ketika kita berbicara tentang Docker, hal pertama yang muncul di pikiran adalah orkestrasi, virtualisasi level OS, gambar, wadah, dll. Saya akan mencoba menjelaskan masing-masing sebagai berikut:

Gambar: Gambar adalah file yang tidak dapat diubah dan dapat dibagikan yang disimpan dalam registri yang dipercaya oleh Docker. Gambar Docker dibangun dari serangkaian lapisan hanya baca. Setiap layer mewakili instruksi yang diberikan di Dockerfile gambar. Sebuah gambar menahan semua binari yang diperlukan untuk dijalankan.

masukkan deskripsi gambar di sini

Wadah: Contoh dari sebuah gambar disebut wadah . Wadah hanyalah biner gambar yang dapat dieksekusi yang dijalankan oleh OS host. Gambar berjalan adalah sebuah wadah.

masukkan deskripsi gambar di sini

Dockerfile: Dockerfile adalah dokumen teks yang berisi semua perintah / instruksi pembangunan, pengguna dapat memanggil pada baris perintah untuk mengumpulkan gambar. Ini akan disimpan sebagai Dockerfile. (Perhatikan huruf kecil 'f'.)

masukkan deskripsi gambar di sini

Docker-Compose: Compose adalah alat untuk mendefinisikan dan menjalankan aplikasi Docker multi-kontainer. Dengan Tulis, Anda menggunakan file YAML untuk mengonfigurasi layanan aplikasi Anda (wadah). Kemudian, dengan satu perintah, Anda membuat dan memulai semua layanan dari konfigurasi Anda. File Tulis akan disimpan sebagai docker-compose.yml.

Waqas Ahmed
sumber
14

Bayangkan Anda adalah manajer perusahaan perangkat lunak dan Anda baru saja membeli server baru. Hanya perangkat kerasnya.

Anggap Dockerfilesebagai seperangkat instruksi yang Anda akan memberi tahu administrator sistem Anda apa yang harus diinstal pada server baru ini. Sebagai contoh:

  • Kami membutuhkan linux Debian
  • tambahkan server web apache
  • kita perlu postgresql juga
  • instal komandan tengah malam
  • ketika semua selesai, salin semua file * .php, * .jpg, dll dari proyek kami ke dalam webroot dari server web ( /var/www)

Sebaliknya, anggap docker-compose.ymlsebagai seperangkat instruksi yang Anda akan memberitahu administrator sistem Anda bagaimana server dapat berinteraksi dengan seluruh dunia. Sebagai contoh,

  • ia memiliki akses ke folder bersama dari komputer lain,
  • itu port 80 sama dengan port 8000 dari komputer host,
  • dan seterusnya.

(Ini bukan penjelasan yang tepat tetapi cukup baik untuk memulai.)

Csongor Halmai
sumber
4

Dockerfiles adalah untuk membangun gambar misalnya dari Ubuntu, Anda dapat menambahkan mysqldipanggil mySQLpada satu gambar dan mywordpresspada gambar kedua disebut mywordpress.

Tulis file YAML adalah untuk mengambil gambar ini dan menjalankannya secara terpadu. misalnya jika Anda memiliki docker-compose.ymlpanggilan layanan dalam file Anda db:

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

dan layanan yang disebut worpress seperti:

wordpress: 
    image: mywordpress

kemudian di dalam wadah mywordpress Anda dapat menggunakan dbuntuk terhubung ke wadah mySQL Anda. Keajaiban ini dimungkinkan karena host buruh pelabuhan Anda membuat jembatan jaringan (hamparan jaringan).

Hugo R
sumber
0

Dalam dunia Microservices (memiliki basis kode bersama yang umum), setiap Microservice akan memiliki Dockerfilesedangkan di tingkat root (umumnya di luar semua Microservices dan di mana POM orang tua Anda berada) Anda akan menentukandocker-compose.yml untuk mengelompokkan semua Microservices ke dalam aplikasi full-blown.

Dalam kasus Anda "Susunan Docker" lebih disukai daripada "Dockerfile". Pikirkan "App" Think "Compose".

KrishPrabakar
sumber
0

Dockerfile adalah file yang berisi perintah teks untuk merakit gambar.

Tulisan Docker digunakan untuk menjalankan lingkungan multi-kontainer.

Dalam skenario spesifik Anda, jika Anda memiliki beberapa layanan untuk setiap teknologi yang Anda sebutkan (layanan 1 menggunakan reddis, layanan 2 menggunakan kelinci mq dll), maka Anda dapat memiliki Dockerfile untuk setiap layanan dan docker-compose.yml umum untuk menjalankan semua "Dockerfile" sebagai wadah.

Jika Anda ingin semuanya dalam satu layanan, komposisi buruh pelabuhan akan menjadi opsi yang layak.

Mudassir Shahzad
sumber