Back to "从基础到高级的“.”NET集装箱化"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

.NET Containers DevOps Docker

从基础到高级的“.”NET集装箱化

Sunday, 09 November 2025

一. 导言导言 导言 导言 导言

Docker从根本上改变了我们如何构建“, ship @, ” 和运行应用程序“MS K2 启动的简单集装箱化工具已经演变成一个完整的生态系统,用于现代应用开发和部署@.

这是我Docker系列中的第四篇也是最全面的文章, 用于“ .@NET developments @ MS K1 ” 如果您是新加入 Dokker@,} 您可能要以“ MPK4}” 开始

  1. docker 合成器 @- 以基本的多功能-acontainer 设置@( 7月 @MSC3
  2. Docker 混音器的开发依赖 建立本地环境 @(August#2024)
  3. 与 Docker 共享图像 解决批量许可问题

在此深度潜水中,我们“'”将利用这些基础探索“MS K2”

  • 制作@- ready docker 作曲@: 运行此博客的实际堆疊
  • 以有限的资源为主用于 VPS预算部署的实用优化技术
  • GPU 支持“: ”集装箱的ML工作量
  • MUY - - 建筑构造支持ARM64和AMDMS K2
  • “.NET ”“9集装箱特性”。@ : 内建- 在没有 Docker 文件的容器发布中
  • .NET 预报员现代的集装箱管弦法

这也是我和A. /的实验的一部分, 这是用来花费"$1000 -Claude Countweb credit MS K3\ I'\ 已经向这个网站提供了一张纸上的BUNCH+,\ 我的理解是\ ,\ 问题我不得不生成这篇文章\ I.\ It''}它很有趣并填补了一个空白

您是否正在使用简单的网络应用程序, 或者用 GPU @ - @ acered machine 学习模型来设计复杂的微服务架构@ MS K2 @ 本指南将您从 Docker 基础到 production\ - @ ready confrontized applications {-} 和运行多为lucid=.net}. 的真实实例带给您

Docker 基本知识@: 了解容器

什么是Docker, ? 真的\ ?

Docker 是一个集装箱化平台,将您的应用程序及其所有附属点包装成一个称为容器的标准化单位。 “.”与虚拟机器不同,虚拟机器使整个操作系统虚拟化。“,”集装箱共享主机OS内核,同时保持孤立用户空间@.

以这种方式想一想

  • 虚拟机“: ” 每个VM 都运行一个完整的OS堆叠“ @(\Linux cernel@, ” 系统库“,” 等“MS K4 {-} 重而缓慢的启动
  • 容器集装箱: 分享主机核心@, 套件, 只使用应用程序代码和依赖关系 @-轻量级且快速

为何集装箱对开发者至关重要

# The classic developer problem
"It works on my machine!" 

# The container solution
"Ship your machine!" 

集装箱解决了几个关键问题

  1. 环境一致性:Disvelopment,测试,和生产环境完全相同
  2. 依赖性隔离@ : @ no more @ MPK1 @ DLL Hell@ MS K2 @ 或矛盾的图书馆版本
  3. 可复制构建@ :} 相同的输入 *\ MS K1} 同样的输出 * * , * 每次都一样
  4. 快速部署@: 启动容器在秒@,}没有时间
  5. 资源使用效率“: 运行几十个集装箱 在单个宿主上”

基本嵌入概念

图像与容器

# An image is a template (like a class in OOP)
docker pull mcr.microsoft.com/dotnet/aspnet:9.0

# A container is a running instance (like an object)
docker run -d -p 8080:8080 myapp:latest

图像图像 是不可更改的 @ , 层文件系统@ MS K1} 在 dockerfile 中的每一指令都创建了新层@ MPK2

FROM mcr.microsoft.com/dotnet/aspnet:9.0      # Layer 1: Base OS + .NET runtime
WORKDIR /app                                   # Layer 2: Directory structure
COPY *.dll ./                                  # Layer 3: Application files
ENTRYPOINT ["dotnet", "MyApp.dll"]            # Layer 4: Startup command

这种分层功能非常强大 @ : @

  • 缓缓“: ”未改变的层被重新利用,“, ” 加速建设。
  • 共享分享MPK0 多图像可以共享基底层
  • 效率效率\ : 只需要下载已修改的层@ MS K1 pload

理解 Dockerfile 执行@ : @ 不是您的机器@ MPK1 @

Docker 初学者常见的混乱根源 @: @% Dockerfile 中的命令在您的机器上运行@' @t 在建筑容器内运行 @-}=%s OSQ.}

这里: '}实际发生的一切 @:

Your Machine (Windows/Mac/Linux)
    ↓ (reads Dockerfile)
Build Image (usually Linux)
    ↓ (executes RUN commands here)
Output Image (contains results)

为什么这重要?

# You're on Windows, writing this Dockerfile
FROM ubuntu:24.04

# This RUN command executes in Ubuntu, NOT on your Windows machine!
RUN apt-get update && apt-get install -y curl

# This copies FROM your Windows filesystem
COPY myapp.exe /app/

# This executes IN the Ubuntu container
RUN chmod +x /app/myapp.exe

密钥洞见@: @%

  1. 本地文件系统# :你的# COPY 和 ADD 从您的机器读取命令
  2. 构建图像# :你的# RUN 在容器中执行的命令 @'%s OS *(%not your machine@)
  3. 输出图像: 最终图像包含在构建中创建的所有层
  4. cross - 平台: 您可以使用 Linux 命令在 Windows @ MS K1上建立 Linus 图像@,

这就是为什么你可以写作 apt-get 在 Windows 的 docker file 中, 以 Linux - 为基础的建筑容器\ MS K5 内运行Name

实例混杂情景

FROM mcr.microsoft.com/dotnet/sdk:9.0  # This is Linux-based

# You might think: "But I'm on Windows, how can I use these Linux commands?"
RUN apt-get update  # ← Executes in the Linux build container, not your Windows machine
RUN dotnet restore  # ← Executes in the Linux build container

Docker 守护进程会处理您本地文件系统与容器化构建环境之间的翻译@.

Dockerfile 最佳做法

@ ' @ a production@ MS K1 ready @ I._ NET Dockerfiles 带有批注@ MPK3}

# Multi-stage build: separates build environment from runtime
# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src

# Copy only csproj files first (better layer caching)
COPY ["MyApp/MyApp.csproj", "MyApp/"]
COPY ["MyApp.Core/MyApp.Core.csproj", "MyApp.Core/"]

# Restore dependencies (cached unless csproj changes)
RUN dotnet restore "MyApp/MyApp.csproj"

# Copy everything else
COPY . .

# Build the application
WORKDIR "/src/MyApp"
RUN dotnet build "MyApp.csproj" -c Release -o /app/build

# Stage 2: Publish
FROM build AS publish
RUN dotnet publish "MyApp.csproj" -c Release -o /app/publish /p:UseAppHost=false

# Stage 3: Final runtime image
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS final
WORKDIR /app

# Create non-root user for security
RUN addgroup --gid 1001 appuser && \
    adduser --uid 1001 --gid 1001 --disabled-password --gecos "" appuser

# Copy published output from publish stage
COPY --from=publish /app/publish .

# Switch to non-root user
USER appuser

# Expose port (documentation only, doesn't actually publish)
EXPOSE 8080

# Set environment variables
ENV ASPNETCORE_URLS=http://+:8080
ENV ASPNETCORE_ENVIRONMENT=Production

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8080/health || exit 1

ENTRYPOINT ["dotnet", "MyApp.dll"]

理解建设流程

这里“ '” 表示在多@ MS K1+Sage Docker 构建 “ -+” 文件的来源和结局中发生的事情 *\ :+}

graph TB
    subgraph "Your Machine"
        A[Source Code<br/>*.cs, *.csproj]
        B[Frontend Assets<br/>*.js, *.css]
        C[Configuration<br/>appsettings.json]
        D[Static Files<br/>wwwroot/]
    end

    subgraph "Stage 1: Build Container (SDK Image)"
        E[dotnet/sdk:9.0<br/>~1.5GB]
        F[Copy .csproj files]
        G[dotnet restore<br/>Download NuGet packages]
        H[Copy source code]
        I[dotnet build<br/>Compile to DLLs]
        J[Build artifacts<br/>/app/build/]
    end

    subgraph "Stage 2: Publish Container"
        K[dotnet publish<br/>Optimize & trim]
        L[Published output<br/>/app/publish/]
    end

    subgraph "Stage 3: Final Runtime Container (ASPNET Image)"
        M[dotnet/aspnet:9.0<br/>~220MB]
        N[Create app user<br/>Security]
        O[Copy published files<br/>ONLY production artifacts]
        P[Final image<br/>~250MB total]
    end

    subgraph "Frontend Build Pipeline (Parallel)"
        Q[npm install<br/>node_modules/]
        R[Webpack bundling<br/>*.js → dist/]
        S[TailwindCSS + PostCSS<br/>*.css → dist/]
        T[Optimized assets<br/>wwwroot/js/dist/<br/>wwwroot/css/dist/]
    end

    A --> F
    A --> H
    F --> G
    G --> H
    H --> I
    I --> J
    J --> K
    K --> L

    B --> Q
    Q --> R
    Q --> S
    R --> T
    S --> T

    L --> O
    T --> O
    C --> O
    D --> O

    M --> N
    N --> O
    O --> P

