Docker Compose与Dockerfile - 哪个更好?

时间:2015-04-06 21:36:44

标签: docker docker-compose dockerfile development-environment boot2docker

我一直在阅读并了解Docker,并尝试正确选择要使用的Django设置。到目前为止,还有:

Docker ComposeDockerfile

我理解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. 来解决它
  4. 我可以将项目Py2& Py3兼容,所以我倾向于django-compose

10 个答案:

答案 0 :(得分:364)

Dockerfile

enter image description here

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

enter image description here

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: {}

答案 1 :(得分:158)

答案都不是。

如果您将build命令添加到项目的docker-compose.yml,Docker Compose(此处称为compose)将使用Dockerfile。

您的Docker工作流程应该是为您要创建的每个图像构建合适的Dockerfile,然后使用compose使用build命令组合图像。

您可以使用build /path/to/dockerfiles/blah指定单个Dockerfiles的路径,/path/to/dockerfiles/blah就是Dockerfile生活的地方。

答案 2 :(得分:76)

  

撰写文件描述   容器处于运行状态,留下如何构建的详细信息   容器 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/那样在生产中使用它。< / p>

答案 3 :(得分:38)

在我的工作流程中,我为系统的每个部分添加了一个Dockerfile,并将其配置为每个部分可以单独运行。然后我添加一个docker-compose.yml将它们组合在一起并链接它们。

最大优势(在我看来):当linking the containers时,您可以使用此名称定义名称并ping容器。因此,您的数据库可以使用名称db访问,而不能通过其IP访问。

答案 4 :(得分:23)

“更好”是相对的。这完全取决于您的需求。 Docker compose用于编排多个容器。如果这些图像已经存在于docker注册表中,那么最好将它们列出在compose文件中。如果必须从计算机上的文件中构建这些映像或其他映像,则可以描述在Dockerfile中构建这些映像的过程。

  

我了解Docker Compose中使用了Dockerfile,但是我不确定是否将所有内容放入一个大Dockerfile中,并使用多个FROM命令来处理不同的映像?

在单个dockerfile中使用多个FROM不是一个好主意,因为有人建议删除该功能。 13026

例如,如果您要对使用数据库的应用程序进行泊坞化并在计算机上拥有该应用程序文件,则可以按如下方式将compose文件和dockerfile一起使用

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

答案 5 :(得分:20)

docker-compose的存在使您不得不编写大量使用docker-cli所需的命令。

docker-compose还使您可以轻松地同时启动多个容器,并通过某种形式的网络将它们自动连接在一起。

docker-compose的目的是充当docker cli,但能够更快地发出多个命令。

要使用docker-compose,您需要将之前运行的命令编码为docker-compose.yml文件。

您不仅要将它们复制粘贴到yaml文件中,还有一种特殊的语法。

创建后,您必须将其喂入docker-compose cli,然后由cli来解析文件并使用我们指定的正确配置创建所有不同的容器。

因此,您将有单独的容器,例如,一个是redis-server,第二个是node-app,并且希望使用当前目录中的Dockerfile创建的容器。 / p>

另外,在制作完该容器之后,您需要将一些端口从该容器映射到本地计算机,以访问其中运行的所有内容。

因此,对于您的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的世界中,如果要重建图像,请编写{ {1}}。这就告诉Docker重新启动容器,但要对其进行重建以获取最新更改。

因此docker-compose up --build使处理多个容器变得更加容易。下次您需要在后台启动这组容器时,可以执行docker-compose,而要停止它们,可以执行docker-compose up -d

答案 6 :(得分:19)

Dockerfile和Docker Compose是Dockerland中的两个不同概念。当我们谈论Docker时,首先想到的是业务流程,操作系统级虚拟化,映像,容器等。我将尝试对它们进行如下解释:

图片: 映像是存储在受Docker信任的注册表中的一个不变的,可共享的文件。 Docker映像由一系列只读层构建而成。每层代表在映像的Dockerfile中给出的一条指令。图像包含运行所需的所有二进制文件。

enter image description here

容器: 图像的实例称为容器。容器只是要由主机OS运行的可执行映像二进制文件。正在运行的图像是一个容器。

enter image description here

Dockerfile: Dockerfile是一个文本文档,其中包含所有命令/构建指令,用户可以在命令行上调用以组装映像。这将另存为Dockerfile。 (请注意小写的“ f”。)

enter image description here

Docker-Compose: Compose是用于定义和运行多容器Docker应用程序的工具。通过Compose,您可以使用YAML文件来配置应用程序的服务(容器)。然后,使用一个命令,就可以从配置中创建并启动所有服务。 撰写文件将另存为docker-compose.yml

答案 7 :(得分:3)

Dockerfile用于从裸露的Ubuntu构建映像,您可以在一个映像上添加名为mysql的{​​{1}},在另一个名为mySQL的映像上添加mywordpress

组成YAML文件是要获取这些图像并连贯地运行它们。 例如,如果您的mywordpress文件中有一个服务电话docker-compose.yml

db

和称为worpress的服务,例如:

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

然后在mywordpress容器内,您可以使用wordpress: image: mywordpress 连接到mySQL容器。之所以如此,是因为您的Docker主机创建了一个网桥(网络覆盖)。

答案 8 :(得分:2)

想象一下,您是一家软件公司的经理,而您刚购买了一台全新的服务器。只是硬件。

Dockerfile作为一组说明,您将告诉系统管理员该新服务器上的安装内容。例如:

  • 我们需要一个Debian linux
  • 添加apache网络服务器
  • 我们也需要postgresql
  • 安装午夜指挥官
  • 完成后,将我们项目的所有* .php,*。jpg等文件复制到网络服务器的网络根目录(/var/www

通过对比,将docker-compose.yml视为一组说明,您可以告诉系统管理员服务器如何与世界其他地区进行交互。例如,

  • 它可以从另一台计算机访问共享文件夹
  • 它的端口80与主机的端口8000相同,
  • 等等。

(这不是一个精确的解释,但足以说明问题。)

答案 9 :(得分:0)

在微服务世界(具有通用的共享代码库)中,每个微服务都会有一个Dockerfile,而在根级别(通常在所有微服务之外以及您的父POM所在的地方),您将定义一个{{1} },将所有微服务分组为功能完善的应用。

在您的情况下,“ Docker Compose”优先于“ Dockerfile”。考虑“应用程序”考虑“撰写”。