我一直在阅读和了解 Docker,并且正在尝试正确选择要使用的 Django 设置。到目前为止,有两种:
我了解 Dockerfiles 在 Docker Compose 中使用,但我不确定将所有内容放在一个大型 Dockerfile 中是否是一种好习惯,其中包含针对不同的多个 FROM
命令图片?
我想使用几个不同的图像,包括:
uwsgi
nginx
postgres
redis
rabbitmq
celery with cron
请告知使用 Docker 设置此类环境的最佳实践。
如果有帮助,我在 Mac 上,所以使用 boot2docker。
我遇到的一些问题:
Docker Compose 与 Python3 不兼容我想将我的项目容器化,所以如果一个大的 Dockerfile 不理想,那么我觉得我需要使用 Docker Compose 将它分解我可以使项目 Py2 和 Py3 兼容,所以我倾向于 django-compose
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: {}
答案都不是。
如果您将构建命令添加到项目的 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
还是仅在开发中使用?谢谢你的帮助。
docker-compose.yml
只使用公共图像(从互联网/docker hub 拉图像),那么不要'不需要 Dockerfile 来运行命令 docker-compose up
。
docker-compose
是您要用于管理单个 VM 上的多个容器的内容。如果您需要跨多个 VM 管理和联网容器,则需要 kubernetes 或 docker swarm 之类的东西。查看 docker 网站上的一些 common use-cases of docker-compose
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
。
docker-compose up
?换句话说,与 docker run xxx
相比,如果我使用 docker-compose up
有什么好处吗?
docker-compose
用于单个容器的好处
6379
是 Redis 的默认端口)。
Docker compose file 是一种让您以声明方式编排多个容器启动的方式,而不是使用 bash 脚本单独运行每个 Dockerfile,这样编写速度会慢得多,调试起来也更困难。
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
。
在我的工作流程中,我为系统的每个部分添加了一个 Dockerfile,并将其配置为每个部分都可以单独运行。然后我添加一个 docker-compose.yml 将它们组合在一起并链接它们。
最大的优势(在我看来):当 linking the containers 时,您可以定义一个名称并使用该名称 ping 您的容器。因此,您的数据库可能可以通过名称 db
访问,而不再通过其 IP 访问。
“更好”是相对的。这完全取决于您的需求。 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
想象一下,您是一家软件公司的经理,您刚刚购买了一台全新的服务器。只是硬件。
将 Dockerfile
视为一组说明,您可以告诉系统管理员在这个全新的服务器上安装什么。例如:
我们需要一个 Debian linux
添加 apache 网络服务器
我们也需要postgresql
安装午夜指挥官
完成后,将我们项目的所有*.php、*.jpg等文件复制到网络服务器的webroot(/var/www)
相比之下,将 docker-compose.yml
视为一组说明,您将告诉系统管理员服务器如何与世界其他地方交互。例如,
它可以从另一台计算机访问共享文件夹,
它的80端口与主机的8000端口相同,
等等。
(这不是一个精确的解释,但足以开始。)
Dockerfile 用于构建一个镜像,例如从一个裸骨 Ubuntu,您可以在一个镜像上添加名为 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 主机创建了一个网桥(网络覆盖)。
在微服务世界(具有公共共享代码库)中,每个微服务都有一个 Dockerfile
,而在根级别(通常在所有微服务之外以及您的父 POM 所在的位置)您将定义一个 docker-compose.yml
以将所有微服务分组到一个成熟的应用程序。
在您的情况下,“Docker Compose”优于“Dockerfile”。想想“应用程序”想想“撰写”。
Dockerfile 是一个包含用于组装图像的文本命令的文件。
Docker compose 用于运行多容器环境。
在您的特定场景中,如果您提到的每种技术都有多个服务(服务 1 使用 reddis,服务 2 使用 rabbit mq 等),那么您可以为每个服务拥有一个 Dockerfile 和一个通用的 docker-compose.yml 来运行所有的“Dockerfile”作为容器。
如果您希望它们都在一个服务中,docker-compose 将是一个可行的选择。
image: redis
,但它来自 dockerhub 吗?本地目录?等等......这让像我这样的新手很难理解到底发生了什么logvolume01
的声明 - 导致配置无效。如果您不熟悉服务定义之外的卷声明,请查看:docs.docker.com/compose/compose-file/…您可能希望回滚该编辑。