548

我一直在阅读和学习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. 我可以使项目 Py2 & Py3 兼容,所以我倾向于 django-compose
4

11 回答 11

725

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 应用程序的工具。

  • 定义构成您的应用程序的服务,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: {}
于 2017-08-07T14:28:16.763 回答
307

答案都不是。

如果您将构建命令添加到项目的docker-compose.yml.

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

build /path/to/dockerfiles/blah你可以使用where /path/to/dockerfiles/blahis where blah's live 来指定你的个人 Dockerfile 的路径Dockerfile

于 2015-04-07T08:28:57.843 回答
179

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'

这告诉 Dockerdocker-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

于 2018-12-21T14:37:54.107 回答
113

Docker compose file 是一种让您以声明方式编排多个容器启动的方式,而不是使用 bash 脚本单独运行每个 Dockerfile,这样编写速度会慢得多,调试起来也更困难。

于 2016-07-12T18:32:55.310 回答
54

Dockerfile 和 Docker Compose 是 Dockerland 中的两个不同概念。当我们谈论 Docker 时,首先想到的是编排、OS 级虚拟化、图像、容器等。我将尝试解释如下:

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

在此处输入图像描述

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

在此处输入图像描述

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

在此处输入图像描述

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

于 2019-09-04T08:49:31.093 回答
49

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

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

于 2016-08-29T08:49:06.050 回答
46

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

我知道 Dockerfiles 在 Docker Compose 中使用,但我不确定将所有内容放在一个大型 Dockerfile 中是否是一种好习惯,其中包含针对不同图像的多个 FROM 命令?

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

例如,如果您想对使用数据库的应用程序进行 docker 化,并将应用程序文件保存在您的计算机上,您可以将 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
于 2018-09-25T11:12:12.330 回答
20

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

可以将Dockerfile其视为一组说明,您将告诉系统管理员在这台全新的服务器上安装什么。例如:

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

相比之下,docker-compose.yml可以将其视为一组指令,告诉系统管理员服务器如何与世界其他地方交互。例如,

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

(这不是一个精确的解释,但足以开始。)

于 2019-07-04T08:52:32.280 回答
8

Dockerfiles 用于构建一个镜像,例如从一个裸骨 Ubuntu,你可以在一个镜像和第二个镜像上添加mysql调用.mySQLmywordpressmywordpress

撰写 YAML 文件将获取这些图像并内聚地运行它们。例如,如果您的docker-compose.yml文件中有一个名为的服务db

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

和一个名为 wordpress 的服务,例如:

wordpress: 
    image: mywordpress

然后在 mywordpress 容器中,您可以使用它db来连接到您的 mySQL 容器。这个魔法是可能的,因为你的 docker 主机创建了一个网桥(网络覆盖)。

于 2018-08-14T22:29:59.080 回答
4

在微服务世界(有一个共同的共享代码库)中,每个微服务都会有一个Dockerfile而在根级别(通常在所有微服务之外以及您的父 POM 所在的位置),您将定义一个docker-compose.yml将所有微服务分组为一个成熟的应用程序。

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

于 2020-02-07T14:20:46.263 回答
2

Dockerfile 是一个包含用于组装图像的文本命令的文件。

Docker compose 用于运行多容器环境。

在您的特定场景中,如果您提到的每种技术都有多个服务(服务 1 使用 reddis,服务 2 使用 rabbit mq 等),那么您可以为每个服务拥有一个 Dockerfile 和一个通用的 docker-compose.yml 来运行所有的“Dockerfile”作为容器。

如果您希望它们都在一个服务中,docker-compose 将是一个可行的选择。

于 2020-05-08T02:44:52.357 回答