Docker Compose против Dockerfile - что лучше?

385

Я читал и изучал Docker и пытаюсь правильно выбрать настройку Django для использования. Пока что есть:

Docker Compose или Dockerfile

Я понимаю, что Dockerfilesиспользуются в Docker Compose, но я не уверен, если это хорошая практика, чтобы поместить все в один большой Dockerfile с несколькими FROMкомандами для разных изображений?

Я хочу использовать несколько разных изображений, которые включают в себя:

uwsgi
nginx
postgres
redis
rabbitmq
celery with cron

Посоветуйте, пожалуйста, как лучше настроить этот тип среды с помощью Docker .

Если это помогает, я на Mac, поэтому использую boot2docker .

Некоторые проблемы у меня были:

  1. Docker Compose не совместим с Python3
  2. Я хочу создать контейнер для своего проекта, поэтому, если один большой Dockerfile не идеален, я чувствую, что мне нужно разбить его с помощью Docker Compose.
  3. Я в порядке, чтобы сделать проект Py2 & Py3 совместимым, поэтому я склоняюсь к django-compose
Аарон Лелевье
источник
5
Вопрос был бы лучше сформулирован как «Должен ли я запускать свое приложение как один или несколько контейнеров?» Кажется, это зависит от ситуации, и следует принимать во внимание вопросы масштабирования и разделения задач (один контейнер на услугу). Это может помочь: stackoverflow.com/questions/30534939/… и quora.com/…
Фабьен Снауварт,
Официальный докер "Getting Started" docs .
jchook

Ответы:

239

Ответ ни один.

Docker Compose (в данном документе называемый compose) будет использовать Dockerfile, если вы добавите команду build в ваш проект docker-compose.yml.

Ваш рабочий процесс Docker должен создавать подходящее Dockerfileдля каждого изображения, которое вы хотите создать, а затем использовать compose для сборки изображений с помощью buildкоманды.

Вы можете указать путь к вашим отдельным файлам Docker, используя, build /path/to/dockerfiles/blahгде /path/to/dockerfiles/blahнаходится Blah Dockerfile.

booyaa
источник
10
Вы используете docker-composeв производстве или только Dev? Спасибо за вашу помощь.
Аарон Лелевье
18
@booyaa Не могли бы вы уточнить это?
Мартин Тома
3
Спасибо за ответ! Dockerfile задает config для image, а docker-compose.yml собирает изображения вместе. Я хочу отметить, что если docker-compose.ymlиспользовать только общедоступное изображение (извлечение изображения из концентратора Интернета / докера), то не нужно Dockerfile для запуска команды docker-compose up.
Oldyoung
550

Dockerfile

введите описание изображения здесь

Dockerfile - это простой текстовый файл, содержащий команды, которые пользователь может вызвать для сборки изображения.

Пример, 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

введите описание изображения здесь

Docker Compose

  • это инструмент для определения и запуска мультиконтейнерных приложений Docker.

  • Определите сервисы, из которых состоит ваше приложение, docker-compose.ymlчтобы они могли работать вместе в изолированной среде.

  • запустите приложение одной командой, просто запустив docker-compose up

Пример, docker-compose.yml

version: "3"
services:
  web:
    build: .
    ports:
    - '5000:5000'
    volumes:
    - .:/code
    - logvolume01:/var/log
    links:
    - redis
  redis:
    image: redis
    volumes:
      logvolume01: {}
cyber8200
источник
43
@sg ответ таков: вопрос плохо сформулирован из-за непонимания Docker vs Docker Compose. Краткое объяснение того, как эти два взаимодействия взаимодействуют, вероятно, лучший ответ, который я могу придумать.
Усиленный
53
Я понятия не имею, почему эта точная поломка не сидит на домашней странице Докера. Спасибо.
codykochmann
4
Я вижу, что такого рода документы отсутствуют в самых последних выпущенных инструментах / решениях / платформах в Интернете. Я думаю, трудно понять, зачем это кому-то нужно, если вы уже знаете / изобрели решение самостоятельно.
Питер Бранфорн
36
В этом ответе отсутствует дополнительная информация о compose. Сценарий compose вызывает dockerfile? Как он знает, что сочинять? Пример показывает, image: redisно это от dockerhub? локальный каталог? и т. д. ... для такого новичка, как я, сбивает с толку понимание того, что на самом деле происходит
Джо Филлипс
5
Этот ответ настаивает на мультиконтейнерном назначении docker compose, но, вероятно, есть много других сценариев, которые вы хотите использовать docker compose, даже с одним контейнером, например, указание порта, на котором вы хотите запускать свой контейнер (невозможно в dockerfile afaik).
Pansoul
99

