Back to "Dock Develop Develop Develop Develop 潜水:从基础到高级.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

Dock Develop Develop Develop Develop 潜水:从基础到高级.NET集装箱化

Sunday, 09 November 2025

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

Docker从根本上改变了我们如何建造、船舶和运行应用程序。

最初是一个简单的集装箱化工具,现已演变成一个完整的生态系统,用于现代应用开发和部署。

  1. **这是我为.NET开发商制作的Docker系列系列中的 第四篇也是最全面的文章。**如果你是Docker的新人,你可能想从以下开始:
  2. docker 合成器- 从基本的多集装箱装置开始(2024年7月)
  3. Dockcker 混音器的开发依赖- 建立当地Dev环境(2024年8月)

与 Docker 共享图像

  • **- 解决批量许可问题(2024年8月)**在这种深度潜水中, 我们将利用这些基础来探索:
  • Docker 作曲器: 运行此博客的实际堆叠
  • 依靠有限的资源进行自我托管预算部署VPS的实用优化技术
  • GPU 支持集装箱:集装箱中管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理、管理
  • 多建筑建筑建筑支持ARM64和AMD64
  • NET 9 集装箱特点:无Docker文件的内置集装箱出版

. NET 寄件者

现代.NET处理集装箱管弦的方法

说明:这是我在AI/一种花费1000美元 克洛德代码网络信用的实验的一部分。

我为这篇论文、我的理解、我不得不提出来的问题 提供了大量的资料。

这很有趣,填补了一个空白 我还没有看到填补 其他地方。

无论是使用简单的网络应用程序,还是使用GPU加速机器学习模型来设计复杂的微服务结构,本指南将您从多克基础到生产准备型的集装箱化应用,并用运行多数为lucid.com的真正实例。

  • Dockker 基本原理:了解集装箱什么是多克,真的吗?
  • **其核心是,多克是一个集装箱化平台,将您及其所有属地的应用程序包装成一个称为集装箱的标准化单位。**与使整个操作系统虚拟化的虚拟机器不同,集装箱共用主机OS内核,同时保持孤立的用户空间。

这样想吧:

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

# The container solution
"Ship your machine!" 

虚拟机

  1. :每个 VM 运行一个完整的 OS 堆叠( Linux 内核、 系统库等) - 启动速度缓慢, 重集装箱集装箱
  2. :共享主机内核、只使用软件包应用程序代码和依赖性 - 轻度和快度为何集装箱对开发者至关重要
  3. **集装箱解决了若干关键问题:**环境一致性
  4. :发展、测试和生产环境相同依赖性隔离
  5. :不再有“ DLL 地狱” 或相互矛盾的图书馆版本可复制构建

:相同的输入 = 相同的输出,每次

快速部署

# 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

:以秒而不是分钟启动容器资源使用效率

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

:在单个宿主上运行数十个集装箱

  • 基本嵌入概念图像与容器
  • 图像图像是不可改变、分层的文件系统。
  • **Dockerfile 中的每一指令都创造了一个新的层 :**这种分层法非常有力:

缓缓

:未改变的层层被再利用,加速建造共享共享共享

:多个图像可以共享基准层

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. **理解 Dockerfile 执行: 不是你的机器!**Docker 初学者常见的混乱根源:COPYDockerfile的指令不会运行在你的机器上 - 他们运行在建筑容器的OS内。ADD以下是实际发生的情况:
  2. **为什么这很重要:**关键洞察力 :RUN本地文件系统
  3. :您的
  4. 从您的机器读取命令构建图像

:您的apt-get在容器的 OS (不是你的机器) 中执行命令

输出图像

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

:最终图像包含在构建过程中创建的所有层层。

跨平台

: 您可以在 Windows 上, 建立一个 Linux 图像, 使用 Linux 命令

# 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"]

这就是为什么你可以写作

在 Windows 上的 Docker 文件命令中 - 它们不是在 Windows 上运行 !

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

