dockercompose和Dockerfile有什么区别

我一直在阅读和学习码头工人,并试图正确选择Django设置使用。到目前为止,有两种:

码头工人组成Dockerfile

我知道Dockerfiles码头工人组成中使用,但我不确定将所有内容放在一个大Dockerfile中,对不同的图像使用多个FROM命令是否是好的实践?

我想使用几个不同的图像,包括:

uwsgi
nginx
postgres
redis
rabbitmq
celery with cron

请建议使用码头工人设置这种类型的环境的最佳实践。

如果有帮助,我是在Mac上,所以使用boot2docker

我遇到的一些问题:

  1. Docker Compose与Python3不兼容
  2. 我想容器化我的项目,所以如果一个大Dockerfile 不是理想的,那么我觉得我需要使用Docker Compose
  3. 我可以做项目Py2 &Py3兼容,所以我倾向于django-compose
274136 次浏览

答案是两者都不是。

如果你将构建命令添加到项目的docker-compose.yml中,Docker Compose(这里称为Compose)将使用Dockerfile。

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

你可以使用build /path/to/dockerfiles/blah来指定你的dockerfile的路径,其中/path/to/dockerfiles/blah是blah的Dockerfile所在的位置。

Docker compose file是一种让你以声明的方式编排多个容器的启动的方式,而不是用bash脚本分别运行每个Dockerfile,后者编写起来要慢得多,而且很难调试。

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

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

Dockerfile

enter image description here

Dockerfile是一个简单的文本文件,其中包含用户可以调用来组装图像的命令。

例如,# EYZ0

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

码头工人组成

enter image description here

码头工人组成

  • >是一个用于定义和运行多容器Docker应用程序的工具。

  • docker-compose.yml中定义组成应用程序的服务,以便它们可以在隔离的环境中一起运行。

  • 获得一个应用程序运行在一个命令,只需运行docker-compose up

例如,# EYZ0

version: "3"
services:
web:
build: .
ports:
- '5000:5000'
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}

Dockerfiles是用来构建一个映像的,例如,你可以在一个映像上添加mysql,即mySQL,在另一个映像上添加mywordpress,即mywordpress

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

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

还有一个叫wordpress的服务,比如:

wordpress:
image: mywordpress

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

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

我知道Dockerfile在Docker Compose中使用,但我不确定将所有内容放在一个大Dockerfile中,对不同的图像使用多个FROM命令是否是个好做法?

在一个dockerfile中使用多个FROM并不是一个很好的主意,因为有人建议删除该功能。# EYZ0

例如,如果你想dockerize一个使用数据库的应用程序,并在你的计算机上有应用程序文件,你可以使用一个合成文件和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

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

假设你是一家软件公司的经理,刚刚买了一台全新的服务器。只有硬件。

Dockerfile看作是在这个全新的服务器上告诉系统管理员安装什么的一组指令。例如:

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

相比之下,可以将docker-compose.yml看作是一组指示,您将告诉系统管理员服务器如何交互以及其他内容。例如,

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

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

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

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

enter image description here

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

enter image description here

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

enter image description here

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

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

在你的例子中,“Docker Compose”优先于“Dockerfile”。想想“应用”,想想“撰写”。

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

Docker组合用于运行多容器环境。

在你的特定场景中,如果你为你提到的每一种技术都有多个服务(服务1使用reddis,服务2使用rabbit mq等),那么你可以为每个服务都有一个Dockerfile和一个公共的docker-compose。以容器的形式运行所有的Dockerfile。

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