docker compose против dockerfile - что лучше?

<p>я читал и узнал о <a href="https://docs.docker.com/">docker</a> и пытаюсь правильно выбрать настройку django для использования. пока что есть:</p><p> <a href="https://docs.docker.com/compose/">docker compose</a> или <a href="https://docs.docker.com/engine/reference/builder/">dockerfile</a> </p><p>я понимаю, что <code>dockerfiles</code> используются в <code>docker compose</code>, но я не уверен, является ли хорошей практикой помещать все в один большой dockerfile с несколькими командами <code>from</code> для разных изображений?</p><p>я хочу использовать несколько разных изображений, которые включают в себя:</p><pre><code>uwsgi nginx postgres redis rabbitmq celery with cron </code></pre><p>посоветуйте, пожалуйста, как лучше настроить этот тип среды с помощью <em> docker </em>.</p><p>если это поможет, я на mac, поэтому использую <a href="https://github.com/boot2docker">boot2docker</a> .</p><p>некоторые проблемы у меня были:</p><ol> <li>docker compose не совместим с python3</li> <li>я хочу создать контейнер для своего проекта, поэтому, если один большой dockerfile не идеален, я чувствую, что мне нужно разбить его с помощью docker compose.</li> <li>я в порядке, чтобы сделать проект py2 & py3 совместимым, поэтому я склоняюсь к django-compose</li> </ol>

<p>ответ ни один.</p><p>docker compose (в данном документе называемый compose) будет использовать dockerfile, если вы добавите команду сборки в <code>docker-compose.yml</code> вашего проекта.</p><p>ваш рабочий процесс docker должен состоять в создании подходящего <code>dockerfile</code> для каждого изображения, которое вы хотите создать, а затем используйте compose для сборки изображений с помощью команды <code>build</code>.</p><p>вы можете указать путь к вашим отдельным файлам docker, используя <code>build /path/to/dockerfiles/blah</code>, где <code>/path/to/dockerfiles/blah</code> - это место, где живет бла <code>dockerfile</code>.</p>

<h1>dockerfile</h1><p> <a href="https://i.stack.imgur.com/jc2iw.jpg"><img src="https://i.stack.imgur.com/jc2iw.jpg" alt="enter image description here"></a> </p><p>dockerfile - это простой текстовый файл, содержащий команды, которые пользователь может вызвать для сборки изображения.</p><p>пример, <strong> dockerfile </strong></p><pre><code>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 </code></pre><hr><h1>docker compose</h1><p> <a href="https://i.stack.imgur.com/56atk.png"><img src="https://i.stack.imgur.com/56atk.png" alt="enter image description here"></a> </p><p><strong> docker compose </strong></p><ul> <li> <p>это инструмент для определения и запуска мультиконтейнерных приложений docker.</p> </li> <li> <p>определите службы, которые составляют ваше приложение, в <code>docker-compose.yml</code>, чтобы они могли работать вместе в изолированной среде.</p> </li> <li> <p>получить приложение, работающее в одной команде, просто запустив <code>docker-compose up</code></p> </li> </ul><p>пример, <strong> docker-compose.yml </strong></p><pre><code>version: '3' services: web: build: . ports: - "5000:5000" volumes: - .:/code - logvolume01:/var/log links: - redis redis: image: redis volumes: logvolume01: {} </code></pre>

<blockquote> <p>файл <strong> compose </strong> описывает <strong> контейнер в его рабочем состоянии </strong>, оставляя детали о том, как <strong> собрать контейнер </strong> в <strong> dockerfiles </strong>. <a href="http://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volumes">http://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volumes</a> </p> <p>когда вы определяете свое приложение <strong> с помощью compose </strong> в разработке, <strong> вы можете использовать это определение для запуска приложения в </strong> различные среды, такие как <strong> ci, постановка и производство </strong>. <a href="https://docs.docker.com/compose/production/">https://docs.docker.com/compose/production/</a> </p> </blockquote><p>также кажется, что compose считается <strong> безопасным с 1.11 </strong>, поскольку <a href="https://docs.docker.com/v1.11/compose/production/">https://docs.docker.com/v1.11/compose/production /</a> больше не имеет предупреждения не использовать его в производственной среде, как <a href="https://docs.docker.com/v1.10/compose/production/">https://docs.docker.com/v1.10/compose/production/</a> делает.</p>