他们正在Linux建筑集装箱内运行

  1. **实例混淆设想:**Docker 守护进程处理您本地文件系统与容器化构建环境之间的翻译。
  2. Dockerfile 最佳做法以下是一个可制作的.NET Dockerfile, 附带注释:.csproj理解建设流程
  3. **这是在多阶段的Docker建筑中 实际发生的事情 文件来自哪里,最终来自哪里:**来自此流的关键洞察力 :npm run buildSDK 图像丢弃
  4. : 1.5GB SDK 容器在公布后被丢弃 - 只有~ 500MB 的汇编输出向前移动: appsettings.json层层缓存wwwroot/: 复制
  5. 在源代码之前, 源代码意味着依赖性恢复被缓存, 除非依赖性改变前期资产
  6. :单独建造(通常通过复制到最后图像

配置文件

  1. 从您的机器复制的内容, 而非构建内容
  2. 最终图像:从最小运行时间图像 (~ 220MB) + 应用程序 (~ 30MB) + 资产 (~ 5MB) =~ 255MB 总计开始
  3. 仅生产文件:源代码, obj/, bin/, 节点模块/ 永远无法到达最终图像
  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 允许您定义并运行多容器应用程序 。

您没有单独管理容器,而是在YAML文档中描述您的全部应用程序堆叠 。docker run为什么是多克作曲?

考虑一个典型的.NET网络应用程序:

ASP.NET 核心网络应用程序**PostgreSQL 数据库docker-compose.yml**重新编辑缓存

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

用于伐木的Seq

  1. 也许是背景工人服务单独管理这些与app_network命令变得不易操作。
  2. **多克作曲解决了这个问题。**完整真实世界实例:制作博客平台/mnt/*
  3. 实际实际生产量运行此站点( 多数为: com) :
  4. **关键生产模式:**单一网络
  5. :所有服务简 简 简 简
  6. 捆绑山峰:主机路径(主机路径)
  7. )需要备份/存取的持久性数据命名音量.env: 由 docker 管理的数据存储, 您不需要直接访问 。

监视器标签

: 仅更新明确贴上自动更新标签的服务

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

资源限额condition: service_healthy:CPU对翻译服务的限制防止资源枯竭

外部港口测绘

# .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

:为避免与其他情况发生冲突,PostgreSQL在5266,而不是5432

环境文件文件

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

: 中的秘密:

  • 文件( 从未对 Git 承诺)
  • Dockcker 合成键功能
  • 服务依赖性
  • Docker Compose 乐团启动命令 。

缩略:

  • 需要数据库的健康检查在启动网络应用程序之前通过。
  • 环境变量和秘密
  • 用于生产机密、使用Docker秘密或外部秘密管理人员(AWS秘密经理、Azure Key Vault、HashiCorp Vault)。

命名音量与捆绑峰之比

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

services:
  web:
    networks:
      - frontend
      - backend

  db:
    networks:
      - backend  # Not exposed to frontend

命名书卷

由 docker 管理

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

集装箱重新开始时的全套永久数据

  • 可使用 Docker 命令备份/ 存储
  • 跨平台兼容兼容
  • 捆绑山峰

直接映射到主机文件系统

# 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

可用于发展(实时代码重新加载)

配置文件、日志、上传

建立网络网络网络提供孤立。

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

**在此,数据库仅供后端服务使用,不直接曝光。**健康检查

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

**健康检查允许Docker:**确定一个容器是否实际准备就绪(不是刚刚开始)

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

重新使用不健康的集装箱

向管弦乐队(Kubernetes、Docker Swararm)提供状态

常见的嵌入拼写命令

# 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

开发 与 制作作曲文件

# 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"]

与多个组成文件的单独关切 :

# 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

docker- competable. yml 转换器

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

(基数):

翻转. yml(发展-自动合并):docker- compable. prod. yml 转换器

(生产):

  • 嵌入器中 GPU 支持的 GPU 支持: 加速 ML 工作量机器学习、科学计算和视频处理应用程序往往需要加速使用GPU。
  • **Docker通过 NVIDIA 集装箱工具包支持 NVIDIA GPUs。**建立NVIDIA集装箱工具包
  • GPU- 加速加速的 Python/ PyTork 应用程序的 docker 文件GPU 运行中的 GPU 容器
  • 嵌入器合成中的 GPU真实世界示例:配有 GPU 和 CPU 构建的翻译服务

这是真实的制作例子

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:

多数为卢布- nmt

由我制作的神经机器翻译服务,

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:gpuGPU 和 CPU 变量
  • scottgal/mostlylucid-nmt:cpu- 相同的代码库,不同的基本图像
  • scottgal/mostlylucid-nmt:gpu-min多建筑建筑建筑
  • scottgal/mostlylucid-nmt:cpu-min- 支持AMM64和ARM64

优化的 docker 图像

  • - 全部和最低变式生产准备就绪
  • - 健康检查、数量持续、适当伐木GPU-加速翻译处
  • CPU- 唯一替代 CPU对于没有 GPUs 的环境,相同的服务在 CPU 上运行 :
  • 可用的图像变量 :- CUDA 12.6,有PyTorch GPU支持(~5GB)
  • - 仅使用CPU,小足足迹(~2.5GB): /health- 最小GPU建设,没有预加载模型(~4GB)/ready- 最小CPU建设(~1.5GB)
  • **关键特征:**GPU 加速 GPU 加速

:10-15x与CUDA翻译速度快模型自动下载:按需下载翻译模型

后退支援

M2M100,用于最大语言覆盖率。

量 量 持久性

# 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 .

:集装箱重新启动中的缓存模型

卫生终点

# 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

用于管弦乐队

# 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 \
  .

运行于x86_64和ARM64(苹果硅、草莓皮)

GitHub 的完整项目

# 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

对于 Dockerfile 示例, 建立脚本和 API 文档 。

#!/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

多建筑建筑和多建筑结构

现代应用程序需要在多个建筑上运行:服务器为x86_64(AMD64), Raspberry Pi 为ARM64, 苹果硅苹果Macs, 有时甚至嵌入设备为ARM32。

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

为何多建筑问题

  • 设置设置 Buildx
  • Docker Buildx 包含在 Docker 桌面中 。
  • 对于 Linux :
  • 多建筑多建筑文件
  • 大多数 Docker 文件工作时没有更改, 但这里有一些提示 :

多平台大楼

多结构化, 配有 Dockcker 混音器

不幸的是,多克·康普斯 不直接支持建筑。

变通办法:

# 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

备选方案1:预建图像

备选方案2:构建脚本.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. automatically configures these based on AppHost
builder.AddServiceDefaults();
builder.AddRedisClient("cache");
builder.AddNpgsqlDbContext<MyDbContext>("mydb");

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

真实世界实例:CI/CD管道

dotnet run --project MyDistributedApp.AppHost

用于多建筑的 GitHub Action 工作流程建设:

  • 此工作流程 :
  • 推到主标签或版本标签时触发
  • 设置用于跨平台模拟的 QEMU
  • AMM64和ARM64的建筑

自动生成标签( 部门名称、 语义版本、 SHA)

使用登记簿加速建造的缓存

  • NET 9 集装箱改进
  • .NET 9对集装箱支持作了重大改进,使得将.NET应用软件集装箱化比以往任何时候更加容易,甚至不填写Docker文件。
  • 内置集装箱出版
  • 使用.NET 9,您可以直接发布一个集装箱化应用程序:

配置容器属性

  • 添加到您的
    1. 4个。
  • 运行一切 :
  • 提醒发射:
  • 仪表板,见http://localhost:15888。

配置适当的所有服务集装箱中的Redis和PostgreSQL

在各服务处之间分配追踪

Aspirre 与 Docker 合成

# 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/

语言不可知性

以基础设施为重点的

// 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);

手动服务发现

带上你自己的观察力

委托人 :

. 具体净值以发展为重点的自动服务发现

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

内置遥测

  • 生成部署清单两者均使用
  • **Docker Compose/Kubernetes 用于生产。**部署派遣助理人员
  • **生成部署清单:**然后部署:

敏感部件预先安装的整合使添加服务变得微不足道:有限资源自我自住:实际优化

像上面那堆一样 运行一个完整的可观测堆 需要大量的资源

如果您是用 4GB 内存 或旧笔记本电脑自行托管 VPS, 这里是减少资源消耗并同时保持功能的实用策略 。

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:

仅依赖发展

  • **为了地方发展,你不需要 完整的制作堆。**缩略
  • devdeps- docker- competive. yml 组合组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式组合式方法只运行您需要的 :docker logs为何这有利于发展:
  • SMTP4Dev (SMTP4Dev):在没有真正的 SMTP 服务器的情况下测试电子邮件功能
  • 邮件greSQL:匹配生产数据库
  • 总足足足足总足足足总足足足足: 满堆 ~ 200MB RAM 与 2 - 4GB 相比 ~ 200MB RAM 和 2 - 4GB 。

充分发展依赖性指南

用于设置指令。

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

受资源制约的生产设置

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

对于预算的VPS (2-4GB RAM),优先考虑基本服务:

# Add everything
docker-compose up -d

去除什么和替代物:

诺莫米修斯/格拉法纳

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

**: 使用外部监测(更新机器人, 更好标准免费级)**无Seq

:使用基于文件的日志+

,或 Seq Cloud 无层

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

没有监视器: GitHub 行动通知的手工更新

翻译处 无翻译处

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

:在您手动启动/停止的单独的容器中按需运行

资源限额

:防止任何单项服务消耗所有内存逐步增强战略启动最小值, 按需要添加服务 :

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

**第一阶段:核心(512MB-1GB VPS)**第2阶段:增加可观察性(2GB VPS)

第3阶段:全堆(4GB+VPS)

资源优化技术 |---------|-----------------|---------------------|

  1. 目标 1. 目标 使用高山图像 节余节余节余

**:阿尔卑斯山图像小于50-70%**2. 目标

共享数据库

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

# 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

节余节余节余:在您合并的每个额外数据库中 : 400MB 内存

3 个

背景服务限制 CPU

# 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

这阻止了背景工作 让你的网络应用程序陷入饥饿

    1. 4个。
  • 持久性缓存量
  • 所包括的

与 Docker 共享图像

  • 安装缓存目录防止不必要的后处理:
  • 为什么重要docker logs:没有此功能,每个容器都重新启动所有缩略图/处理过的图像的再生。
  • 5 个
  • 使用外部服务(免费)
  • 服务 自我住址 RAM 外部替代

500MB (10GB/ month free)

普羅米修斯 + Grafana ~ 600MB ~ 格拉法纳云(免费) ~

@Ummami @~200MB @plausable(有偿)或其它地方的自我主机 @%

# 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

: 卸载可观测到的自由级, 将核心应用程序保留在您的 VPS 上 。

# Quick resource check
docker stats --no-stream

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

6 . 6 . 6 .

现需服务

翻译等不常用的服务:

节余节余节余

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

翻译服务不运行时 1-2GB 内存

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();

实际世界预算托管东道国实例

以下是每月6美元的Hetzner VPS (2 vCPU, 4GB RAM):**资源使用总额:**内存:~ 800MB(3.2GB无)

// 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;
    }
}

磁盘:~2GB

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();

CPU: <10%闲置, <50%在装载中

什么是不同的:

  1. Nometheus/Grafana(使用实时机器人+云花分析器): dotnet run --project Mostlylucid.AppHost无 Seq( 使用)
  2. **+偶发grep)**No Umami(使用云雾网络分析器 - 免费)
    • 监测站每小时而不是每5分钟检查1小时,而不是每5分钟检查1小时
    • 没有翻译服务( 需要时手动操作)
    • 预算监测
    • 如果没有Prometheus/Grafana,
  3. **健康监测:**日志监测 :
  4. **资源使用情况:**预报版本 :.NET 路径.env现在让我们用.NET Aspire重构整个堆叠

这给大家带来了 更好的.NET整合 和惊人的开发者经验。

设置 Mostlylucid 的指定任务

# 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

**首先, 创建 Aspire App 主机 :**多数为:AppHost/Program.cs:

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

委托服务默认值

创建创建 |---------|---------------|-------------| | 最难解。 服务违约项目 : | 更新最湿润/方案csA. 远期办法的惠益 | **发展经验:**单单命令 | 开始一切开始 | docker-compose up | dotnet run仪表板 | **http://localhost:15888 显示:**所有有生命状态的服务 | 所有服务在同一地点的日志 | docker logs服务之间分布的跟踪 | 计量和健康检查服务发现 | : 服务通过名称自动找到对方配置配置配置 | :集中在AppHost,不再杂耍

生产部署:

生成来自Aspire的部署清单:

  • 生成 docker 合成. yml
  • (简化):
  • Aspirre 与传统嵌入式拼写
  • 特写
  • 设置设置设置设置设置设置设置

手册YAML C#代码与Intellisense

  • 服务发现
  • 手动 env vars * 自动 *
  • 可观察性
  • 带上你自己的内建(开放遥测)
  • 发展、发展、发展、发展

**+ 仪表板 **

  • 除调调
  • 在视觉工作室中附在容器F5
  • 日志

中央化仪表板

追踪追踪

  1. **手动設定 自行分配追蹤**生产
  2. *** 直接使用YAML * 生成清单 ***学习曲线
  3. **YAML语法 C#你已经知道**何时使用 Aspire 与 Docker 合成
  4. **使用指定时间 :**大楼.NET微型服务
  5. 您想要集成调试球队对C#很满意

您需要分布式追踪文件箱外的追踪

  • 您正在部署到 Azure 集装箱 Apps( 本地支援)
  • 使用嵌入合成当 :
  • 聚球服务(Node.js、Python、Go等)
  • 团队更喜欢基础设施 as-code YAML(YAML)
  • 正在部署到任何与 Docker 兼容的主机
  • 您需要对集装箱配置进行最大控制

简单单一服务部署

双用 :

  1. 促进地方发展
  2. 生成用于生产部署的多克混音
  3. 最好的两个世界!
  4. 此博客的 Dockcker 设置的演变latest)
  5. 这个博客的Docker行程呈现出典型的进展:
  6. 2024年7月2024日 - 简单开始.dockerignore:只是应用程序,云雾和观察台
  7. 2024年8月 2024年8月 - 依赖性
  8. :增加只发展开发的服务

2024年8月 - 图像分享固定

  1. :已解决的缓存音量权限
  2. 2024年11月2024日 - 全堆叠
  3. :与普罗米修斯、格拉法纳、塞克完全保持一致.env今天今天
  4. :.NET-First Development 的附加选项
  5. 经验教训:depends_on开始简单, 仅在需要时才添加复杂性
  6. 独立的 dev 和生产配置
  7. 资源限限量防止一项服务杀害他人
  8. 用于缓存的量量增量以节省大量后处理时间

观察塔启用零停止时间自动更新

  1. 可观察性价值生产资源成本
  2. 最佳做法摘要
  3. Dockerfile 最佳做法
  4. 使用多级建筑
  5. 作为非 root 用户运行
  6. 最佳缓存命令指示
  7. 使用特定的基底图像标签( 非)
  8. 包括健康检查

使用使用

  1. 排除不必要的文件
  2. 最小化层( combine RUN 命令)
  3. 使用构建参数促进灵活性
  4. Docker 合成最佳做法.dockerignore为数据使用命名的音量
  5. 实施健康检查
  6. 使用使用
  7. 秘密的(永不秘密的)
  8. 界定明确的网络

使用使用

健康状况及健康条件

# 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 .

独立的 dev/ prod 配置

# 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

安保最佳做法

作为非 root 用户运行

使用倾斜/最小基图像

弱点扫描图像

使用使用

  • 慷慨慷慨
  • 用于较小尺寸的阿尔卑/切片图像
  • 用于开发的用量量增量
  • 配置适当的资源限制
  • 使用健康检查进行管弦

解决共同问题

  • 集装箱不会启动
  • 缓慢构建
  • 联网问题
  • 数量权限问题
  • 结论 结论 结论 结论 结论
  • Docker已从一个简单的集装箱化工具演变成一个建筑、运输和运行现代应用的综合平台。

这本指南将你们从基本原理 带到生产准备状态的部署, 并用现实世界的范例 来介绍大部分的Lucid.com。

  • 密钥外出
  • 对于初创者 :
  • 基本嵌入合成设置
    • 仅3个服务

使用使用

  • 仅依赖发展
  • 当地工作
  • 解决共同的问题,比如
  • 音量权限

早期

预算预算自控者VPS:

开始最小值 : App +数据库 + 反转代理 (~ 800MB RAM) |-------|----------|-----------|------------| | 使用高山图像和资源限制向自由级(Seq Cloud、Grafana Cloud、AuttimeRobot)卸载可观测性 | **仅按需要运行昂贵的服务(翻译、ML)**一个每月6美元的VPS可以经营一个制作博客, | **在生产部署方面:**健康检查使得能够与观察台进行零时间更新 | **独立的网络提供安保(前端/后端隔离)**备份/存取所需的数据捆绑挂载 | Docker 管理的存储库命名音量CPU/模拟限制防止资源枯竭

Cloudflare Cloudflare隧道消除了对公共IP地址的需求对于.NET 开发者 :

在.NET9内置的集装箱出版消除了用于简单应用程序的多克文件

Chiseled Ubuntu 图像提供最小攻击表面

  • NET Asprire 提供最佳当地发展经验Aspire 能够生成多克作曲用于生产部署开放遥测集成与 Aspire 自由
  • **高级使用案例:**GPU集装箱使 ML/AI 工作量能够加快10-15x速度
  • 多建筑从单一来源建立支持ARM64和AMD64的支持GitHub 动作自动化多平台构建
  • 层层的缓缓速度急剧加快了重复建设的速度旅程这个博客的Docker进化论反映了典型的进展:
  • *** 服务阶段 * * RAM使用 * 复杂 * * 服务阶段 * * RAM useage * RAM Complication ***第1阶段

第2阶段

(今天) + 占卜选项 + 变数 = 现代 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

  1. 模式模式:开始简单,一旦出现问题,就解决问题,只有在需要时才增加复杂性。
  2. 下一个是什么?取决于您的路径 :
  3. 学习嵌入:从
  4. Docker 合成基础

自我自 住

:检查

Happy containerizing! 🐳

logo

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