it-swarm.asia

Docker Compose与Dockerfile - 哪个更好?

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

Docker ComposeDockerfile

我知道在Docker Compose中使用了Dockerfiles,但我不确定将所有内容放在一个大型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
260
Aaron Lelevier

答案都不是。

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

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

您可以使用build /path/to/dockerfiles/blah指定各个Dockerfiles的路径,其中/path/to/dockerfiles/blah是blah的Dockerfile所在的位置。

154
booyaa

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撰写

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

Compose文件描述了处于运行状态的容器,留下了如何构建容器Dockerfiles的详细信息。 http://deninet.com/blog/1587/docker-scratch-part-4-compose-and-volumes

当您在开发中定义应用使用Compose时,您可以使用此定义来运行您的应用程序不同的环境,例如CI,staging和productionhttps://docs.docker.com/compose/production/

似乎Compose被认为生产安全,从1.11开始,因为 https://docs.docker.com/v1.11/compose/production/ 不再有警告不要在生产中使用它,如 https://docs.docker.com/v1.10/compose/production/ does。

74
Peeter Kokk

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

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

37
n2o

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

我知道DockerFiles是在Docker Compose中使用的,但是我不确定将所有内容放在一个大型Dockerfile中,并为不同的图像添加多个FROM命令是不错的做法?

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

例如,如果要将使用数据库并在计算机上具有应用程序文件的应用程序停靠,则可以将compose文件与dockerfile一起使用,如下所示

泊坞窗,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
23
Akongnwi Devert

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创建。

此外,在创建该容器之后,您可以将一些端口从容器映射到本地计算机,以访问其中运行的所有内容。

所以对于你的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应用程序和redis,你想确保你知道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

18
Daniel

Dockerfiles用于构建图像,例如从裸骨Ubuntu构建图像,您可以在一个图像上添加mysqlname__,在mySQLname__上添加mywordpressname__,在另一个图像上添加mywordpressname__。

撰写YAML文件是为了获取这些图像并以内聚方式运行它们。例如,如果您的docker-compose.yml文件中有服务调用dbname__:

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

以及一项名为worpress的服务,例如:

wordpress: 
    image: mywordpress

然后在mywordpress容器中,您可以使用dbname__连接到mySQL容器。这种魔力是可能的,因为您的docker Host创建了一个网桥(网络覆盖)。

3
Hugo R