Compose файл описывает контейнер в рабочем состоянии , оставляя детали о том , как построить контейнер для Dockerfiles . http://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volumes

Когда вы определяете свое приложение с помощью Compose в процессе разработки, вы можете использовать это определение для запуска приложения в различных средах, таких как CI, подготовка и производство . https://docs.docker.com/compose/production/

Похоже также, что с 1.11 Compose считается безопасным для производства , так как https://docs.docker.com/v1.11/compose/production/ больше не имеет предупреждения о том, что его нельзя использовать в таких продуктах, как https: // docs. .docker.com / v1.10 / compose / production / do .

Питер Кокк
источник
1
Спасибо, что подняли вопрос. Не могли бы вы добавить еще что-то, что было исправлено для безопасности производства в 1.11?
М.А. Хоссейн Тону
93

docker-compose существует для того, чтобы вам приходилось писать кучу команд, которые вам бы пришлось делать с помощью docker-cli.

Docker-compose также позволяет легко запускать несколько контейнеров одновременно и автоматически соединять их вместе с какой-либо формой сетевого взаимодействия.

Цель docker-compose - функционировать как docker cli, но выполнять несколько команд намного быстрее.

Чтобы использовать docker-compose, вам нужно закодировать команды, которые вы выполняли ранее, в docker-compose.ymlфайл.

Вы не просто скопируете, вставите их в файл yaml, есть специальный синтаксис.

После создания вы должны передать его в docker-compose cli, и у вас будет возможность проанализировать файл и создать все различные контейнеры с правильной конфигурацией, которую мы указали.

Таким образом, у вас будут отдельные контейнеры, скажем, например, один есть, redis-serverа второй - node-appи вы хотите, чтобы он был создан с использованием Dockerfileв вашем текущем каталоге.

Кроме того, после создания этого контейнера вы должны отобразить некоторый порт из контейнера на локальную машину, чтобы получить доступ ко всему, что работает внутри него.

Итак, для вашего docker-compose.ymlфайла вы бы хотели начать первую строку примерно так:

version: '3'

Это говорит Docker о версии, которую docker-composeвы хотите использовать. После этого вы должны добавить:

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

Пожалуйста, обратите внимание на отступ, очень важно. Кроме того, обратите внимание, что для одного сервиса я собираю изображение, но для другого сервиса я предлагаю docker-composeзаглянуть в текущий каталог, чтобы создать образ, который будет использоваться для второго контейнера.

Затем вы хотите указать все различные порты, которые вы хотите открыть в этом контейнере.

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

Обратите внимание на тире, тире в файле yaml - это то, как мы указываем массив. В этом примере я сопоставляю 8081свою локальную машину с 8081контейнером следующим образом:

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

Таким образом, первый порт - это ваша локальная машина, а другой - порт в контейнере, вы также можете различать два, чтобы избежать путаницы, например:

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

Разрабатывая docker-compose.ymlподобный файл, он будет создавать эти контейнеры, по существу, в одной и той же сети, и они будут иметь свободный доступ для общения друг с другом любым удобным для них способом и обмена таким количеством информации, как они захотят.

Когда два контейнера создаются с использованием, docker-composeнам не нужны никакие объявления портов.

Теперь в моем примере нам нужно выполнить настройку кода в приложении Nodejs, которое выглядит примерно так:

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

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

Я использую этот пример выше, чтобы вы знали, что может быть какая-то конкретная конфигурация, которую вам придется сделать в дополнение к docker-compose.yml файлу, который может относиться к вашему проекту.

Теперь, если вы когда-нибудь обнаружите, что работаете с приложением Nodejs и выполнили повтор, вы хотите убедиться, что знаете о порте по умолчанию, который использует Nodejs, поэтому я добавлю это:

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

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