此流程中的关键洞察@ : @

  1. SDK 图像丢弃@ :_ {1.5} GBSDK 容器在发布 < \ / > * \ @ MPK2 _\ > 只公布\ MS K3 ZMB 的编译输出后被丢弃 premove
  2. 层层缓存: 复制 .csproj 在源代码之前, 源码意味着依赖性恢复被缓存, 除非依赖性改变
  3. 前期资产@ : 单独建造@(}经常通过 npm run build) 并复制到最终图像中
  4. 配置文件: appsettings.json 和 wwwroot/ 从您的机器复制的内容@, @% 未建立
  5. 最终图像@: 起始于最短运行时间的图像@(~220MB) @ +你的应用程序 @MS K4MTMQ}{)}#+资产 *(~5MT)Z=~255
  6. 仅生产文件:源碼, obj/, binMS K3 節點_MTULESMSQK5 永遠不會到最後的影像

关键原则说明 :

  1. 多 MUSK0 阶段建设@ : @ 分开建筑@ MS K1 @ 出版阶段大大缩小最终图像大小
  2. 图层优化: 在源代码前复制依附文件, 以更好地缓存
  3. 安全安保安全: 运行为非{-}\ root user
  4. 健康检查集装箱管弦手可以监控应用健康
  5. 明确环境: 设定生产默认值

建筑和运行

# Build the image
docker build -t myapp:1.0.0 -t myapp:latest .

# Run with common options
docker run -d \
  --name myapp \
  -p 8080:8080 \
  -e ConnectionStrings__DefaultConnection="Server=db;Database=myapp" \
  -v /data/logs:/app/logs \
  --restart unless-stopped \
  myapp:latest

# View logs
docker logs -f myapp

# Execute commands inside running container
docker exec -it myapp /bin/bash

# Stop and remove
docker stop myapp
docker rm myapp

多\ -\ 容器管束

Docker Compose 允许您定义并运行多@ - @ container application *\ MS K1} 而不是单个管理容器@ MPK2。 您在 YAML 文件里描述整个应用程序堆栈=.}

为什么多克作曲? ?

考虑一个典型的 @.NET Web 应用程序@:

  • ASP.NET核心网络应用程序
  • PostgreSQL 数据库
  • 重新编辑缓存
  • 用于伐木的Seq
  • 也许是背景工人服务

单独管理这些与 docker run 命令成为不操作@ . @ docker compose 解答此 .}

完整 Real@-世界示例 @:制作博客平台

这里,这里 实际生产量 docker-compose.yml 运行此站点的 ( @ mostlylucid.@net @):}

services:
  # Main ASP.NET Core application
  mostlylucid:
    image: scottgal/mostlylucid:latest
    restart: always
    healthcheck:
      test: [ "CMD", "curl", "-f -K", "https://mostlylucid:7240/healthy" ]
      interval: 30s
      timeout: 10s
      retries: 5
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
    env_file:
      - .env
    environment:
      - Auth__GoogleClientId=${AUTH_GOOGLECLIENTID}
      - Auth__GoogleClientSecret=${AUTH_GOOGLECLIENTSECRET}
      - Auth__AdminUserGoogleId=${AUTH_ADMINUSERGOOGLEID}
      - SmtpSettings__UserName=${SMTPSETTINGS_USERNAME}
      - SmtpSettings__Password=${SMTPSETTINGS_PASSWORD}
      - Analytics__UmamiPath=${ANALYTICS_UMAMIPATH}
      - Analytics__WebsiteId=${ANALYTICS_WEBSITEID}
      - ConnectionStrings__DefaultConnection=${POSTGRES_CONNECTIONSTRING}
      - TranslateService__ServiceIPs=${EASYNMT_IPS}
      - Serilog__WriteTo__0__Args__apiKey=${SEQ_API_KEY}
      - Markdown__MarkdownPath=${MARKDOWN_MARKDOWNPATH}
    volumes:
      - /mnt/imagecache:/app/wwwroot/cache
      - /mnt/logs:/app/logs
      - /mnt/markdown:/app/markdown
      - ./mostlylucid.pfx:/app/mostlylucid.pfx
      - /mnt/articleimages:/app/wwwroot/articleimages
      - /mnt/mostlylucid/uploads:/app/wwwroot/uploads
    networks:
      - app_network
    depends_on:
      - db

  # PostgreSQL database
  db:
    image: postgres:16-alpine
    ports:
      - 5266:5432  # Custom external port to avoid conflicts
    env_file:
      - .env
    networks:
      - app_network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 5s
      timeout: 5s
      retries: 5
    volumes:
      - /mnt/umami/postgres:/var/lib/postgresql/data
    restart: always

  # Cloudflare tunnel for secure external access
  cloudflared:
    image: cloudflare/cloudflared:latest
    command: tunnel --no-autoupdate run --token ${CLOUDFLARED_TOKEN}
    env_file:
      - .env
    restart: always
    networks:
      - app_network

  # Umami analytics
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    env_file: .env
    environment:
      DATABASE_URL: ${DATABASE_URL}
      DATABASE_TYPE: ${DATABASE_TYPE}
      HASH_SALT: ${HASH_SALT}
      APP_SECRET: ${APP_SECRET}
      TRACKER_SCRIPT_NAME: getinfo
      API_COLLECT_ENDPOINT: all
    depends_on:
      - db
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
    networks:
      - app_network
    restart: always

  # Translation service (CPU-limited for resource management)
  easynmt:
    image: easynmt/api:2.0.2-cpu
    volumes:
      - /mnt/easynmt:/cache/
    deploy:
      resources:
        limits:
          cpus: "4.0"  # Prevent translation service from consuming all CPU
    networks:
      - app_network

  # Caddy reverse proxy with automatic HTTPS
  caddy:
    image: caddy:latest
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - app_network
    restart: always

  # Seq centralized logging
  seq:
    image: datalust/seq
    container_name: seq
    restart: unless-stopped
    environment:
      ACCEPT_EULA: "Y"
      SEQ_FIRSTRUN_ADMINPASSWORDHASH: ${SEQ_DEFAULT_HASH}
    volumes:
      - /mnt/seq:/data
    networks:
      - app_network

  # Prometheus metrics collection
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    volumes:
      - prometheus-data:/prometheus
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
    networks:
      - app_network

  # Grafana visualization
  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
    volumes:
      - grafana-data:/var/lib/grafana
    networks:
      - app_network
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}

  # Host metrics exporter
  node_exporter:
    image: quay.io/prometheus/node-exporter:latest
    container_name: node_exporter
    command:
      - '--path.rootfs=/host'
    networks:
      - app_network
    restart: unless-stopped
    volumes:
      - '/:/host:ro,rslave'

  # Automatic container updates
  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WATCHTOWER_CLEANUP=true
      - WATCHTOWER_LABEL_ENABLE=true
    command: --interval 300  # Check every 5 minutes

volumes:
  grafana-data:
  caddy_data:
  caddy_config:
  prometheus-data:

networks:
  app_network:
    driver: bridge

密钥生产模式 @:

  1. 单一网络: 所有服务 app_network 简单化
  2. 捆绑山峰@: @主机路 # (#/mnt/*) 用于您需要备份的持久性数据@/access
  3. 命名音量: Docker-管理存储您需要直接访问的数据
  4. 监视器标签: 仅更新为自动标记的服务@- update
  5. 资源限额CPU对翻译服务的限制防止资源断绝。
  6. 外部港口测绘@ : @ postgreSQL 在 @ 5266 @ 而不是 @ MPK2 @ 以避免与其他情况发生冲突
  7. 环境文件: 秘密在 .env {\fn微软雅黑\fs16\2cHFFFFFF\3cH4D0000}文件 ( 从未投入过 git@) *

Dockcker 合成键功能

服务依赖性

services:
  web:
    depends_on:
      db:
        condition: service_healthy  # Wait for health check
      redis:
        condition: service_started  # Just wait for start

docker 合成调弦乐队启动顺序@. @% condition: service_healthy 需要数据库的健康检查在启动 Web app.}之前通过。

环境变量和秘密

# .env file (never commit to git!)
DB_PASSWORD=super_secret_password
SMTP_PASSWORD=another_secret
services:
  web:
    environment:
      - DB_PASSWORD=${DB_PASSWORD}  # From .env file
      - STATIC_VALUE=production     # Hardcoded
    env_file:
      - .env                        # Load entire file

