ChatGPT解决这个技术问题 Extra ChatGPT

Docker Compose 与 Dockerfile 有什么区别

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

Docker ComposeDockerfile

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

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

uwsgi
nginx
postgres
redis
rabbitmq
celery with cron

请告知使用 Docker 设置此类环境的最佳实践。

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

我遇到的一些问题:

Docker Compose 与 Python3 不兼容我想将我的项目容器化,所以如果一个大的 Dockerfile 不理想,那么我觉得我需要使用 Docker Compose 将它分解我可以使项目 Py2 和 Py3 兼容,所以我倾向于 django-compose

最好将此事表述为“我应该将我的应用程序作为单个容器还是多个容器运行?”看起来这取决于并且应该考虑扩展和关注点分离(每个服务一个容器)的问题。这些可能会有所帮助:stackoverflow.com/questions/30534939/…quora.com/…
官方 Docker "Getting Started" docs
运行 ''' apt install python3 pip3 && pip3 uninstall docker-compose && pip3 install docker-compose 安装docker-compose,这样安装没有常见问题
我只想指出,对于一个显然“离题”的人来说,这是一个非常有用的问题。

P
Pang

Dockerfile

https://i.stack.imgur.com/jc2IW.jpg

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

码头工人撰写

https://i.stack.imgur.com/56AtK.png

码头工人撰写

是一个用于定义和运行多容器 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: {}

@sg 的答案是,由于对 Docker 与 Docker Compose 缺乏了解,这个问题是不正确的。简洁地解释两者如何相互作用可能是我能想到的最佳答案。
我看到网络上最近发布的工具/解决方案/框架中缺少这种文档。我想如果您自己已经知道/发明了解决方案,很难理解为什么有人需要它。
这个答案缺少的是有关撰写的更多信息。撰写脚本是否调用 dockerfile?它怎么知道要作什么?该示例显示 image: redis,但它来自 dockerhub 吗?本地目录?等等......这让像我这样的新手很难理解到底发生了什么
此响应坚持 docker compose 的多容器用途,但即使只有一个容器,您可能还想使用 docker compose 的许多其他场景,例如指定您希望容器运行的端口(在 dockerfile afaik 中不可能)。
@omidrezabagheri 您的编辑在 redis 服务中移动了 logvolume01 的声明 - 导致配置无效。如果您不熟悉服务定义之外的卷声明,请查看:docs.docker.com/compose/compose-file/…您可能希望回滚该编辑。
b
booyaa

答案都不是。

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

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

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


您在生产中使用 docker-compose 还是仅在开发中使用?谢谢你的帮助。
@booyaa 你能详细说明一下吗?
感谢你的回答! Dockerfile 为图像指定配置,并且 docker-compose.yml 将图像组装在一起。我想指出的一件事是,如果 docker-compose.yml 只使用公共图像(从互联网/docker hub 拉图像),那么不要'不需要 Dockerfile 来运行命令 docker-compose up
我认为值得强调的一个问题,尤其是在回答“为生产或开发而作曲?”的问题时。 (回答 IMO:取决于用例,但通常是开发人员)。 docker-compose 是您要用于管理单个 VM 上的多个容器的内容。如果您需要跨多个 VM 管理和联网容器,则需要 kubernetes 或 docker swarm 之类的东西。查看 docker 网站上的一些 common use-cases of docker-compose
P
Pang

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


@Chris 这几乎与接受的答案之间有 3 年的知识价值。
如果在我的情况下只有一项服务,我想知道我是否有充分的理由使用 docker-compose up?换句话说,与 docker run xxx 相比,如果我使用 docker-compose up 有什么好处吗?
@atline 请参阅 Pansoul 对 stackoverflow.com/a/45549372/3366962 的回复,了解将 docker-compose 用于单个容器的好处
@PaulRazvanBerg 您的“或”部分是正确的(并且 6379 是 Redis 的默认端口)。
docker-compose.yml 的示例帮助我回答了一些关于 docker-compose 的问题。接受的答案没有用,尤其是对于 docker 新手。
P
Peeter Kokk

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


感谢您提出这个问题。您能否添加更多在 1.11 中为生产安全而修复的内容?
B
BBaysinger

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

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

https://i.stack.imgur.com/CeFrU.jpg

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

https://i.stack.imgur.com/5Fkn0.jpg

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

https://i.stack.imgur.com/gHkPA.jpg

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


n
n2o

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

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


您能否详细说明按名称访问数据库?
在哪一部分?在 docker-compose 中它是微不足道的,因为这是定义服务时为其命名并使其无需配置即可访问的常规方式。在我们的 CI 中,我正在创建一个网络,在该网络中创建容器并为它们命名。然后,您也可以通过容器内的名称访问它们(而不是来自主机)
我的意思是作曲家。所以我在作曲家中链接图像,在我的应用程序配置而不是 IP 中,我以我在作曲家文件中给出的任何名称来定位 MySQL?
这是正确的。您甚至不必指定链接。如果没有以不同方式指定网络,则默认情况下它们是链接的。 In this example 服务“web”可以通过名称“redis” ping 主机“redis”
P
Pang

“更好”是相对的。这完全取决于您的需求。 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

C
Csongor Halmai

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

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

我们需要一个 Debian linux

添加 apache 网络服务器

我们也需要postgresql

安装午夜指挥官

完成后,将我们项目的所有*.php、*.jpg等文件复制到网络服务器的webroot(/var/www)

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

它可以从另一台计算机访问共享文件夹,

它的80端口与主机的8000端口相同,

等等。

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


P
Pang

Dockerfile 用于构建一个镜像,例如从一个裸骨 Ubuntu,您可以在一个镜像上添加名为 mySQLmysql,在另一个名为 mywordpress 的镜像上添加 mywordpress

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

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

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

wordpress: 
    image: mywordpress

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


K
KrishPrabakar

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

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


M
Mudassir Shahzad

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

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

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

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