基于eShopOnContainers学习ASP.NET Core之使用 docker-compose.yml 定义多容器应用程序

前言

docker相关知识和docker-compose相关知识就不再本文说明了。

本文主要参考

官方示例使用 docker-compose.yml 定义多容器应用程序

使用 ASP.NET Core 构建优化的 Docker 镜像

环境准备

添加docker支持和容器业务流程协调程序支持即docker-compose

image

image

然后就会出现image

如果出现如下错误

Unable to load schema from 'https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json': getaddrinfo ENOENT raw.githubusercontent.com.(768)

则参考https://www.jianshu.com/p/d273d9a35b11解决

简单的Web服务API容器

关注单个容器的 SystemInfo.Api定义如下

systeminfo.api:
    image: zhao56/systeminfoapi
    environment:
      - ConnectionString=server=localhost;user=root;password=[PLACEHOLDER];database=zhao56
    expose:
    	-80
    ports:
      - "5101:80"
	depends_on:
      - sqldata

特点:

  • 基于自定义镜像,这就意味着必须提前生成zhao56/systeminfoapi这个镜像
  • 定义了 ConnectionString环境变量,会覆盖对应微服务中的appsettings.json中的ConnectionString
  • 依赖于数据库容器sqldata,使用的名称。无需知道数据库容器内部的ip

使用多个 docker-compose 文件

针对不同的环境是应该使用多个docker-compose文件

重写docker-compose文件来处理多个环境

Visual Studio创建docker支持的时候会创建三个文件

image

  • .dockerignore - 用于忽略文件
  • docker-compose.yml - 用于撰写微服务
  • docker-compose.override.yml - 用于配置微服务环境

通常:

docker-compose.yml 中包含基本配置和其他静态设置 ,即不会随着环境的改变而变化

docker-compose.override.yml中包含可替代基本配置的配置,用来应对各个环境的不同,也可以创建不同名称的重写文件

针对多个环境

典型的用例是定义多个 compose 文件时,可针对多个环境,如生产、暂存、CI 或开发环境。 为支持这些差异,可将 Compose 配置拆分成多个文件,如图 6-12 所示。

三个 docker-compose 文件设置为替代基文件的关系图。

先定义基本不变的docker-compose.yml文件

version: '3.4'

services:
  systeminfo.api:
    image: zhao56/systeminfoapi:${TAG:-latest}
    build:
      context: .
      dockerfile: SystemInfo.Api/Dockerfile
    depends_on:
      - sqldata
  sqldata:
    image: mysql:8.0.25

其次是docker-compose.override.yml文件来应对环境的不同

version: '3.4'

services:
  systeminfo.api:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=https://+:443;http://+:80
    ports:
      - "80"
      - "443"
    volumes:
      - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
      - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
  sqldata:
    environment:
      - SA_PASSWORD=[PLACEHOLDER]
      - ACCEPT_EULA=Y
    ports:
      - "5433:1433"

当执行docker-compose up或者从 Visual Studio 启动时,会将两个文件合并

如何使用特定重写文件进行部署

如果需要为生产环境配置具有不同端口、配置值或者连接串的另外一个compose文件,如创建docker-compose.prod.yml可执行如下命令

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

在 docker-compose 文件中使用环境变量

用.env文件定义主机环境,环境不同修改对应的值即可格式为: ${MY_VAR}

如在 docker-compose.override.yml中定义连接字符串的环境变量

systeminfo.api:
    environment:
      - ConnectionString=${SYSTEMINFO_DB}

环境变量中修改添加值

SYSTEMINFO_DB=server=localhost;user=root;password=root;database=zhao56

生成优化的DockerFile

编写常规的DcokerFile可能如下所示

FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build
WORKDIR /src
COPY ["SystemInfo.Api/SystemInfo.Api.csproj", "SystemInfo.Api/"]
COPY ["SystemInfo.Service/SystemInfo.Service.csproj", "SystemInfo.Service/"]
COPY ["SystemInfo.Repositories/SystemInfo.Repositories.csproj", "SystemInfo.Repositories/"]
COPY ["SystemInfo.Entities/SystemInfo.Entities.csproj", "SystemInfo.Entities/"]
COPY ["SystemInfo.Core/SystemInfo.Core.csproj", "SystemInfo.Core/"]
COPY ["Services.Common/Services.Common.csproj", "Services.Common/"]
RUN dotnet restore "SystemInfo.Api/SystemInfo.Api.csproj"
COPY . .
WORKDIR "/src/SystemInfo.Api"
RUN dotnet build "SystemInfo.Api.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "SystemInfo.Api.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "SystemInfo.Api.dll"]

此种情况下所有的步骤都放到了同一个镜像中,镜像也包含了源代码,虽然简单,但是仍可以优化,以便重新发布的时候达到最少的停机时间

动态编译

日常部署的过程中不会每次都将程序全部替换,而是采用增量发布的方式来进行的。

容器是不可变的,预先优化

在使用容器的场景中,不会关闭容器或休眠容器,而是Kill掉容器,所以就重新发布时,镜像就准备好了,这样会节省很多时间,即当需要重新发布容器时,程序已经预先编译好了

所以当前存在几个基本镜像:

  • sdk:用于开发和生成方案
  • aspnet:用于 ASP.NET 生产方案( 部署ASP.NET Core应用程序 )
  • runtime:用于 .NET 生产方案( 部署.NET Core控制台程序 )
  • runtime-deps:用于 自包含应用程序的生产方案