用于制作机密@,}使用嵌入密秘或外部秘密管理器 @(_AWS 密秘管理器{,#Azure 键 Vault,}HashiCorp vault}).}*

命名音量与捆绑峰之比

services:
  db:
    volumes:
      # Named volume (managed by Docker)
      - postgres_data:/var/lib/postgresql/data

  web:
    volumes:
      # Bind mount (maps host directory to container)
      - ./data/markdown:/app/Markdown
      - ./logs:/app/logs

命名书卷:

  • 由 docker 管理
  • 集装箱重新启动的全套永久数据
  • 可用 Docker 命令重新保存后备份@ / @
  • cross - 平台兼容

捆绑山峰:

  • 直接映射到主机文件系统
  • 用于开发@ ( @ live 代码重新加载 @ )} @
  • 配置文件@,logs @,上传

联网

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

services:
  web:
    networks:
      - frontend
      - backend

  db:
    networks:
      - backend  # Not exposed to frontend

网络提供孤立@. @ Here,}只有后端服务才能访问该数据库 ,}没有直接曝光.}

健康检查

services:
  db:
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

健康检查允许 Docker 到 @ : @

  • 确定一个容器是否实际上已经准备好 @ ( @ not just started\ ) @
  • 重新使用不健康的集装箱
  • 向管弦乐队提供状态@( @Kubernetes_,}杜克·斯瓦玛(Docker Swararm)=)

常见的嵌入拼写命令

# Start all services (detached)
docker-compose up -d

# Start specific services
docker-compose up -d web db

# View logs (all services)
docker-compose logs -f

# View logs (specific service)
docker-compose logs -f web

# Stop services (containers remain)
docker-compose stop

# Stop and remove containers
docker-compose down

# Stop, remove containers, and remove volumes
docker-compose down -v

# Rebuild and restart
docker-compose up -d --build

# Scale a service
docker-compose up -d --scale worker=3

# Execute command in running service
docker-compose exec web /bin/bash

# Run one-off command
docker-compose run --rm web dotnet ef database update

开发与制作合成文件

与多个撰写文件的单独关注@: @%

多克 - comption * MS K1 _ _ yml (Base):

services:
  web:
    build: .
    environment:
      - ASPNETCORE_ENVIRONMENT=Development

多克- compose\ ._ override @ MS K2_ yml @(_Disvelopment@-}自动-合并 ):

services:
  web:
    volumes:
      - .:/app  # Live code reloading
    ports:
      - "5000:8080"

._prod}.Yyml (双关语) -=YTET -伊甸园字幕组=- 翻译:

services:
  web:
    image: registry.example.com/myapp:${VERSION}
    restart: always
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '2'
          memory: 2G
# Development (base + override)
docker-compose up -d

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

加速 ML 工作量中的 GPU 支持

机器学习@,科学计算,和视频处理应用程序通常需要 GPU 加速度MS K2docker 通过 NVIDIA 容器工具包.支持NIVIDA GPS

建立NVIDIA集装箱工具包

# Install NVIDIA Container Toolkit (Ubuntu/Debian)
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/libnvidia-container/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit

# Configure Docker daemon
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

# Test GPU access
docker run --rm --gpus all nvidia/cuda:12.6.0-base-ubuntu24.04 nvidia-smi

GPU @ - @ accered Python@ MSSK1_ pyTork 应用程序的 docker 文件

# Use NVIDIA CUDA base image
FROM nvidia/cuda:12.6.0-cudnn-runtime-ubuntu24.04

# Install Python
RUN apt-get update && apt-get install -y \
    python3.12 \
    python3-pip \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Install PyTorch with CUDA support
COPY requirements.txt .
RUN pip3 install --no-cache-dir torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124

# Copy application
COPY . .

# Test GPU on container start
RUN python3 -c "import torch; print(f'CUDA available: {torch.cuda.is_available()}'); print(f'GPU: {torch.cuda.get_device_name(0) if torch.cuda.is_available() else \"None\"}')"

ENTRYPOINT ["python3", "train.py"]

运行中的 GPU 容器

# Run with all GPUs
docker run --gpus all myapp:gpu

# Run with specific GPUs
docker run --gpus '"device=0,2"' myapp:gpu

# Run with GPU memory limits
docker run --gpus all --memory=16g myapp:gpu

嵌入器合成中的 GPU

services:
  ml-trainer:
    build:
      context: .
      dockerfile: Dockerfile.gpu
    image: myapp:gpu
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all  # or specific count: 1, 2, etc.
              capabilities: [gpu]
    volumes:
      - ./models:/app/models
      - ./data:/app/data
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
      - CUDA_VISIBLE_DEVICES=0,1  # Use GPUs 0 and 1

具有 GPU 和 CPU 构建的翻译服务

@M'Zh这里是一个真正的制作例子, 多数情况下, - @nmt@,@ a 神经机器翻译服务,

该项目展示了#:

  • GPU 和 CPU 变量 - 相同代码库, 不同的基底图像
  • MUY - - 建筑构造 “-”支持 AMD64和ARMMS K2
  • 优化的 docker 图像 - 全部和最小的变体
  • 制作@-_ 已就绪 健康检查=,}体积坚持 *,}正确记录

GPU-}加速翻译处

services:
  translation:
    image: scottgal/mostlylucid-nmt:gpu
    container_name: translation-gpu
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    environment:
      - MODEL_FAMILY=opus-mt
      - FALLBACK_MODELS=mbart50,m2m100
      - CUDA_VISIBLE_DEVICES=0
      - LOG_LEVEL=info
    volumes:
      - model_cache:/app/cache  # Persistent model storage
    ports:
      - "8888:8888"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8888/health"]
      interval: 30s
      timeout: 10s
      retries: 3

volumes:
  model_cache:

CPU- 唯一替代

对于没有 GPUs @ ,}的环境,相同的服务运行在 CPU:}

services:
  translation:
    image: scottgal/mostlylucid-nmt:cpu
    container_name: translation-cpu
    environment:
      - MODEL_FAMILY=opus-mt
      - FALLBACK_MODELS=mbart50,m2m100
    volumes:
      - model_cache:/app/cache
    ports:
      - "8888:8888"
    restart: unless-stopped

volumes:
  model_cache:

可用的图像变体@ : @

  • scottgal/mostlylucid-nmt:gpu -+CUDA+12.6+PyTorrch GPU支持的(~5+GB)+
  • scottgal/mostlylucid-nmt:cpu 微小足迹 @(~2.5 @GB_)
  • scottgal/mostlylucid-nmt:gpu-min @ - 最小 GPU 构建@ MS K1 没有预加载的模型 @ MPK2GB)
  • scottgal/mostlylucid-nmt:cpu-min 微小CPU建设

密钥特性 @:

  • GPU 加速使用 CUDA 快速翻译
  • 模型自动=-}下载@:_}下载翻譯模式於-{% accurd
  • 后退支援: Opus-MT→ mBARTEMS K3→MQ2MZ100最大语言覆盖范围
  • 量持久性:卡缓存模型横跨容器重新启动
  • 卫生终点: /health 和 /ready 用于管弦乐队
  • 多重-- 建筑设计:在 x86_64 和ARMEK2 MS K3Apple Silicon, 草莓皮)

见 GitHub 的完整项目 用于 Dockerfiles 示例@, 构建脚本 @ , 和 API 文档@ MS K2

多Q- 带有 docker 构建器的建筑

用于 Raspberry Pi 和 Apple Silicon Macs @,有时甚至包括ARM@32

为何多@- @# 建筑问题

# Problem: Image built on M1 Mac won't run on Linux server
docker build -t myapp:latest .  # Builds for ARM64
docker push myapp:latest
# Server tries to run it... error: "exec format error"

# Solution: Build for multiple platforms
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest --push .

设置启动构建器

Docker Buildx 包含在 Docker 桌面@ . @ 用于 Linux @ MS K1}

# Verify buildx is available
docker buildx version

# Create a new builder instance
docker buildx create --name multiarch --driver docker-container --use

# Inspect and bootstrap the builder
docker buildx inspect --bootstrap

# List available platforms
docker buildx inspect | grep Platforms

多@ - @ 建筑化嵌入文件

大多数 docker 文件工作时没有更改@ , @ but here is some title\ : @

# Use official multi-arch base images
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base

# For platform-specific operations, use build arguments
ARG TARGETPLATFORM
ARG BUILDPLATFORM

RUN echo "Building on $BUILDPLATFORM for $TARGETPLATFORM"

# Install architecture-specific dependencies
RUN if [ "$TARGETPLATFORM" = "linux/arm64" ]; then \
        apt-get update && apt-get install -y some-arm64-package; \
    elif [ "$TARGETPLATFORM" = "linux/amd64" ]; then \
        apt-get update && apt-get install -y some-amd64-package; \
    fi

多平台大楼

# Build and push for AMD64 and ARM64
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myregistry/myapp:latest \
  -t myregistry/myapp:1.0.0 \
  --push \
  .

