docker-compose -f docker-compose.yml -f docker-compose-test.override.yml up -d
./run_unit_tests
docker-compose -f docker-compose.yml -f docker-compose-test.override.yml down
开发人员还可使用 Compose 部署到远程 Docker 引擎。 部署到单个 Docker 主机实例(例如配置了 Docker Machine 的生产 VM 或服务器)就是一个典型的例子。
如果正在使用任何其他业务流程协调程序(Azure Service Fabric、Kubernetes 等),则可能需要添加如 docker-compose.yml 中的设置和元数据配置设置,但需采用其他业务流程协调程序所需的格式。
在任何情况下,docker-compose 都是用于开发、测试和生产工作流的便捷工具和元数据格式,但生产工作流可能因使用的业务流程协调程序而异。
使用多个 docker-compose 文件来处理多个环境
针对不同环境时,应使用多个 compose 文件。 通过此方法可以根据环境创建多个配置变体。
重写基本 docker-compose 文件
开发人员可使用单个 docker-compose.yml 文件,如前面部分中的简化示例所示。 但是,对于大多数应用程序不建议这样做。
默认情况下,Compose 读取两个文件,docker-compose.yml 和可选的 docker-compose.override.yml 文件。 如图 6-11 所示,使用 Visual Studio 并启用 Docker 支持时,Visual Studio 还会创建另一个用于调试应用程序的 docker compose.vs.debug.g.yml 文件,可在主解决方案文件夹的 obj\Docker\ 文件夹中查看此文件。
图 6-11 。 Visual Studio 2019 中的 docker-compose 文件
docker-compose 项目文件结构:
.dockerignore - 用于忽略文件
docker-compose.yml - 用于撰写微服务
docker-compose.override.yml - 用于配置微服务环境
用户可使用任何编辑器(如 Visual Studio Code 或 Sublime)编辑 docker-compose 文件,并使用 docker-compose up 命令运行该应用程序。
按照约定,docker-compose.yml 文件包含基本配置和其他静态设置。 这意味着服务配置不应该根据所针对的部署环境而改变。
顾名思义,docker-compose.override.yml 文件包含替代基本配置的配置设置,例如依赖于部署环境的配置。 用户也可以拥有具有不同名称的多个重写文件。 重写文件通常包含应用程序所需的但特定于环境或部署的其他信息。
针对多个环境
典型的用例是定义多个 compose 文件时,可针对多个环境,如生产、暂存、CI 或开发环境。 为支持这些差异,可将 Compose 配置拆分成多个文件,如图 6-12 所示。
图 6-12 。 重写基本 docker-compose.yml 文件中的值的多个 docker-compose 文件
可组合多个 docker compose*.yml 文件来应对不同的环境。 从基本 docker-compose.yml 文件开始。 此基本文件包含的基本设置或静态配置设置不会因环境而更改。 例如,eShopOnContainers 应用将以下 docker-compose.yml 文件(使用少量服务以进行简化)作为基本文件。
#docker-compose.yml (Base)
version: '3.4'
services:
basket-api:
image: eshop/basket-api:${TAG:-latest}
build:
context: .
dockerfile: src/Services/Basket/Basket.API/Dockerfile
depends_on:
- basketdata
- identity-api
- rabbitmq
catalog-api:
image: eshop/catalog-api:${TAG:-latest}
build:
context: .
dockerfile: src/Services/Catalog/Catalog.API/Dockerfile
depends_on:
- sqldata
- rabbitmq
marketing-api:
image: eshop/marketing-api:${TAG:-latest}
build:
context: .
dockerfile: src/Services/Marketing/Marketing.API/Dockerfile
depends_on:
- sqldata
- nosqldata
- identity-api
- rabbitmq
webmvc:
image: eshop/webmvc:${TAG:-latest}
build:
context: .
dockerfile: src/Web/WebMVC/Dockerfile
depends_on:
- catalog-api
- ordering-api
- identity-api
- basket-api
- marketing-api
sqldata:
image: mcr.microsoft.com/mssql/server:2019-latest
nosqldata:
image: mongo
basketdata:
image: redis
rabbitmq:
image: rabbitmq:3-management
基本 docker-compose.yml 文件中的值不应因目标部署环境不同而不同。
例如,如果专注于 webmvc 服务定义,则可以看到无论目标环境如何,这些信息都相同。 会看到以下信息:
服务名称:webmvc。
容器的自定义映像:eshop/webmvc。
生成自定义 Docker 映像的命令,指示要使用的 Dockerfile。
其他服务依赖项,所以此容器在其他依赖项容器启动之前不会启动。
开发人员可进行其他配置,但重要的一点是,在基本 docker-compose.yml 文件中,只需设置各环境的共同信息。 然后,在 docker-compose.override.yml 或用于生产或暂存的类似文件中,应配置特定于每个环境的配置。
通常,docker-compose.override.yml 适用于开发环境,如 eShopOnContainers 中的以下示例所示:
#docker-compose.override.yml (Extended config for DEVELOPMENT env.)
version: '3.4'
services:
# Simplified number of services here:
basket-api:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=${ESHOP_AZURE_REDIS_BASKET_DB:-basketdata}
- identityUrl=http://identity-api
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
- EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
- AzureServiceBusEnabled=False
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE}
- UseLoadTest=${USE_LOADTEST:-False}
ports:
- "5103:80"
catalog-api:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sqldata;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=[PLACEHOLDER]}
- PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG_URL:-http://host.docker.internal:5202/api/v1/catalog/items/[0]/pic/}
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
- EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
- AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME}
- AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY}
- UseCustomizationData=True
- AzureServiceBusEnabled=False
- AzureStorageEnabled=False
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE}
ports:
- "5101:80"
marketing-api:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- ConnectionString=${ESHOP_AZURE_MARKETING_DB:-Server=sqldata;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=[PLACEHOLDER]}
- MongoConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosqldata}
- MongoDatabase=MarketingDb
- EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
- EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
- EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
- identityUrl=http://identity-api
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
- CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI}
- PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING_URL:-http://host.docker.internal:5110/api/v1/campaigns/[0]/pic/}
- AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME}
- AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY}
- AzureServiceBusEnabled=False
- AzureStorageEnabled=False
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE}
- UseLoadTest=${USE_LOADTEST:-False}
ports:
- "5110:80"
webmvc:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- PurchaseUrl=http://webshoppingapigw
- IdentityUrl=http://10.0.75.1:5105
- MarketingUrl=http://webmarketingapigw
- CatalogUrlHC=http://catalog-api/hc
- OrderingUrlHC=http://ordering-api/hc
- IdentityUrlHC=http://identity-api/hc
- BasketUrlHC=http://basket-api/hc
- MarketingUrlHC=http://marketing-api/hc
- PaymentUrlHC=http://payment-api/hc
- SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
- UseCustomizationData=True
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE}
- UseLoadTest=${USE_LOADTEST:-False}
ports:
- "5100:80"
sqldata:
environment:
- SA_PASSWORD=[PLACEHOLDER]
- ACCEPT_EULA=Y
ports:
- "5433:1433"
nosqldata:
ports:
- "27017:27017"
basketdata:
ports:
- "6379:6379"
rabbitmq:
ports:
- "15672:15672"
- "5672:5672"
在此示例中,开发替代配置向主机公开一些端口,使用重定向 URL 定义环境变量,并为开发环境指定连接字符串。 这些设置都只针对开发环境。
运行 docker-compose up
(或从 Visual Studio 启动它时)时,该命令会自动读取替代内容,就像它已合并这两个文件。
假设需要为生产环境使用具有不同配置值、端口或连接字符串的另一个 Compose 文件。 可创建另一个重写文件,如具有不同设置和环境变量的名为 docker-compose.prod.yml
的文件。 该文件可能存储在不同 Git 存储库中,或由其他团队管理和保护。
如何使用特定重写文件进行部署
若要使用多个重写文件或具有不同名称的重写文件,可通过 docker-compose 命令使用 -f 选项并指定文件。 按照合并文件在命令行上的指定顺序进行撰写。 以下示例演示如何使用重写文件进行部署。
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
在 docker-compose 文件中使用环境变量
如前面的示例所示,开发人员可方便地从环境变量中获取配置信息,尤其是在生产环境中。 可使用语法 ${MY_VAR} 在 docker-compose 文件中引用环境变量。 docker-compose.prod.yml 文件中的以下行显示如何引用环境变量的值。
IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105
创建和初始化环境变量的方式不同,具体取决于主机环境(Linux、Windows、云集群等)。 但是,便捷方法是使用 .env 文件。 docker-compose 文件支持在 .env 文件中声明默认环境变量。 这些环境变量的值是默认值。 但开发人员在每个环境(主机操作系统或群集中的环境变量)中定义的值可重写这些默认值。 将此 .env 文件放置在执行 docker-compose 命令的文件夹中。
以下示例展示了 .env 文件,例如用于 eShopOnContainers 应用程序的 .env 文件。
# .env file
ESHOP_EXTERNAL_DNS_NAME_OR_IP=host.docker.internal
ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.92
Docker-compose 要求 .env 文件中的每行都是 <variable>=<value> 格式。
运行时环境中设置的值始终会重写 .env 文件中定义的值。 同样,通过命令行参数传递的值也会重写 .env 文件中设置的默认值。
Docker Compose 概述
https://docs.docker.com/compose/overview/
多个 Compose 文件
https://docs.docker.com/compose/extends/#multiple-compose-files
生成优化的 ASP.NET Core Docker 映像
如果查看 Internet 上源代码的 Docker 和 .NET,则会发现 Dockerfiles 会将源代码复制到容器,以展现生成 Docker 映像的简单性。 这些示例表明,使用简单配置,即可拥有 Docker 映像,同时应用程序还会带有环境。 以下示例显示在此情况下的简单 Dockerfile。
FROM mcr.microsoft.com/dotnet/sdk:6.0
WORKDIR /app
ENV ASPNETCORE_URLS http://+:80
EXPOSE 80
COPY . .
RUN dotnet restore
ENTRYPOINT ["dotnet", "run"]
这样的 Dockerfile 为有效 Dockerfile。 但开发人员可以大幅优化映像,尤其是生产映像。
开发人员会在容器和微服务模型中不断启动容器。 使用容器时,通常不会重启睡眠容器,因为该容器为一次性容器。 业务流程协调程序(如 Kubernetes 和 Azure Service Fabric)创建映像的新实例。 这意味着,需要在生成应用程序时,通过预编译应用程序进行优化,这样可加快实例化过程。 当容器启动时,它应已准备好运行。 请勿在运行时使用 dotnet restore
和 dotnet build
CLI 命令进行还原和编译,如有关 .NET 和 Docker 的博客文章中所述。
.NET 团队一直致力于使 .NET 和 ASP.NET Core 成为容器优化的框架。 .NET 不仅是一个内存占用少的轻量级框架,该团队还从版本 2.1 开始,致力于针对三种主要方案优化 Docker 映像,并在 dotnet/ 的 Docker 中心注册表中发布这些映像:
开发:实现快速迭代和调试更改为优先事项,大小次之。
生成:编译应用程序是优先事项,此映像包括二进制文件和其他可优化二进制文件的依赖项。
生产:重点是实现快速部署和容器启动,所以这些映像仅限于二进制文件和运行应用程序所需的内容。
.NET 团队在 dotnet/(位于 Docker Hub)中提供了四个基本变体:
sdk:用于开发和生成方案
aspnet:用于 ASP.NET 生产方案
runtime:用于 .NET 生产方案
runtime-deps:用于自包含应用程序的生产方案
为了更快启动,运行时映像还会自动将 aspnetcore_urls 设置为端口 80,并使用 Ngen 创建程序集的本机映像缓存。
使用 ASP.NET Core 生成优化的 Docker 映像https://learn.microsoft.com/archive/blogs/stevelasker/building-optimized-docker-images-with-asp-net-core
为 .NET 应用程序生成 Docker 映像https://learn.microsoft.com/dotnet/core/docker/building-net-docker-images
上一页下一页