Docker 和 asp.net core 使用 "scratch"图像最小化分布?

标签 docker asp.net-core docker-compose

Microsoft 关于通过 Docker 容器运行 asp.net 核心项目的指南提倡将我们的程序文件复制到 Dockerfile 中的 microsoft/aspnetcore 镜像。

我们正在使用图像保存和图像加载命令将我们的代码更改分发到测试服务器。

这意味着图像非常大且难以分发。

是否可以使用“scratch”镜像,将我们的文件复制到其中,然后通过 docker-compose 引入 microsoft/aspnetcore 镜像,然后使用“scratch”镜像构建我们的程序文件镜像?

通过这种方式,我们自己的代码图像很小,可以通过图像保存和图像加载命令轻松分发。

我试过了,但出现以下错误: “错误:对于 myapp 无法启动服务 myapp:OCI 运行时创建失败:container_linux.go:296:启动容器进程导致“exec:\“dotnet\”:在 $PATH 中找不到可执行文件“:未知”

撰写文件:

version: '2'

services:

  postgresserver:
     image: postgres:alpine
     restart: always
     ports:
       - 5432:5432
     environment:
         POSTGRES_PASSWORD: XXXX
     volumes:
       - /var/lib/myapp/db:/var/lib/postgresql/data
     networks:
       - myapp-network

  aspnetcoreruntime:
     image: microsoft/aspnetcore
     working_dir: /app    

  myapp:
     image: mycorp/myapp:v8.0.0-alpha.2
     restart: always
     ports:
       - 7575:7575
     volumes:
       - /var/lib:/var/lib
     environment:
        myapp_USE_URLS: http://*:7575
        myapp_DB_CONNECTION: User ID=postgres;Password=letmein;Host=postgresserver;Port=5432;Database=myapp;Pooling=true;  
        myapp_FOLDER_USER_FILES: /var/lib/myapp/files/user    
        myapp_FOLDER_BACKUP_FILES: /var/lib/myapp/files/backup
     build:
       context: ./myappdocker
       dockerfile: Dockerfile
     links:
       - postgresserver
     depends_on:
       - "postgresserver"
       - "aspnetcoreruntime"
     networks:
       - myapp-network

networks:
  myapp-network:
     driver: bridge

最佳答案

首先让我说我不建议尝试使用“scratch”。该图像现在可能有几百 MB,但这是有充分理由的:该图像包含所有 .NET Core 先决条件,默认启用一些网络设置以使部署更容易,并且包含 ASP.NET Core 运行时( 1) 使用名为 crossgen 的工具针对 Linux 进行了预优化,并且 (2) 定期使用安全补丁进行维护。

如果尺寸是您最关心的问题,请查看 https://github.com/aspnet/Universe/issues/833 .在 ASP.NET Core 2.1 中,应该有一个基于 Alpine Linux 的镜像,它将比当前的基础:Debian Linux 更小。


也就是说,这是您使用“scratch”作为基础所需要的。

  1. 准备您自己的基础 Docker 镜像

如果您想将其基于“scratch”,则需要确保您拥有所有 .NET Core 的 native 依赖项。参见 https://github.com/dotnet/core/blob/master/Documentation/prereqs.md .这包括 libcurl3libssllibuuid 等内容。

  1. 准备独立部署。

独立部署意味着 dotnet publish 的输出将包含运行您的应用程序所需的几乎所有文件。此输出将非常大,因为它包含构成 .NET Core 的所有 System.*.dll 文件的副本所有 Microsoft.AspNetCore.*.dll 文件。要准备独立的应用程序,您需要:

  • 在您的 .csproj 文件中设置 RuntimeIdentifier

    <PropertyGroup>
      <RuntimeIdentifier>linux-x64</RuntimeIdentifier>
    </PropertyGroup>
    
  • 执行dotnet publish --self-contained --output ./publish/--configuration Release

  • ./publish/ 复制到您的 Docker 镜像中
  • 使用独立部署时,它会生成一个 Linux 可执行文件供您启动您的应用。执行 ./publish/my-app 而不是 dotnet ./publish/my-app.dll

您还可以使用 dotnet publish --runtime linux-x64 将前 2 个步骤压缩为一个操作。有关详细信息,请参阅 https://learn.microsoft.com/en-us/dotnet/core/deploying/

  1. 设置 ASP.NET Core 以公开 0.0.0.0。默认情况下,ASP.NET Core 仅绑定(bind)到本地主机。在 Docker 中,这意味着您必须将其更改为绑定(bind)到 IPAny,以便从 Docker 容器外部访问 Web 服务器。您可以通过多种方式执行此操作,但最简单的是设置环境变量 ENV ASPNETCORE_URLS http://*:80

  2. (可选)最后,考虑使用名为“crossgen”的工具预先优化您的应用程序。对于大型应用程序,它可以将您的应用程序启动时间缩短 15-30 秒。 crossgen pre-JIT 您的 *.dll 程序集。参见 https://github.com/dotnet/coreclr/blob/v2.0.5/Documentation/building/crossgen.md了解更多详情。


这里还有一件事需要考虑。如果您在运行 .NET Core 的服务器上有多个应用程序,那么通过“从头开始”构建您自己的镜像,您将失去潜在的磁盘空间节省。如果您有两个或三个应用程序都使用 microsoft/aspnetcore 作为基础,Docker 只会保留一份 microsoft/aspnetcore。如果你从头开始构建这两个或三个应用程序,你最终会使用更多的磁盘空间,因为每个图像中的大部分内容都是重复的内容:ASP.NET Core 运行时。就运行 .NET Core 应用程序所需的文件大小而言,您的程序文件通常是较小的部分。

关于Docker 和 asp.net core 使用 "scratch"图像最小化分布?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49201329/

相关文章:

docker - Gitlab CI : docker not found

docker-compose up 容器开始排序

c# - Dotnet Core 2.2 - Azure AD 身份验证工作但角色库返回访问被拒绝

docker-compose - 如何将 env 变量从 .env 传递到 Dockerfile?

spring-boot - Elastic:如何在Elastic APM Agent/APM Server中启用对容器ID之类的元数据的自动检测?

docker - 从Google Container Registry删除图像并上传另一个具有相同标签的图像后,删除的图像仍会被拉出

docker - 在 Windows 容器中运行 erlang 时出错

asp.net-core - ASP.NET Core 图片上传和调整大小

c# - .AspNetCore.相关性。未找到国家属性(property)。未知位置

docker - 如何在 docker-compose.yml 上运行 docker exec