# Build without pushing (loads into local Docker)
# Note: Can only load one platform at a time
docker buildx build \
  --platform linux/amd64 \
  -t myapp:latest \
  --load \
  .

# Build and export to tar files
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myapp:latest \
  -o type=tar,dest=./myapp.tar \
  .

多QM- 带有多克合成的建筑设计

很不幸,,+Docker Compose does @'}直接支持建设=.+Working rounds@:

选项 @1: @ pre@ -}构建图像

# Build multi-arch images first
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest --push .

# Then use in compose
services:
  web:
    image: myapp:latest  # Already built for multiple architectures

构建脚本

#!/bin/bash
# build-multiarch.sh

docker buildx build --platform linux/amd64,linux/arm64 \
  -t myregistry/web:latest \
  -f web/Dockerfile \
  --push \
  web/

docker buildx build --platform linux/amd64,linux/arm64 \
  -t myregistry/worker:latest \
  -f worker/Dockerfile \
  --push \
  worker/

docker-compose pull  # Pull the multi-arch images
docker-compose up -d

真正的-世界示例 :CI/CD管道

GitHub 用于多@ - @ architecture 建设的 GitHub 动作工作流程\ MS K1

name: Build and Push Multi-Arch Images

on:
  push:
    branches: [ main ]
    tags: [ 'v*' ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: myregistry/myapp
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha,prefix={{branch}}-

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=registry,ref=myregistry/myapp:buildcache
          cache-to: type=registry,ref=myregistry/myapp:buildcache,mode=max

此工作流程@ :

  • 推到主标签或版本标记时触发
  • 设置用于 cross @ - @ platform 模擬的QEMU
  • AMD64和ARMMS K1的建筑
  • 自动生成标签@(Branch name @ , 语义版本@ MS K2_ SHA}){
  • 使用登记簿加速建造的缓存

高级嵌入构建模式@ : @ real @ MS K1_ 世界示例

缩略 多数缩略语@- @nmt 此项目展示了如何构建和分发来自单一代码库的多个图像变体@.}

构建变式战略矩阵

项目生产 8个不同图像变量 以覆盖不同的使用案例@: @%

@ _ 图像标记 #% MS K1# 建筑结构 * 加速器 @ MPK3} 模型预加载@ Q 大小 @ MASK5 使用 case { }
:cpu (:latest-=YTET -伊甸园字幕组=- 翻译:
:cpu-min +AMMQ64,+ARMK2+} +CPU @ +否 +~1.5+GB# +动态型号装载@ *
:gpu -=YTET -伊甸园字幕组=- 翻译:
:gpu-min +AMMQ64+NVIDIA CUDA 不使用动态模型的 +~4GB

为什么多重变式 @ ?#

  1. 生产: (#full}): 预加载模型 * @= 即时翻译 *, 无冷开始
  2. 发展:#(_MITIM @): 快速建構 @(~30s vs *5-10ñmin), 体积@-_mount 模型
  3. GPU 图形@ : @ @ I10-15x 在高空中更快@ MS K2 @ comput discribe
  4. CPU CPCPU@ :_ 运行于任何地方@,}没有特殊硬件
  5. 亚美尼亚#64:+Raspberry Pi,+苹果硅+,=ARM服务器

层缓抓战略

Docker 文件使用战略层命令来最大限度地建立缓存再利用@ : @

标准 CPU Docker 文件结构@: @%

FROM python:3.12-slim