<p>в своем рабочем процессе я добавляю dockerfile для каждой части моей системы и настраиваю его так, чтобы каждая часть могла запускаться отдельно. затем я добавляю docker-compose.yml, чтобы собрать их вместе и связать их.</p><p>самое большое преимущество (на мой взгляд): когда <a href="https://docs.docker.com/compose/compose-file/#/links">связывая контейнеры</a> , вы можете определить имя и пропинговать ваши контейнеры с этим именем. поэтому ваша база данных может быть доступна с именем <code>db</code> и больше не по ее ip.</p>

<p>docker-compose существует для того, чтобы вам приходилось писать кучу команд, которые вам бы пришлось делать с помощью docker-cli.</p><p>docker-compose также позволяет легко запускать несколько контейнеров одновременно и автоматически соединять их вместе с какой-либо формой сетевого взаимодействия.</p><p>цель docker-compose - функционировать как docker cli, но выполнять несколько команд гораздо быстрее.</p><p>чтобы использовать docker-compose, вам необходимо кодировать команды, которые вы выполняли ранее, в файл <code>docker-compose.yml</code>.</p><p>вы не просто скопируете, вставите их в файл yaml, есть специальный синтаксис.</p><p>после создания вы должны передать его в docker-compose cli, и у вас будет возможность проанализировать файл и создать все различные контейнеры с правильной конфигурацией, которую мы указали.</p><p>таким образом, у вас будут отдельные контейнеры, скажем, например, один - <code>redis-server</code>, а второй - <code>node-app</code>, и вы хотите, чтобы он был создан с использованием <code>dockerfile</code> в вашем текущем каталоге.</p><p>кроме того, после создания этого контейнера вы должны отобразить некоторый порт из контейнера на локальный компьютер, чтобы получить доступ ко всему, что работает внутри него.</p><p>итак, для вашего файла <code>docker-compose.yml</code> вы бы хотели начать первую строку следующим образом:</p><p><code>version: '3'</code></p><p>это говорит docker о версии <code>docker-compose</code>, которую вы хотите использовать. после этого вы должны добавить:</p><pre><code>version: '3' services: redis-server: image: 'redis' node-app: build: . </code></pre><p>пожалуйста, обратите внимание на отступ, очень важно. кроме того, обратите внимание, что для одного сервиса я получаю изображение, но для другого сервиса я говорю <code>docker-compose</code>, что нужно искать в текущем каталоге, чтобы создать образ, который будет использоваться для второго контейнера.</p><p>затем вы хотите указать все разные порты, которые вы хотите открыть в этом контейнере.</p><pre><code>version: '3' services: redis-server: image: 'redis' node-app: build: . ports: - </code></pre><p>обратите внимание на тире, тире в файле yaml - это то, как мы указываем массив. в этом примере я отображаю <code>8081</code> на моей локальной машине на <code>8081</code> на контейнере следующим образом:</p><pre><code>version: '3' services: redis-server: image: 'redis' node-app: build: . ports: - "8081:8081" </code></pre><p>таким образом, первый порт - это ваша локальная машина, а другой - порт в контейнере, вы также можете различать два, чтобы избежать путаницы, например:</p><pre><code>version: '3' services: redis-server: image: 'redis' node-app: build: . ports: - "4001:8081" </code></pre><p>разрабатывая подобный файл <code>docker-compose.yml</code>, он будет создавать эти контейнеры практически в одной и той же сети, и у них будет свободный доступ для общения друг с другом любым удобным для них способом и обмена таким количеством информации, как они захотят.</p><p>когда два контейнера создаются с использованием <code>docker-compose</code>, нам не нужны никакие объявления портов.</p><p>теперь в моем примере нам нужно выполнить настройку кода в приложении nodejs, которое выглядит примерно так:</p><pre><code>const express = require('express'); const redis = require('redis'); const app = express(); const client = redis.createclient({ host: 'redis-server' }); </code></pre><p>я использую этот пример выше, чтобы вы знали, что, возможно, вам придется выполнить какую-то конкретную настройку в дополнение к файлу <code>docker-compose.yml</code>, который может быть специфичен для вашего проекта.</p><p>теперь, если вы когда-нибудь обнаружите, что работаете с приложением nodejs и выполнили повтор, вы хотите убедиться, что знаете о порте по умолчанию, который использует nodejs, поэтому я добавлю это:</p><pre><code>const express = require('express'); const redis = require('redis'); const app = express(); const client = redis.createclient({ host: 'redis-server', port: 6379 }); </code></pre><p>итак, docker увидит, что приложение node ищет <code>redis-server</code>, и перенаправит это соединение в этот работающий контейнер.</p><p>все время <code>dockerfile</code> содержит только это:</p><pre><code>from node:alpine workdir '/app' copy /package.json ./ run npm install copy . . cmd ["npm", "start"] </code></pre><p>итак, если раньше вам нужно было запускать <code>docker run myimage</code> для создания экземпляра всех контейнеров или служб внутри файла, который вы можете вместо этого запустить, <code>docker-compose up</code>, и вам не нужно указывать изображение, потому что docker будет искать в текущем рабочем каталоге и искать для файла <code>docker-compose.yml</code> внутри там.</p><p>до <code>docker-compose.yml</code> нам приходилось иметь дело с двумя отдельными командами <code>docker build .</code> и <code>docker run myimage</code>, но в мире <code>docker-compose</code>, если вы хотите перестроить свои изображения, вы пишете <code>docker-compose up --build</code>. это говорит docker снова запускать контейнеры, но перестраивать его, чтобы получить последние изменения.</p><p>таким образом, <code>docker-compose</code> облегчает работу с несколькими контейнерами. в следующий раз, когда вам нужно запустить эту группу контейнеров в фоновом режиме, вы можете сделать <code>docker-compose up -d</code>, а чтобы остановить их, вы можете сделать <code>docker-compose down</code>.</p>