Итак, Docker увидит, что приложение Node ищет redis-serverи перенаправит это соединение в этот работающий контейнер.

Все время Dockerfileтолько содержит это:

FROM node:alpine

WORKDIR '/app'

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

CMD ["npm", "start"]

Итак, если раньше вам нужно было запустить docker run myimageэкземпляр всех контейнеров или служб внутри файла, вы можете вместо этого запустить его, docker-compose upи вам не нужно указывать изображение, потому что Docker будет искать в текущем рабочем каталоге и искатьdocker-compose.yml файл внутри там.

Раньше docker-compose.ymlнам приходилось иметь дело с двумя отдельными командами docker build .и docker run myimage, но в docker-composeмире, если вы хотите восстановить свои изображения, вы пишете docker-compose up --build. Это говорит Docker снова запускать контейнеры, но перестраивать его, чтобы получить последние изменения.

Так что docker-composeоблегчает работу с несколькими контейнерами. В следующий раз, когда вам нужно будет запустить эту группу контейнеров в фоновом режиме, вы можете сделать это docker-compose up -dи остановить их docker-compose down.

Даниил
источник
14
@Chris Это похоже на то, что между этим и принятым ответом есть знания за 3 года.
Наруто
Интересно, есть ли для меня веская причина использовать docker-compose upхотя бы один сервис в моей ситуации? Другое слово, сравните с docker run xxx, какую выгоду, если я буду использовать docker-compose up?
позднее
@atline см. ответ Pansoul на stackoverflow.com/a/45549372/3366962 о преимуществах использования docker-composeдля отдельных контейнеров
go2null
1
@PaulRazvanBerg у вас "или" часть верна (и 6379является портом Redis по умолчанию).
КришПрабакар
1
Примеры для docker-compose.yml помогли мне ответить на некоторые мои вопросы о docker-compose. Принятый ответ бесполезен, особенно для новичков в докере.
maulik13
43

В своем рабочем процессе я добавляю Dockerfile для каждой части моей системы и настраиваю его так, чтобы каждая часть могла запускаться отдельно. Затем я добавляю docker-compose.yml, чтобы собрать их вместе и связать их.

Самое большое преимущество (на мой взгляд): при связывании контейнеров вы можете определить имя и пропинговать ваши контейнеры этим именем. Поэтому ваша база данных может быть доступна с именем dbи больше не по ее IP.

N2O
источник
Не могли бы вы подробнее рассказать о доступе к БД по имени?
Ведран Марицевич.
На какой части? В docker-compose это тривиально, потому что это обычный способ при определении ваших сервисов дать ему имя и сделать его доступным без необходимости его настройки. В нашем CI я создаю сеть, создаю контейнер в этой сети и даю им имя. Тогда у вас также есть доступ к ним по имени внутри контейнеров (не от хоста)
n2o
В композиторе я имею ввиду. Поэтому я связываю изображения в composer, и в конфигурации моего приложения вместо IP я помечаю MySQL по имени, которое я дал ему в файле composer?
Ведран Марицевич.
Это правильно. Вам даже не нужно указывать ссылку. Они связаны по умолчанию, если сеть не указана иначе. В этом примере служба «web» может пропинговать хост «redis» по имени «redis»
n2o
37

«лучше» относительно. Все зависит от ваших потребностей. Docker compose предназначен для организации нескольких контейнеров. Если эти образы уже существуют в реестре Docker, то лучше перечислить их в файле композиции. Если эти изображения или некоторые другие изображения должны быть собраны из файлов на вашем компьютере, вы можете описать процессы создания этих изображений в Dockerfile.

Я понимаю, что Dockerfiles используются в Docker Compose, но я не уверен, является ли хорошей практикой помещать все в один большой Dockerfile с несколькими командами FROM для разных образов?

Использование нескольких FROM в одном файле Docker не очень хорошая идея, потому что есть предложение удалить эту функцию. 13026

Если, например, вы хотите докеризировать приложение, которое использует базу данных и имеет файлы приложения на вашем компьютере, вы можете использовать файл компоновки вместе с файлом докера следующим образом