# Layer 1: System dependencies (rarely changes)
RUN apt-get update && apt-get install -y --no-install-recommends \
    git curl \
    && rm -rf /var/lib/apt/lists/*

# Layer 2: Python dependencies (changes when requirements.txt updates)
WORKDIR /app
COPY requirements-prod.txt .
RUN pip install --no-cache-dir -r requirements-prod.txt

# Layer 3: Model preloading (slowest layer, changes when model list changes)
ARG PRELOAD_LANGS="de,es,fr,it,nl,pl,pt,ru,zh,ja,ar,uk"
ARG PRELOAD_PAIRS=""
RUN python -c "from easynmt import EasyNMT; \
    import os; \
    langs = os.environ.get('PRELOAD_LANGS', '').split(','); \
    pairs = os.environ.get('PRELOAD_PAIRS', '').split(',') if os.environ.get('PRELOAD_PAIRS') else []; \
    model = EasyNMT('opus-mt'); \
    [model.translate('warmup', source_lang='en', target_lang=lang) for lang in langs if lang]; \
    [model.translate('warmup', source_lang=src, target_lang=tgt) for pair in pairs for src,tgt in [pair.split('->')] if pair]"

# Layer 4: Application code (changes frequently, rebuilds in seconds)
COPY app.py .
COPY src/ ./src/

# Runtime configuration
EXPOSE 8000
ENV PYTHONUNBUFFERED=1 \
    MODEL_CACHE_DIR=/app/models \
    WEB_CONCURRENCY=4

CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:8000", \
     "--worker-class", "uvicorn.workers.UvicornWorker", \
     "--timeout", "300", "--graceful-timeout", "5"]

为何此命令重要 @: @

|层 @|重建频率@|构建时间 @MS K3缓存速率 @| |-------|------------------|------------|----------------| @|_Base image@|}永远不要 @MS K2}除非 Python 版本有变化 #}\ |Q}{0} @ @sk6 @s99%}|* |系统故障| Rarely|MS K3 -=YTET -伊甸园字幕组=- 翻译: @| 模型预加载@| Rarely @( 模式列表更改 @MS K3 @#| #5-10 min @MSKO6 @ @MSC7 @% |} |+App 代号 @|#每个承诺@|_Q#~3}|+10%{|}

结果结果成果“: ” 大多数建筑在“~3”秒内使用缓存层“MS K2”完成。

GPU vs CPU @ :基图像差异

CPU Dockerfile @ :

FROM python:3.12-slim

# CPU-optimized PyTorch (smaller, no CUDA)
RUN pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu

# CPU performance tuning
ENV OMP_NUM_THREADS=4 \
    MKL_NUM_THREADS=4 \
    EASYNMT_BATCH_SIZE=16

GPU Dockerfile {(} dockerfiles\ . gpu):\ @ MSk0 Dockerfile _ MS K1\ gppu}\ MPK2@

FROM nvidia/cuda:12.6.2-cudnn-runtime-ubuntu24.04

# Install Python 3.12
RUN apt-get update && apt-get install -y \
    python3.12 python3-pip \
    && rm -rf /var/lib/apt/lists/*

# CUDA-enabled PyTorch matching CUDA 12.6
RUN pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124

# GPU performance tuning
ENV CUDA_VISIBLE_DEVICES=0 \
    EASYNMT_BATCH_SIZE=64 \
    EASYNMT_MODEL_ARGS='{"torch_dtype":"fp16"}' \
    MAX_INFLIGHT_TRANSLATIONS=1

# Runtime needs GPU access
# docker run --gpus all scottgal/mostlylucid-nmt:gpu

密钥差异@: @%

  • 基底图像: python:3.12-slim @(300MB)vs nvidia/cuda:12.6.2-cudnn-runtime 万岁,万岁
  • 手枪轮“: CPU (~140 MB 2 诉 CUDA 12.4 NSK4 GB})”
  • 批量大小: CPU=16 vs GPU=64 MS K3GPU 高效处理较大批量@)
  • 精度: CPU=FPMS K2 vs GPU=PMPK4 (半精度保存 GPO 内存@)

最优化

Dockerfile@ . @ arm @ MS K1+% 包括ARM- 特定调制@:

FROM python:3.11-slim-bookworm  # Debian Bookworm has better ARM support

# Minimal dependencies (ARM devices often storage-constrained)
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc g++ git curl \
    && rm -rf /var/lib/apt/lists/*

# ARM performance tuning (Raspberry Pi 4/5 with 4GB RAM)
ENV OMP_NUM_THREADS=3 \
    MKL_NUM_THREADS=3 \
    OPENBLAS_NUM_THREADS=3 \
    EASYNMT_BATCH_SIZE=4 \
    MAX_CACHED_MODELS=1 \
    MEMORY_CRITICAL_THRESHOLD=70.0

# Single worker (memory constrained)
CMD ["gunicorn", "app:app", "-w", "1", \
     "--bind", "0.0.0.0:8000", \
     "--timeout", "300"]

特别优化=:

  1. 减少线串: @ @ MS K1_ 线条@ ( @ vs @ I4} 在 x86)# 上, 用于热节拍
  2. 小批次@: @ @ 4@ vs @ I16} 在 x86 @ @ @ *(# 限制的RAMZ) @
  3. 单身工人“:”在“4”GB设备上防止OOM
  4. 内存监测:在 MS K1RAM 使用上的侵略性清理
  5. 保守性超时@:ARM 装置变慢@,}允许更多时间

最小变量@ : @ 运行时间模型加载

Dockerfile .min :

FROM python:3.12-slim

# Dependencies only, NO model preloading
COPY requirements-prod.txt .
RUN pip install --no-cache-dir -r requirements-prod.txt

# Application code
COPY app.py .
COPY src/ ./src/

# Models loaded on-demand from volume
ENV MODEL_CACHE_DIR=/models

VOLUME ["/models"]

用量 : @:

# Create persistent model cache
docker volume create translation-models

# First run: downloads models on-demand
docker run -d \
  -v translation-models:/models \
  -p 8888:8000 \
  scottgal/mostlylucid-nmt:cpu-min

# Subsequent runs: reuse cached models
# Same volume mount, instant startup

最微量交易与完全交易@- @ offs_ :+#

QAspect @ }完整影像 * QMMIMAND 最小圖片@
图像大小 @ 2.5 GB MS K2 @#1.5 USK4
建造时间 @ @ @ 5-10 @ 分钟 @ @ *30#秒@ }
首开始 @ 即时翻译@ 1-2
嗣后开始 即时 @ 便捷@( 如果音量持之以恒 *) # #
磁盘使用 “ 2.5 GB ” 每个集装箱“ I1.5 GQ GB @+ 共享量
发展、发展和发展 快速循环
生产 无网络依赖性 @ 需求量的持久性@

自动多立方构建脚本

建设 M- @all @.#sh 以一致的版本构建所有变量@: @%

#!/bin/bash

# Generate version tags
VERSION=$(date +%Y%m%d.%H%M%S)
GIT_SHA=$(git rev-parse --short HEAD)

# Enable buildx for multi-platform
docker buildx create --use --name multiarch 2>/dev/null || true

echo "Building all variants for mostlylucid-nmt:${VERSION}"

# CPU Full (multi-platform)
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -f Dockerfile \
  -t scottgal/mostlylucid-nmt:cpu \
  -t scottgal/mostlylucid-nmt:latest \
  -t scottgal/mostlylucid-nmt:${VERSION} \
  --build-arg VERSION=${VERSION} \
  --build-arg VCS_REF=${GIT_SHA} \
  --push \
  .

# CPU Minimal (multi-platform)
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -f Dockerfile.min \
  -t scottgal/mostlylucid-nmt:cpu-min \
  -t scottgal/mostlylucid-nmt:${VERSION}-min \
  --build-arg VERSION=${VERSION} \
  --push \
  .

# GPU Full (AMD64 only)
docker build \
  -f Dockerfile.gpu \
  -t scottgal/mostlylucid-nmt:gpu \
  -t scottgal/mostlylucid-nmt:${VERSION}-gpu \
  --build-arg VERSION=${VERSION} \
  --build-arg PRELOAD_LANGS="de,es,fr,it,nl,pl,pt,ru,zh,ja,ar,uk" \
  --push \
  .

# GPU Minimal (AMD64 only)
docker build \
  -f Dockerfile.gpu.min \
  -t scottgal/mostlylucid-nmt:gpu-min \
  --push \
  .

echo "All builds complete!"
echo "Images tagged with version: ${VERSION}"

建设自动化效益:*

  1. 统一版本用于追踪的 Git SHA
  2. 多Q-平台为AMD64}和ARM□64 建立单一命令
  3. 平行出版:}所有变体同时推动
  4. 灵活预装前: 建立要包含哪些模型的参数控制
  5. 已经准备好由 GitHub Action 触发 :

实用使用假设情景

假设情景 @1:开发@(}快速迭代_)

# Use minimal image with volume mount
docker run -d \
  -v ./models:/models \
  -v ./src:/app/src \
  -p 8888:8000 \
  scottgal/mostlylucid-nmt:cpu-min

# Edit code locally, container picks up changes
# Models cached in volume, no re-download

生产CPU ( 高可用性)

# Use full image, no volume needed
docker run -d \
  --restart always \
  --memory=2g \
  --cpus=2 \
  -p 8888:8000 \
  scottgal/mostlylucid-nmt:cpu

# Models preloaded, instant translation
# No external dependencies

生产GPU ( 高通量)

# docker-compose.yml
services:
  translation:
    image: scottgal/mostlylucid-nmt:gpu
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    environment:
      - CUDA_VISIBLE_DEVICES=0
      - EASYNMT_BATCH_SIZE=64

假设情景 @4:ARMZK1边缘部署@(Raspberry Pi)

# Automatic platform selection
docker run -d \
  --restart always \
  --memory=3g \
  -p 8888:8000 \
  scottgal/mostlylucid-nmt:cpu

# Docker pulls ARM64 variant automatically
# Optimized for ARM performance

高级构建模式中的密钥取出

  1. 图层缓存至关重要:按更改频率命令 dockerfile 指令
  2. 用于不同需要的构建变式生产与开发,
  3. M- 平台支持: 使用来自单个 Docker 文件的 AMD64 @ @ MS K2 ARMESK3
  4. 预加载与运行时间装入贸易建设启动时间
  5. 架构@- @% 特定优化:Tune 线索@,批量大小 @,每个平台的内存限制
  6. 自动化事项: 脚本确保不同变量的一致性
  7. 全部版本@:时间戳 @ +_ Git SHA 用于追踪
  8. 量量战略: 持久性缓存量可节省再生时间

这些来自Mostucid-nmt的图案展示了生产过程\ - 已经具备Docker做法,适用于具有多种部署假想情况的任何复杂应用@.}

集装箱改进

@.@NET {9} 对集装箱支援做了重大改进_,}使得在不写 Dockerfile.}的情况下将“.+NET”应用程序容器化变得比以往更加容易。

集装箱出版公司

您可以直接用“ .NET” 发布一个集装箱化应用程序@: @%

# Publish as a container image (no Dockerfile needed!)
dotnet publish --os linux --arch x64 -p:PublishProfile=DefaultContainer

# Specify image name and tag
dotnet publish \
  --os linux \
  --arch x64 \
  -p:PublishProfile=DefaultContainer \
  -p:ContainerImageName=myapp \
  -p:ContainerImageTag=1.0.0

# Multi-architecture
dotnet publish --os linux --arch arm64 -p:PublishProfile=DefaultContainer

配置容器属性

添加到您的 .csproj:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>

    <!-- Container Configuration -->
    <ContainerImageName>myapp</ContainerImageName>
    <ContainerImageTag>$(Version)</ContainerImageTag>
    <ContainerRegistry>myregistry.azurecr.io</ContainerRegistry>

    <!-- Base image (defaults to mcr.microsoft.com/dotnet/aspnet:9.0) -->
    <ContainerBaseImage>mcr.microsoft.com/dotnet/aspnet:9.0-alpine</ContainerBaseImage>

    <!-- Container runtime configuration -->
    <ContainerWorkingDirectory>/app</ContainerWorkingDirectory>
    <ContainerPort>8080</ContainerPort>
    <ContainerEnvironmentVariable Include="ASPNETCORE_ENVIRONMENT">Production</ContainerEnvironmentVariable>

    <!-- User (security best practice) -->
    <ContainerUser>app</ContainerUser>

    <!-- Labels -->
    <ContainerLabel Include="org.opencontainers.image.description">My awesome app</ContainerLabel>
    <ContainerLabel Include="org.opencontainers.image.source">https://github.com/me/myapp</ContainerLabel>
  </PropertyGroup>
</Project>

然后出版:

dotnet publish -p:PublishProfile=DefaultContainer

集装箱支持内建和MSMK0的优势

  1. 不需要 docker 文件降低复杂性
  2. 优化图像: 微软调制图像用于性能
  3. 一致@ : 标准图像, 包括所有 & MS K1\ _NET 应用程序
  4. 安全安保安全@: 自动基础图像更新
  5. 小图像: Trimming and AOT 编译支持

更小图像的 Trimming和 AOT

<PropertyGroup>
  <!-- Enable trimming to remove unused code -->
  <PublishTrimmed>true</PublishTrimmed>
  <TrimMode>full</TrimMode>

  <!-- OR use Native AOT for even smaller, faster images -->
  <PublishAot>true</PublishAot>
</PropertyGroup>

结果*:

  • 标准标准{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}万岁!
  • 进行修补{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}万岁!
  • 与 AOT用于简单应用程序的: ~12MB

比較@ : @ dockerfiles vs Intuttle=-_in

传统 dockerfile 方法@ : @

FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY ["MyApp.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]

内置的- 集装箱接近

# Just this!
dotnet publish -p:PublishProfile=DefaultContainer

两者都产生相似的图像@,,

何时使用 Dockerfile vs 内建@ - @ in

:\ \ 时使用 Docker 文件

  • 您需要完全控制图像
  • 安装系统依赖关系
  • 复杂多层-级建筑
  • 非-标准基准图像

使用已建@ - @ in

  • 标准@.NET web @/_console Apps
  • 你想要简单
  • 利用微软优化
  • 快速原型

Chiseled Ubuntu 图像

@.NET {9} 支持"chiseledMS K3Ubuntu 影像@-RT-:

<PropertyGroup>
  <ContainerBaseImage>mcr.microsoft.com/dotnet/aspnet:9.0-noble-chiseled</ContainerBaseImage>
</PropertyGroup>

福利*:

  • 微细@ :} @ MPK1} 小于常规图像
  • 安全安全: 最小攻击表面@(no 软件包管理器 @, shell)
  • 快速快快速拉动并启动

交易

  • 没有 shell @ ( @ harder 可调试@ MS K1 @ *
  • 有限系统公用事业

最适合在安全和体积重要的地方生产

.NET Aspire 介绍

.NET Aspire 是建构分布式应用程序的备注堆叠@. 把它想象成专门为“.Net micservices @.”设计的类固醇多克合成

什么是"天启" ?

Aspire 提供@: @%

  1. 管弦乐: 运行并连接本地多种服务
  2. 服务发现: 服务自动找到对方
  3. 遥测“: 内建 - 在伐木中”“, 立方公尺”、“, 追踪”
  4. 组件构成构成部分:Pre-Configuled整合@(RidisMS K3PostgresSQL,RabitMMSKO5等.)
  5. 部署: 生成Kubernetes/ 多克作曲列表

高级建筑结构

Aspire 解决方案有三个项目类型@: @%

  1. App 主机: 管弦乐
  2. 服务项目您的实际服务 @( @Web APIs@,}工人 @MS K3&等#.)
  3. 服务默认@:_共享配置@(loging,}健康检查{,}等等□.)

快速示例

1. 创建 Aspire 项目:

dotnet new aspire-starter -n MyDistributedApp
cd MyDistributedApp

2.+App App 主机 @(@MydifiredApp @MS2_AppHost}App Host=/ Program}.{cs):

var builder = DistributedApplication.CreateBuilder(args);

// Add Redis cache
var cache = builder.AddRedis("cache");

// Add PostgreSQL database
var db = builder.AddPostgres("postgres")
               .AddDatabase("mydb");

// Add API service (references cache and db)
var api = builder.AddProject<Projects.MyApi>("api")
                 .WithReference(cache)
                 .WithReference(db);

// Add frontend (references API)
builder.AddProject<Projects.MyWeb>("web")
       .WithReference(api);

builder.Build().Run();

@3.在您工作时使用@:#

// MyApi/Program.cs
var builder = WebApplication.CreateBuilder(args);

// Aspire automatically configures these based on AppHost
builder.AddServiceDefaults();
builder.AddRedisClient("cache");
builder.AddNpgsqlDbContext<MyDbContext>("mydb");

var app = builder.Build();
app.MapDefaultEndpoints();  // Health, metrics, etc.

4.运行一切 :"

dotnet run --project MyDistributedApp.AppHost

紧急发射@: @%

  • 位于 http @:// @localhost@:15888}的挂贴板
  • 配置适当的所有服务
  • 集装箱中的Redis和PostgreSQL
  • 在各服务处之间分配追踪

Aspirre 与 Docker 合成

Docker 拼写@ : @%

  • 語言@-不可知性
  • 以基础设施为主
  • 手动服务发现
  • 带上你自己的观察力

寄件人@: @%

  • @.NET-}特例
  • 以发展为重点
  • 自动服务发现
  • 内建的- 遥测
  • 生成部署清单

两者均使用“: ”当地开发的占位器“,”生成多克作曲“MSSK2”生产“Kubernetes”

部署派遣助理人员

生成部署显示器@: @%

# Generate Docker Compose
dotnet run --project MyDistributedApp.AppHost -- \
  --publisher compose \
  --output-path ../deploy

# Generate Kubernetes manifests
dotnet run --project MyDistributedApp.AppHost -- \
  --publisher manifest \
  --output-path ../deploy/k8s

然后部署:

# Docker Compose
docker-compose -f deploy/docker-compose.yml up -d

# Kubernetes
kubectl apply -f deploy/k8s/

敏感部件

Preá- 建立集成使得添加服务变得微不足道@:

// Add various backing services
var redis = builder.AddRedis("cache");
var postgres = builder.AddPostgres("db").AddDatabase("mydb");
var rabbitmq = builder.AddRabbitMQ("messaging");
var mongodb = builder.AddMongoDB("mongo").AddDatabase("docs");
var sql = builder.AddSqlServer("sql").AddDatabase("business");

// Add Azure services
var storage = builder.AddAzureStorage("storage");
var cosmos = builder.AddAzureCosmosDB("cosmos");
var servicebus = builder.AddAzureServiceBus("messaging");

// Use in services
builder.AddProject<Projects.MyService>("service")
       .WithReference(redis)
       .WithReference(postgres)
       .WithReference(rabbitmq);

以有限资源为己任

如果您在VPS上用 @4+GB RAM或旧笔记本电脑托管,

仅依赖发展

为了本地发展 您不需要完整的生产堆 . Devdeps @- @docker@ -#compose @MS K2_yml 编辑器 选项只运行您需要的内容 @:}

services:
  smtp4dev:
    image: rnwood/smtp4dev
    ports:
      - "3002:80"
      - "2525:25"
    volumes:
      - e:/smtp4dev-data:/smtp4dev
    restart: always

  postgres:
    image: postgres:16-alpine
    container_name: postgres
    ports:
      - "5432:5432"
    env_file:
      - .env
    volumes:
      - e:/data:/var/lib/postgresql/data
    restart: always

为什么这为发展工作?

  • SMTP4Dev@: 测试电子邮件功能, 没有真正的 SMTP 服务器
  • 邮件greSQL: 匹配生产数据库
  • 总足迹总数: MS K1MB RAM vs *2-4GB 全堆放

见 充分发展依赖性指南 设置指令@. @%

资源@- @ 限制的生产设置

VPS (2-4+GBRAM%),}优先提供基本服务=:*

services:
  # Core application
  mostlylucid:
    image: scottgal/mostlylucid:latest
    restart: always
    env_file: .env
    volumes:
      - ./markdown:/app/markdown
      - ./logs:/app/logs
    networks:
      - app_network
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '1.0'
        reservations:
          memory: 256M

  # Database only
  db:
    image: postgres:16-alpine
    env_file: .env
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - app_network
    deploy:
      resources:
        limits:
          memory: 512M
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 30s
      timeout: 5s
      retries: 3

  # Caddy for HTTPS
  caddy:
    image: caddy:latest
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
    networks:
      - app_network
    deploy:
      resources:
        limits:
          memory: 128M

volumes:
  db_data:
  caddy_data:

networks:
  app_network:

移除了哪些' 和替代物 @:

  • 没有普罗米修斯 /Grafana@:_ 使用外部监控@(_ 更新时间Robot},_ 更好地排入免费的阶梯=){
  • 无Seq: 使用文件@- 基于日志 @+ docker logs,或Seq Cloud 无层
  • 没有监视器: 手册更新 GitHub Action 通知
  • 翻译处: 运行于 @- 需求在您启动的单独容器中@/手动停止
  • 资源限额防止任何单项服务消耗所有内存

逐步增强战略

启动最小端@ , @ {按需要添加服务\ MS K1} @

-=YTET -伊甸园字幕组=- 翻译:

# Just app + database + reverse proxy
docker-compose up -d mostlylucid db caddy

+(2GB VPS)}添加可观察性

# Add lightweight monitoring
docker-compose up -d mostlylucid db caddy seq
# Use Seq free 10GB/month

阶段: 3:+全堆叠+(4+GB=++VPS)}

# Add everything
docker-compose up -d

资源优化技术

1.使用阿尔卑斯山图像

services:
  myapp:
    image: postgres:16-alpine     # 50% smaller than postgres:16
    # vs
    image: postgres:16            # Full Debian base

节节余:阿尔卑斯山图像小于 @50-70%

2.共用数据库

使用一个带有多个数据库的 PostgreSQL 实例@:

db:
  image: postgres:16-alpine
  # One instance, multiple databases
  # Umami, Mostlylucid, etc. all share this PostgreSQL

节节余: 400MB 每增加一个数据库您合并

3.- 背景服务限制 CPU

easynmt:
  deploy:
    resources:
      limits:
        cpus: "2.0"      # Don't let translation consume all CPU
      reservations:
        cpus: "0.5"      # Guarantee minimum

这阻止了背景工作 使您的网络应用程序绝食@. @

4.持久性缓存量

所涵盖 与 Docker 共享图像正在安装的缓存目录防止不必要的后处理@: @%

mostlylucid:
  volumes:
    - /mnt/imagecache:/app/wwwroot/cache  # ImageSharp cache persists across restarts

为什么重要: 没有此选项, 每个容器重新开始重生所有缩略图@/处理过的图像 @.

使用外部服务@( @free Tiers_)

@ _Service@ Self-_Hosted RAM% 外部替代 { }
@ _Seq@ }~500MB □ Seg Cloud4GB}/月度免費 )#
M Grafana Cloud @( 免费的阶梯 @) @ @MS K7#
@ ~200MB @ I } 可见的@(}支付$) 或自负 -host 其他地方 @ #

战略战略战略: 卸载可观察到免费级别@, 在您的 VPS.上保留核心应用程序

6.On-需求服务

翻译等不常用的服务@: @%

# Create a separate compose file
# translation-compose.yml
services:
  easynmt:
    image: easynmt/api:2.0.2-cpu
    ports:
      - "8888:8888"
    volumes:
      - /mnt/easynmt:/cache/

# Only run when needed
docker-compose -f translation-compose.yml up -d

# Translate your content
# ...

# Shut down when done
docker-compose -f translation-compose.yml down

节节余当翻译服务在运行时 ' @ t

世界预算托管机构

这里的' @% 1 月 Hetzner VPS @ (2 @ vCPU+,}{4$GBRAMQ):}运行方式

# Minimal production compose
services:
  mostlylucid:
    image: scottgal/mostlylucid:latest
    restart: always
    env_file: .env
    volumes:
      - /mnt/markdown:/app/markdown
      - /mnt/logs:/app/logs
      - /mnt/imagecache:/app/wwwroot/cache
    depends_on:
      - db

  db:
    image: postgres:16-alpine
    env_file: .env
    volumes:
      - /mnt/postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready"]
      interval: 30s

  cloudflared:
    image: cloudflare/cloudflared:latest
    command: tunnel run --token ${CLOUDFLARED_TOKEN}
    restart: always

  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      WATCHTOWER_CLEANUP: "true"
      WATCHTOWER_LABEL_ENABLE: "true"
    command: --interval 3600  # Check once per hour, not every 5 minutes

资源使用总额 @: @%

  • RAMZ: ~800MB( leaves <3.2GB free})
  • 磁盘#:} @ ~2_%GB
  • CPU: <10% 闲置MS K2 MPK3 装入中

什么是'? 不同吗?

  • 没有 Prometheus@/ @Grafana @(_use 恢复时间 Robot @MS K2云雾分析=)}
  • 无 Seq @ (_use docker logs {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}不时的Grep@) @
  • 没有 Umami (use Cloudflare Web分析器 @ - free@)#
  • 监测站每小时检查一次,而不是每个“5”分钟。
  • 没有翻译服务@( 需要时手动运行 @)

预算监测

没有Prometheus @/ @Grafana#,_使用这些免费的替代方案@:

健康监测#:

# Simple health check script
#!/bin/bash
while true; do
  curl -f http://localhost/healthz || echo "Health check failed!" | mail -s "Alert" [email protected]
  sleep 300
done

日志监测@: @%

# Watch for errors
docker-compose logs -f --tail=100 | grep -i error

# Email on critical errors
docker-compose logs -f | grep -i "critical" | while read line; do
  echo "$line" | mail -s "Critical Error" [email protected]
done

资源使用@: @%

# Quick resource check
docker stats --no-stream

# Pretty output
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

高级版本@ : @ 即 *.NET 路径

现在让我们使用“.NET Aspire”.来重新构思整个堆叠, 这样能给你们带来更好的“ .NET集成和惊人的开发者经验” “.” 。

设置 Mostlylucid 的指定任务

创建 Aspire App 主机@ : @ action

# Add Aspire to your solution
dotnet new aspire-apphost -n Mostlylucid.AppHost
cd Mostlylucid.AppHost

Mostlylucid.ApphostMS K1 方案.cs}:

var builder = DistributedApplication.CreateBuilder(args);

// PostgreSQL with persistent data
var postgres = builder.AddPostgres("postgres")
    .WithDataVolume()  // Persistent storage
    .WithPgAdmin();     // Optional: PgAdmin for database management

var mostlylucidDb = postgres.AddDatabase("mostlylucid");
var umamiDb = postgres.AddDatabase("umami");

// Seq for centralized logging
var seq = builder.AddSeq("seq")
    .WithDataVolume();

// Redis for caching (if needed)
var redis = builder.AddRedis("cache")
    .WithDataVolume()
    .WithRedisCommander();  // Optional: Redis Commander UI

// Main blog application
var mostlylucid = builder.AddProject<Projects.Mostlylucid>("web")
    .WithReference(mostlylucidDb)
    .WithReference(seq)
    .WithReference(redis)
    .WithEnvironment("TranslateService__Enabled", "false")  // Disable for dev
    .WithHttpsEndpoint(port: 7240, name: "https");

// Umami analytics
var umami = builder.AddContainer("umami", "ghcr.io/umami-software/umami", "postgresql-latest")
    .WithReference(umamiDb)
    .WithEnvironment("DATABASE_TYPE", "postgresql")
    .WithEnvironment("TRACKER_SCRIPT_NAME", "getinfo")
    .WithEnvironment("API_COLLECT_ENDPOINT", "all")
    .WithHttpEndpoint(port: 3000, name: "http");

// Translation service (CPU version, with resource limits)
var translation = builder.AddContainer("easynmt", "easynmt/api", "2.0.2-cpu")
    .WithDataVolume("/cache")
    .WithHttpEndpoint(port: 8888, name: "http")
    .WithEnvironment("MODEL_FAMILY", "opus-mt");

// Scheduler service (Hangfire background jobs)
var scheduler = builder.AddProject<Projects.Mostlylucid_SchedulerService>("scheduler")
    .WithReference(mostlylucidDb)
    .WithReference(seq);

// Prometheus for metrics
var prometheus = builder.AddContainer("prometheus", "prom/prometheus", "latest")
    .WithDataVolume()
    .WithBindMount("./prometheus.yml", "/etc/prometheus/prometheus.yml")
    .WithHttpEndpoint(port: 9090);

// Grafana for visualization
var grafana = builder.AddContainer("grafana", "grafana/grafana", "latest")
    .WithDataVolume()
    .WithHttpEndpoint(port: 3001)
    .WithEnvironment("GF_SECURITY_ADMIN_PASSWORD", builder.Configuration["Grafana:AdminPassword"] ?? "admin");

builder.Build().Run();

委托服务默认值

创建创建 Mostlucid@ . @ serviciceDefaults 多数功能性崩溃 “:”项目

// Extensions.cs
public static class Extensions
{
    public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder)
    {
        // OpenTelemetry
        builder.Services.AddOpenTelemetry()
            .WithMetrics(metrics =>
            {
                metrics.AddAspNetCoreInstrumentation()
                    .AddHttpClientInstrumentation()
                    .AddRuntimeInstrumentation();
            })
            .WithTracing(tracing =>
            {
                if (builder.Environment.IsDevelopment())
                {
                    tracing.SetSampler(new AlwaysOnSampler());
                }

                tracing.AddAspNetCoreInstrumentation()
                    .AddHttpClientInstrumentation()
                    .AddEntityFrameworkCoreInstrumentation();
            });

        // Health checks
        builder.Services.AddHealthChecks()
            .AddCheck("self", () => HealthCheckResult.Healthy(), tags: new[] { "live" });

        return builder;
    }

    public static IApplicationBuilder MapDefaultEndpoints(this WebApplication app)
    {
        app.MapHealthChecks("/healthz");
        app.MapHealthChecks("/ready", new HealthCheckOptions
        {
            Predicate = check => check.Tags.Contains("ready")
        });

        return app;
    }
}

更新 Mostlylucid@/ @ program_.%cs

var builder = WebApplication.CreateBuilder(args);

// Add Aspire service defaults (telemetry, health checks)
builder.AddServiceDefaults();

// Add services
builder.AddNpgsqlDbContext<MostlylucidDbContext>("mostlylucid");
builder.AddRedisClient("cache");

// Existing service registrations...
// builder.Services.AddControllersWithViews();
// etc...

var app = builder.Build();

// Map Aspire default endpoints
app.MapDefaultEndpoints();

// Existing middleware...
app.Run();

远期办法的惠益

发展经验

  1. 单一个命令: dotnet run --project Mostlylucid.AppHost 开始一切
  2. 仪表板@:_美丽的UI在 http://}@localhost@:15888}显示#:*
    • 所有有生命状态的服务
    • 所有服务在同一地点的日志
    • 服务之间分布的跟踪
    • 计量和健康检查
  3. 服务发现:Services 通过名称自动找到对方
  4. 配置配置:在AppHost,不再集中 .env 杂耍

生产部署=:

从 Aspire 生成部署列表@: @%

# Generate Docker Compose
dotnet run --project Mostlylucid.AppHost -- \
  --publisher compose \
  --output-path ./deploy

# This creates a production-ready docker-compose.yml
cd deploy
docker-compose up -d

生成 docker@ - @ compose @ MS K1 @ yml ( 简化):

services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres-data:/var/lib/postgresql/data

  mostlylucid-db:
    image: postgres:16
    # Database initialization

  seq:
    image: datalust/seq:latest
    environment:
      ACCEPT_EULA: Y
    volumes:
      - seq-data:/data

  web:
    image: scottgal/mostlylucid:latest
    environment:
      ConnectionStrings__mostlylucid: Host=postgres;Database=mostlylucid;Username=postgres;Password=${POSTGRES_PASSWORD}
      ConnectionStrings__cache: cache:6379
    depends_on:
      - postgres
      - cache
      - seq

  cache:
    image: redis:7-alpine
    volumes:
      - redis-data:/data

  # ... other services

Aspirre 与传统嵌入式拼写

@ @ 地物 @ I @ 多克作曲@ MS K2 @ * ._ NET Aspire @ MPK4#
设置设置设置 #手册 YAML @ }C#}与IntelliSense的代码 * *
服务发现 手动 env vars 自动 *
可观察性 带来你自己的# }(内建)―-}在 @( 200)}开放的远程测距
发展、发展和发展 docker-compose up dotnet run *+ 板子 * *
调试 “ ”附在视觉演播室的容器“ ” F5 中
日志 docker logs 中央控制仪表板 @
追查追踪 手动设置 @ 自动分配跟踪@
生产 直接使用 YAML * 生成舱单*
学习曲线 YAML 语法@ C#你已经知道 @

何时使用 Aspire vs Docker 撰写器

使用占位时@ : @

  • 大楼 .+NET微服务
  • 您想要集成调试
  • 团队对C#很满意
  • 您需要分布式追踪@ - @ of_ - @ the\ MS K2}框
  • 您正在部署到 Azure 集装箱Apps @(#native support@)

** :\ \ 时使用嵌入式拼写**

  • (Node.jsMS K2Python},Go,等
  • 团队更喜欢基础设施@- @as @-_code YAML
  • 正在部署到任何 Docker @ - con兼容的主机
  • 您需要对集装箱配置进行最大控制
  • 简单单一@-}服务部署

**双用@ : @ ***

  • 促进地方发展
  • 生成用于生产部署的多克混音
  • 两个世界最优秀的

此 Blog@ ' @%s Docker 设置的演变

此博客“ ' @%s Docker 旅程” 展示了典型的进度@:

  1. 7月 @2024 @ @ @ - @ 简单开始@: @ 仅此应用程序% , @ Cloudflared @ MS K2 @ and watchower
  2. 8月 2024 NSK1D依赖性: 添加开发@-}只提供服务
  3. 8月 @2024 @ -}图像光化固定: 已解析的缓存音量权限
  4. 11月 2024 MS K1 全堆叠“:”完全可使用 Prometheus @,+Grafana@,_Seq
  5. 今天今天:_Aspire 首开发选项

汲取的教训:

  • 启动简单@, @ 只在需要时才添加复杂性
  • 独立的dev和生产配置
  • 资源限量防止一项服务杀害他人
  • 用于缓存的音量堆积,可节省大量后处理时间
  • 观察塔启用零@ - @ doduntime auto=-}更新时间
  • 可观察性值生产资源成本

最佳做法摘要

Dockerfile 最佳做法

  1. 使用多QM-+Z 级构建
  2. 运行为非@ - @ root 用户
  3. 最佳缓存命令指示
  4. 使用特定的基底图像标记@ ( @ note latest)
  5. 包括健康检查
  6. 使用 .dockerignore 排除不必要的文件
  7. 最小化层@(combine RUN 命令 @)
  8. 使用构建参数促进灵活性

Docker 合成最佳做法

  1. 为数据使用命名的音量
  2. 实施健康检查
  3. 使用 .env 永不犯)
  4. 界定明确的网络
  5. 使用 depends_on 健康状况和健康条件
  6. 设定重新启动政策
  7. dev/prod 独立配置
  8. 生产资源限量

安保最佳做法

  1. 运行为非@ - @ root 用户
  2. 使用 chiseled / minminal base 图像
  3. 弱点扫描图像
  4. 不断更新基本图像
  5. Don'% t 包含图像中的秘密
  6. 尽可能只使用已读@-}文件系统
  7. 限制集装箱容量
  8. 使用嵌入机密或外部秘密管理器

业绩最佳做法

  1. 使用 buildKit 快速构建
  2. 利用层层缓存
  3. 用于缩小图像大小的 MUIM-+ZSage 建设阶段
  4. 使用 .dockerignore 慷慨大方
  5. AlpineMSMK0 碎缩图像
  6. 用于开发的用量
  7. 配置适当的资源限制
  8. 使用健康检查进行管弦

解决共同问题

集装箱 Won'}启动

# Check logs
docker logs container-name

# Common issues:
# 1. Port already in use
docker ps | grep 8080  # Find conflicting container
docker stop conflicting-container

# 2. Missing environment variables
docker inspect container-name | grep Env

# 3. Failed health check
docker inspect container-name | grep Health -A 20

缓慢构建

# Enable BuildKit for faster builds
export DOCKER_BUILDKIT=1

# Use build cache
docker build --cache-from myapp:latest -t myapp:latest .

# Check what's taking time
docker build --progress=plain -t myapp:latest .

联网问题

# Containers can't communicate
# Solution: Ensure they're on the same network
docker network ls
docker network inspect network-name

# DNS not working
# Container names are DNS names within Docker networks
docker exec web ping db  # Should work if both on same network

数量权限问题

# Permission denied on volume
# Solution: Match user IDs
FROM ubuntu
RUN useradd -u 1000 appuser  # Match host user ID
USER appuser

结论结论

Docker已经从一个简单的集装箱化工具演变成一个建设“,”航运“MSMK1”和运行现代应用程序的综合性平台@.。 该指南将您从基本原理带入生产中 =-\ready approductions @,}用真实的<->世界性实例, 从运行 mostlucid.netMPK7}

密钥外出

对于初学者来说 :

预算负责人VPS=:

  • 启动最小@ :_ App @ MS K1}数据库 * + 逆向代理 * (~800MB RAMEZ)
  • 使用高山图像和资源限制
  • 卸载到自由级@( @Seq Cloud_,Grafana Clod=,更新时间Robot})
  • 运行昂贵的服务 @ ( @ translation=,} MLQ) 只使用 @ I-}
  • @$6/_oth month VPS 可以经营制作博客,

用于生产部署

  • 健康检查启用零@ - downtime 更新观察器
  • 独立网络提供安全 {(} pronend /}\ 后端孤立@)
  • 用于备份@/}访问权限需要的数据绑定挂载
  • Docker-管理存储的音量命名
  • CPU/\memory 限制防止资源断绝
  • Cloudflare 隧道消除了对公共IP地址的需求

@._NET 开发者@:

  • 在 NET 9内建MS-}在集装箱出版中消除用于简单应用程序的 docker 文件
  • Chiseled Ubuntu 图像提供最小攻击表面
  • @.NET Aspire 提供最佳的-in}-地方级发展经验
  • Aspire 能够生成多克作曲用于生产部署
  • 开放遥测集成与 Aspire 自由

用于高级使用案例@:

  • GPU 容器使 ML/AAI 工作量能够以 @ 10-15x 加速完成
  • 多 - 建筑结构从单一来源建立支持ARM64和AMDMS K2
  • GitHub 动作自动化多@ - @platform 构建
  • 层层的渐变急剧加快了重复建设的速度

旅行

此博客“ ' @%s Docker 进化演化” 反射了典型的进展@:

-=YTET -伊甸园字幕组=- 翻译: |-------|----------|-----------|------------| | 阶段1 @(_七月#2024)}(|}App A+}隧道 |}~300{MB 200)}♪|}简单的@|}* | 阶段2 |500MB 学习| | 阶段3 | MS K5 MB| 调试 | | 阶段4 |+3.5+GB I|+生产 @|# | 阶段5 @(_今天 @MS K1} @ | @ *+# Aspire 选项@|}变数 @|#现代 @MSC6#

模式图式@:_ 开始简单化的@,}当问题出现时解决问题 #,} 只有在需要时才增加复杂性.}

什么是' 下一步 @?

取决于您的路径@: @%

  • 学习嵌入以“:”开头 Docker 合成基础
  • 自 己 -尝试此文章的最小 VPS 设置@ :
  • 建设微观服务@ :_ 探索@ MS K1# NET Aspire
  • 运行中 ML 工作量:检查一下 翻译服务
  • 多Q-平台“: ” 为ARM=64}“+ AMD64”建造建筑

资源资源资源 资源和资源资源资源

正式文件_:

本博客@' @s Docker Series_:

  1. docker 合成器 正在启动
  2. 发展依赖性 - 本地 dev 设置
  3. 与 Docker 共享图像 - 量权限
  4. 此篇文章 @ -_ 深潜到生产中

相关项目 @:

记住: 最好的架构是满足您的需要而不不必要的复杂@. 启动简单, 度量 @,}当您遇到实际的瓶颈时优化 {- 想象不到的是#.

快乐的集装箱化 @! @ @ 🐳#

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.