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集装箱化
Sunday, 09 November 2025
一. 导言导言 导言 导言 导言
Docker从根本上改变了我们如何构建“, ship @, ” 和运行应用程序“MS K2 启动的简单集装箱化工具已经演变成一个完整的生态系统,用于现代应用开发和部署@.
这是我Docker系列中的第四篇也是最全面的文章, 用于“ .@NET developments @ MS K1 ” 如果您是新加入 Dokker@,} 您可能要以“ MPK4}” 开始
- docker 合成器 @- 以基本的多功能-acontainer 设置@( 7月 @MSC3
- Docker 混音器的开发依赖 建立本地环境 @(August#2024)
- 与 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!"
集装箱解决了几个关键问题
- 环境一致性:Disvelopment,测试,和生产环境完全相同
- 依赖性隔离@ : @ no more @ MPK1 @ DLL Hell@ MS K2 @ 或矛盾的图书馆版本
- 可复制构建@ :} 相同的输入 *\ MS K1} 同样的输出 * * , * 每次都一样
- 快速部署@: 启动容器在秒@,}没有时间
- 资源使用效率“: 运行几十个集装箱 在单个宿主上”
基本嵌入概念
图像与容器
# 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
密钥洞见@: @%
- 本地文件系统# :你的#
COPY和ADD从您的机器读取命令 - 构建图像# :你的#
RUN在容器中执行的命令 @'%s OS *(%not your machine@) - 输出图像: 最终图像包含在构建中创建的所有层
- 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
此流程中的关键洞察@ : @
- SDK 图像丢弃@ :_ {1.5} GBSDK 容器在发布 < \ / > * \ @ MPK2 _\ > 只公布\ MS K3 ZMB 的编译输出后被丢弃 premove
- 层层缓存: 复制
.csproj在源代码之前, 源码意味着依赖性恢复被缓存, 除非依赖性改变 - 前期资产@ : 单独建造@(}经常通过
npm run build) 并复制到最终图像中 - 配置文件:
appsettings.json和wwwroot/从您的机器复制的内容@, @% 未建立 - 最终图像@: 起始于最短运行时间的图像@(~220MB) @ +你的应用程序 @MS K4MTMQ}{)}#+资产 *(~5MT)Z=~255
- 仅生产文件:源碼, obj/, binMS K3 節點_MTULESMSQK5 永遠不會到最後的影像
关键原则说明 :
- 多 MUSK0 阶段建设@ : @ 分开建筑@ MS K1 @ 出版阶段大大缩小最终图像大小
- 图层优化: 在源代码前复制依附文件, 以更好地缓存
- 安全安保安全: 运行为非{-}\ root user
- 健康检查集装箱管弦手可以监控应用健康
- 明确环境: 设定生产默认值
建筑和运行
# 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
密钥生产模式 @:
- 单一网络: 所有服务
app_network简单化 - 捆绑山峰@: @主机路 # (#
/mnt/*) 用于您需要备份的持久性数据@/access - 命名音量: Docker-管理存储您需要直接访问的数据
- 监视器标签: 仅更新为自动标记的服务@- update
- 资源限额CPU对翻译服务的限制防止资源断绝。
- 外部港口测绘@ : @ postgreSQL 在 @ 5266 @ 而不是 @ MPK2 @ 以避免与其他情况发生冲突
- 环境文件: 秘密在
.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 |
为什么多重变式 @ ?#
- 生产: (#full}): 预加载模型 * @= 即时翻译 *, 无冷开始
- 发展:#(_MITIM @): 快速建構 @(~30s vs *5-10ñmin), 体积@-_mount 模型
- GPU 图形@ : @ @ I10-15x 在高空中更快@ MS K2 @ comput discribe
- CPU CPCPU@ :_ 运行于任何地方@,}没有特殊硬件
- 亚美尼亚#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)vsnvidia/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"]
特别优化=:
- 减少线串: @ @ MS K1_ 线条@ ( @ vs @ I4} 在 x86)# 上, 用于热节拍
- 小批次@: @ @ 4@ vs @ I16} 在 x86 @ @ @ *(# 限制的RAMZ) @
- 单身工人“:”在“4”GB设备上防止OOM
- 内存监测:在 MS K1RAM 使用上的侵略性清理
- 保守性超时@: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}"
建设自动化效益:*
- 统一版本用于追踪的 Git SHA
- 多Q-平台为AMD64}和ARM□64 建立单一命令
- 平行出版:}所有变体同时推动
- 灵活预装前: 建立要包含哪些模型的参数控制
- 已经准备好由 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
高级构建模式中的密钥取出
- 图层缓存至关重要:按更改频率命令 dockerfile 指令
- 用于不同需要的构建变式生产与开发,
- M- 平台支持: 使用来自单个 Docker 文件的 AMD64 @ @ MS K2 ARMESK3
- 预加载与运行时间装入贸易建设启动时间
- 架构@- @% 特定优化:Tune 线索@,批量大小 @,每个平台的内存限制
- 自动化事项: 脚本确保不同变量的一致性
- 全部版本@:时间戳 @ +_ Git SHA 用于追踪
- 量量战略: 持久性缓存量可节省再生时间
这些来自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的优势
- 不需要 docker 文件降低复杂性
- 优化图像: 微软调制图像用于性能
- 一致@ : 标准图像, 包括所有 & MS K1\ _NET 应用程序
- 安全安保安全@: 自动基础图像更新
- 小图像: 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 提供@: @%
- 管弦乐: 运行并连接本地多种服务
- 服务发现: 服务自动找到对方
- 遥测“: 内建 - 在伐木中”“, 立方公尺”、“, 追踪”
- 组件构成构成部分:Pre-Configuled整合@(RidisMS K3PostgresSQL,RabitMMSKO5等.)
- 部署: 生成Kubernetes/ 多克作曲列表
高级建筑结构
Aspire 解决方案有三个项目类型@: @%
- App 主机: 管弦乐
- 服务项目您的实际服务 @( @Web APIs@,}工人 @MS K3&等#.)
- 服务默认@:_共享配置@(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();
远期办法的惠益
发展经验
- 单一个命令:
dotnet run --project Mostlylucid.AppHost开始一切 - 仪表板@:_美丽的UI在 http://}@localhost@:15888}显示#:*
- 所有有生命状态的服务
- 所有服务在同一地点的日志
- 服务之间分布的跟踪
- 计量和健康检查
- 服务发现:Services 通过名称自动找到对方
- 配置配置:在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 旅程” 展示了典型的进度@:
- 7月 @2024 @ @ @ - @ 简单开始@: @ 仅此应用程序% , @ Cloudflared @ MS K2 @ and watchower
- 8月 2024 NSK1D依赖性: 添加开发@-}只提供服务
- 8月 @2024 @ -}图像光化固定: 已解析的缓存音量权限
- 11月 2024 MS K1 全堆叠“:”完全可使用 Prometheus @,+Grafana@,_Seq
- 今天今天:_Aspire 首开发选项
汲取的教训:
- 启动简单@, @ 只在需要时才添加复杂性
- 独立的dev和生产配置
- 资源限量防止一项服务杀害他人
- 用于缓存的音量堆积,可节省大量后处理时间
- 观察塔启用零@ - @ doduntime auto=-}更新时间
- 可观察性值生产资源成本
最佳做法摘要
Dockerfile 最佳做法
- 使用多QM-+Z 级构建
- 运行为非@ - @ root 用户
- 最佳缓存命令指示
- 使用特定的基底图像标记@ ( @ note
latest) - 包括健康检查
- 使用
.dockerignore排除不必要的文件 - 最小化层@(combine RUN 命令 @)
- 使用构建参数促进灵活性
Docker 合成最佳做法
- 为数据使用命名的音量
- 实施健康检查
- 使用
.env永不犯) - 界定明确的网络
- 使用
depends_on健康状况和健康条件 - 设定重新启动政策
- dev/prod 独立配置
- 生产资源限量
安保最佳做法
- 运行为非@ - @ root 用户
- 使用 chiseled / minminal base 图像
- 弱点扫描图像
- 不断更新基本图像
- Don'% t 包含图像中的秘密
- 尽可能只使用已读@-}文件系统
- 限制集装箱容量
- 使用嵌入机密或外部秘密管理器
业绩最佳做法
- 使用 buildKit 快速构建
- 利用层层缓存
- 用于缩小图像大小的 MUIM-+ZSage 建设阶段
- 使用
.dockerignore慷慨大方 - AlpineMSMK0 碎缩图像
- 用于开发的用量
- 配置适当的资源限制
- 使用健康检查进行管弦
解决共同问题
集装箱 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}
密钥外出
对于初学者来说 :
- 以 基本嵌入合成设置 @-}只是服务#3>
- 使用 @-_ 唯一的依赖关系 当地工作
- 解决共同的问题,比如 音量权限 早期
预算负责人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_:
- docker 合成器 正在启动
- 发展依赖性 - 本地 dev 设置
- 与 Docker 共享图像 - 量权限
- 此篇文章 @ -_ 深潜到生产中
相关项目 @:
- 多数情况下, - @nmt -GPU/CPU翻译服务,由多-arch建立
- Mostlylucid 博客来源 - 查看实际代码和拼写文件
记住: 最好的架构是满足您的需要而不不必要的复杂@. 启动简单, 度量 @,}当您遇到实际的瓶颈时优化 {- 想象不到的是#.
快乐的集装箱化 @! @ @ 🐳#