докер-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
источник
30

Dockerfile и Docker Compose - это две разные концепции в Dockerland. Когда мы говорим о Docker, первое, что приходит на ум, это оркестровка, виртуализация на уровне ОС, образы, контейнеры и т. Д. Я постараюсь объяснить каждый из них следующим образом:

Изображение: изображение - это неизменяемый общий файл, который хранится в надежном реестре Docker. Образ Docker состоит из ряда слоев, доступных только для чтения. Каждый слой представляет инструкцию, которая дается в Dockerfile изображения. Изображение содержит все необходимые двоичные файлы для запуска.

введите описание изображения здесь

Контейнер: экземпляр изображения называется контейнером . Контейнер - это просто исполняемый двоичный файл образа, который должен запускаться операционной системой хоста. Работающее изображение - это контейнер.

введите описание изображения здесь

Dockerfile: Dockerfile - это текстовый документ, который содержит все команды / инструкции по сборке, которые пользователь может вызвать в командной строке для сборки образа. Это будет сохранено как Dockerfile. (Обратите внимание на строчную букву 'f'.)

введите описание изображения здесь

Docker-Compose: Compose - это инструмент для определения и запуска многоконтейнерных приложений Docker. С Compose вы используете файл YAML для настройки сервисов вашего приложения (контейнеров). Затем с помощью одной команды вы создаете и запускаете все службы из вашей конфигурации. Файл Compose будет сохранен как docker-compose.yml.

Вакас Ахмед
источник
14

Представьте, что вы менеджер компании-разработчика программного обеспечения и только что купили новый сервер. Просто железо.

Подумайте, Dockerfileкак набор инструкций, которые вы скажете своему системному администратору, что устанавливать на этот новый сервер. Например:

  • Нам нужен Debian Linux
  • добавить веб-сервер Apache
  • нам нужен также postgresql
  • установить полночь командир
  • когда все сделано, скопируйте все * .php, * .jpg и т. д. файлы нашего проекта в webroot веб-сервера ( /var/www)

В отличие от docker-compose.ymlэтого, вы должны представить себе набор инструкций, которые вы скажете своему системному администратору, как сервер может взаимодействовать с остальным миром. Например,

  • у него есть доступ к общей папке с другого компьютера,
  • его порт 80 совпадает с портом 8000 хост-компьютера,
  • и так далее.

(Это не точное объяснение, но достаточно хорошее для начала.)

Чонгор Халмай
источник
4

Dockerfiles предназначены для создания образа, например, из голой Ubuntu, вы можете добавить mysqlвызываемый mySQLна одном изображении, а mywordpressна втором - вызываемом mywordpress.

Составьте файлы YAML, чтобы взять эти изображения и выполнить их связно. например, если в вашем docker-compose.ymlфайле есть сервисный вызов db:

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

и сервис под названием worpress, такой как:

wordpress: 
    image: mywordpress

затем внутри контейнера mywordpress вы можете использовать его dbдля подключения к контейнеру mySQL. Это волшебство возможно, потому что ваш хост докер создает сетевой мост (сетевое наложение).

Хьюго Р
источник
0

В мире микросервисов (имеющих общую общую кодовую базу) каждый микросервис будет иметь некоторое значение, Dockerfileтогда как на корневом уровне (как правило, за пределами всех микросервисов и где находится ваш родительский POM) вы определяетеdocker-compose.yml чтобы сгруппировать все микросервисы в полноценное приложение.

В вашем случае «Docker Compose» предпочтительнее «Dockerfile». Подумайте «приложение» Подумайте «Составить».

KrishPrabakar
источник
0

Dockerfile - это файл, который содержит текстовые команды для сборки изображения.

Docker compose используется для запуска мультиконтейнерной среды.

В вашем конкретном сценарии, если у вас есть несколько служб для каждой упомянутой вами технологии (служба 1, использующая reddis, служба 2, использующая rabbit mq и т. Д.), То вы можете иметь Dockerfile для каждой из служб и общий docker-compose.yml для запуска все "Dockerfile" как контейнеры.

Если вы хотите, чтобы все они были в одном сервисе, docker-compose будет приемлемым вариантом.

Мудассир Шахзад
источник