<p>"лучше" относительно. все зависит от ваших потребностей. docker compose предназначен для организации нескольких контейнеров. если эти образы уже существуют в реестре docker, то лучше перечислить их в файле композиции. если эти изображения или некоторые другие изображения должны быть собраны из файлов на вашем компьютере, вы можете описать процессы создания этих изображений в dockerfile.</p><blockquote> <p>я понимаю, что docker-файлы используются в docker compose, но я не уверен, является ли хорошей практикой помещать все в один большой dockerfile с несколькими командами from для разных образов?</p> </blockquote><p>использование нескольких from в одном файле docker не очень хорошая идея, потому что есть предложение удалить эту функцию. <a href="https://github.com/moby/moby/issues/13026">13026</a> </p><p>например, если вы хотите докеризировать приложение, которое использует базу данных и имеет файлы приложения на вашем компьютере, вы можете использовать файл компоновки вместе с файлом докера следующим образом</p><h2>докер-compose.yml</h2><pre><code>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 </code></pre><h2>dockerfile</h2><pre><code>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 </code></pre>

<p>dockerfiles предназначены для создания образа, например, из простой ubuntu, вы можете добавить <code>mysql</code> с именем <code>mysql</code> на одно изображение и <code>mywordpress</code> на второе изображение с именем <code>mywordpress</code>.</p><p>составьте файлы yaml, чтобы взять эти изображения и выполнить их связно. например, если в вашем файле <code>docker-compose.yml</code> есть сервисный вызов <code>db</code>:</p><pre><code>services: db: image: mysql --- image that you built. </code></pre><p>и сервис под названием worpress, такой как:</p><pre><code>wordpress: image: mywordpress </code></pre><p>затем внутри контейнера mywordpress вы можете использовать <code>db</code> для соединения с вашим контейнером mysql. эта магия возможна потому, что ваш докер-хост создает сетевой мост (сетевое наложение).</p>