创建一个 build.sh 脚本

 #!bin/bash
dotnet restore
#如果有测试需要执行
#dotnet test xxxx
#删除发布文件夹
rm -rf $(pwd)/app/publish/API/SystemInfo
dotnet publish "SystemInfo.Api.csproj" -c Release -o $(pwd)/app/publish/API/SystemInfo

使用构建脚本编译和发布项目

进入到解决方案根目录

运行命令(容器用完即删)

docker run -it --rm -v "$PWD/\:/src" --workdir /sln/sln/src/Services/SystemInfo/SystemInfo.Api mcr.microsoft.com/dotnet/sdk:5.0 sh ./build.sh

或者可以使用docker-compose来封装我们的构建脚本

添加docker-compose-build.yml添加如下内容

version: '3.4'

services:
  SystemInfo-build:
    image: mcr.microsoft.com/dotnet/sdk:5.0-buster-slim
    volumes:
      - /usr/local/test/zhao56.microservices.demo/:/sln
    working_dir: /sln/src/Services/SystemInfo/SystemInfo.Api
    entrypoint: ["sh", "./build.sh"]

运行来构建

docker-compose -f docker-compose-build.yml up

构建结果如下

[root@manager zhao56.microservices.demo]# docker-compose -f docker-compose-build.yml up
WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use `docker stack deploy`.

Recreating zhao56microservicesdemo_SystemInfo-build_1 ... done
Attaching to zhao56microservicesdemo_SystemInfo-build_1
SystemInfo-build_1  | ./build.sh: 1: ./build.sh: : not found
SystemInfo-build_1  | Could not execute because the specified command or file was not found.
SystemInfo-build_1  | Possible reasons for this include:
SystemInfo-build_1  |   * You misspelled a built-in dotnet command.
 does not exist._1  |   * You intended to execute a .NET program, but dotnet-restore
SystemInfo-build_1  |   * You intended to run a global tool, but a dotnet-prefixed executable with this name could not be found on the PATH.
SystemInfo-build_1  | Microsoft (R) Build Engine version 16.10.2+857e5a733 for .NET
SystemInfo-build_1  | Copyright (C) Microsoft Corporation. All rights reserved.
SystemInfo-build_1  | 
SystemInfo-build_1  |   Determining projects to restore...
SystemInfo-build_1  |   Restored /sln/src/Services/SystemInfo/SystemInfo.Service/SystemInfo.Service.csproj (in 9.39 sec).
SystemInfo-build_1  |   Restored /sln/src/Services/SystemInfo/SystemInfo.Repositories/SystemInfo.Repositories.csproj (in 14 ms).
SystemInfo-build_1  |   Restored /sln/src/Services/SystemInfo/SystemInfo.Entities/SystemInfo.Entities.csproj (in 8 ms).
SystemInfo-build_1  |   Restored /sln/src/Services/SystemInfo/SystemInfo.Core/SystemInfo.Core.csproj (in 1.87 sec).
SystemInfo-build_1  |   Restored /sln/src/Services/SystemInfo/SystemInfo.Api/SystemInfo.Api.csproj (in 39.84 sec).
SystemInfo-build_1  |   Restored /sln/src/Services/CommonSupport/Services.Common/Services.Common.csproj (in 2 ms).
SystemInfo-build_1  |   Services.Common -> /sln/src/Services/CommonSupport/Services.Common/bin/Release/net5.0/Services.Common.dll
SystemInfo-build_1  |   SystemInfo.Entities -> /sln/src/Services/SystemInfo/SystemInfo.Entities/bin/Release/net5.0/SystemInfo.Entities.dll
SystemInfo-build_1  |   SystemInfo.Core -> /sln/src/Services/SystemInfo/SystemInfo.Core/bin/Release/net5.0/SystemInfo.Core.dll
SystemInfo-build_1  | /usr/share/dotnet/sdk/5.0.302/Microsoft.Common.CurrentVersion.targets(2202,5): warning 
SystemInfo-build_1  |   SystemInfo.Api -> /sln/src/Services/SystemInfo/SystemInfo.Api/app/publish/API/SystemInfo/
zhao56microservicesdemo_SystemInfo-build_1 exited with code 0

查看挂载目录

[root@manager SystemInfo]# ll
总用量 10304
-rw-r--r--. 1 root root     168 8月   5 14:26 appsettings.Development.json
-rw-r--r--. 1 root root    1318 8月   5 14:26 appsettings.json
-rw-r--r--. 1 root root     291 8月   5 14:26 Dockerfile
...........省略........
[root@manager SystemInfo]# pwd
/usr/local/test/zhao56.microservices.demo/src/Services/SystemInfo/SystemInfo.Api/app/publish/API/SystemInfo

成功编译

构建优化图像

将项目中的DockerFile改为

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

COPY . .
ENTRYPOINT ["dotnet", "SystemInfo.Api.dll"]

总结

1.使用docker-compose.yml定义基本的信息,不会随环境改变的信息

2.使用docker-compose.*.yml配置主机环境相关的信息

3.使用构建脚本编译和发布项目,最后将发布后的程序添加到对应的生产镜像中

posted @ 2021-08-04 16:05  zhao56  阅读(294)  评论(0编辑  收藏  举报