Back to "Docker Development Deep Sukellus: Perusasioista edistyneeseen .NET Containerization"

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

Docker Development Deep Sukellus: Perusasioista edistyneeseen .NET Containerization

Sunday, 09 November 2025

Johdanto

Docker on muuttanut perusteellisesti sitä, miten rakennamme, lähetämme ja pyöritämme sovelluksia.

Se, mikä alkoi yksinkertaisena konttityökaluna, on kehittynyt täydelliseksi ekosysteemiksi modernille sovelluskehitykselle ja käyttöönotolle.

  1. **Tämä on neljäs ja kattavin artikkeli Docker-sarjassani .NET-kehittäjille.**Jos olet uusi Dockerissa, kannattaa aloittaa:
  2. Dockerin sävellys- Aloittaminen monipakkausten perussarjoilla (heinäkuu 2024)
  3. Docker Compose -levyn kehitysriippuvuus- Paikallisten dev-ympäristöjen perustaminen (elokuu 2024)

Kuvanvahvistaja Dockerilla

  • **- Määrällisten lupa-asioiden selvittäminen (elokuu 2024)**Tässä syväsukelluksessa rakennamme noille perustuksille tutkiaksemme:
  • Tuotantovalmis Docker Composite: Varsinainen pino pyörittää tätä blogia
  • Omatoimisuus rajatuilla resursseilla: Käytännölliset optimointitekniikat VPS-budjetin käyttöönottoa varten
  • GPU-tuki: ML-kuormat konteissa
  • Moniarkkitehtuurin rakennelmat: ARM64:n ja AMD64:n tukeminen
  • .NET 9 kontin ominaisuudet: Sisäänrakennettu konttijulkaisu ilman Dockerfilejä

.NET-pyrkimys

: Nykyaikainen .net-lähestymistapa konttiorkesterissa

HUOMAUTUS: Tämä on osa kokeilujani tekoälyllä / tapa käyttää 1000 dollaria Claude Code Web -pisteitä.

Olen syöttänyt tälle BUNCH-lehden, ymmärrykseni ja kysymykseni, jotka minun oli tuotettava.

Se on hauskaa ja täyttää aukon, jota en ole nähnyt missään muualla.

Olitpa sitten ottamassa käyttöön yksinkertaisen verkkosovelluksen tai suunnittelemassa monimutkaista mikropalveluarkkitehtuuria GPU-kiihdytetyillä koneoppimismalleilla, tämä opas vie sinut Dockerin alkeista tuotantovalmiisiin sovelluksiin, joissa on todellisia esimerkkejä enimmäkseen lucid.comin pyörittämisestä.

  • Docker Fundamentals: Understanding ContainersMikä Docker oikeasti on?
  • **Sen ytimessä Docker on konttialusta, joka pakkaa sovelluksesi ja kaikki sen riippuvuudet standardoituun yksikköön, jota kutsutaan kontiksi.**Toisin kuin virtuaaliset koneet, jotka virtuaalisoivat kokonaisia käyttöjärjestelmiä, kontit jakavat isäntäjärjestelmän ytimen säilyttäen samalla eristetyt käyttötilat.

Ajattele asiaa näin:

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

# The container solution
"Ship your machine!" 

Virtuaalikoneet

  1. : Jokaisella VM:llä on täysi käyttöjärjestelmäpino (Linux-ydin, järjestelmäkirjastot jne.) - raskas ja hidas käynnistysKontit
  2. : Jaa isäntäydin, paketti vain sovelluskoodi ja riippuvuudet - kevyt ja nopeaMiksi konteilla on merkitystä kehittäjille
  3. **Kontit ratkaisevat useita kriittisiä ongelmia:**Ympäristön yhtenäisyys
  4. : Kehitys-, testaus- ja tuotantoympäristöt ovat identtisetRiippuvuuseristys
  5. Ei enää "DLL Hell" tai ristiriitaisia kirjastoversioitaToistuvia rakennelmia

: Sama tulo = sama lähtö, joka kerta

Nopea käyttöönotto

# 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

: Aloita kontit sekunneissa, ei minuuteissaResurssitehokkuus

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

: Suorita kymmeniä kontteja yhdellä kerralla

  • Olennaiset docker-käsitteetKuvat vs. kontit
  • KuvatNe ovat muuttumattomia, kerroksellisia tiedostojärjestelmiä.
  • **Jokainen Dockerfile-ohje luo uuden kerroksen:**Tämä kerros on voimakas:

Välilyöntejä

: Muuttumattomia kerroksia käytetään uudelleen, mikä nopeuttaa rakentamista

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

Jakaminen

  1. : Useilla kuvilla voi jakaa pohjakerroksiaTehokkuus
  2. : Vain vaihdetut kerrokset on ladattava/ladattavaDockerfile parhaat käytännöt
  3. **Tässä on tuotantovalmis .NET Dockerfile, jossa on kommentteja:**Keskeisiä periaatteita havainnollistettiin:
  4. Monivaiheiset rakenteet: Erilliset rakennus- ja julkaisuvaiheet pienentävät lopullista kuvakokoa dramaattisesti
  5. Tason optimointi: Kopioi riippuvuustiedostot ennen lähdekoodia parempaan välimuistiin

Turvallisuus

# 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

: Juokse ei-juurellisena käyttäjänä

Terveystarkastukset

: Konttiorkesterit voivat seurata sovellusterveyttä

Erityinen ympäristö

  • : Aseta tuotannon oletukset
  • Rakentaminen ja juokseminen
  • Dockerin sävellys: Multi-Container Orchestration
  • Docker Compose -ohjelmiston avulla voit määritellä ja pyörittää monipakkaussovelluksia.
  • Sen sijaan, että hallinnoisit kontteja yksilöllisesti, kuvaat koko hakemuspinon YAML-tiedostossa.

Miksi dokkari säveltää?docker runHarkitse tyypillistä .NET-verkkosovellusta:

ASP.NET Core -verkkosovellus

PostgreSQL-tietokanta**Uusi välimuistidocker-compose.yml**Seq puunkorjuuta varten

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

Ehkä taustatyöntekijän palvelu

  1. Yksittäin hallinnoiminenkäskyistä tulee kankeita.app_networkDocker Compose ratkaisee tämän.
  2. Complete Real-World Example: Production Blog PlatformTässä on/mnt/*Todellinen tuotanto
  3. **joka pyörittää juuri tätä sivustoa (useimmitenlucid.com):**Avaintuotantomallit:
  4. Yhtenäinen verkko: Kaikki palvelut
  5. yksinkertaisuuden puolestaRinnakkaiskiinnikkeet
  6. : Hosting-polut () Pysyvien tietojen varmuuskopiointi/käyttö
  7. Nimetyt volyymit: Docker-hallittu tietojen tallennus, johon ei tarvita suoraa pääsyä.envVartiotornin tarroja

: Vain päivityspalvelut, jotka on nimenomaisesti merkitty automaattiseksi päivitykseksi

Resurssirajat

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

: Käännöspalveluun liittyvät prosessorirajoitukset estävät resurssien nälänhädäncondition: service_healthyUlkoinen satamakartoitus

: PostgreSQL 5266:ssa 5432:n sijaan, jotta vältyttäisiin ristiriidoilta muiden tapausten kanssa

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

Ympäristötiedostot

: Salaisuudet in

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

Tiedosto (ei koskaan sitoutunut gittiin):

  • Dockerin pääpiirteet
  • Palvelun riippuvuus
  • Docker Composite orkestroi startup-tilauksen.
  • Erytropoietiini

edellyttää, että tietokannan terveystarkastus läpäisee ennen verkkosovelluksen käynnistämistä.:

  • Ympäristömuuttujat ja -salaisuudet
  • Tuotantosalaisuuksiin käytetään Docker Secretsiä tai ulkopuolisia salaisia johtajia (AWS Secrets Manager, Azure Key Vault, HashiCorp Vault).
  • Nimetyt tilavuudet vs. kiinnikkeet

Nimetyt määrät

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

services:
  web:
    networks:
      - frontend
      - backend

  db:
    networks:
      - backend  # Not exposed to frontend

Dockerin hallinnoima

Sinnikkäät tiedot konteista käynnistyvät uudelleen

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

Voidaan varmuuskopioida/palauttaa Docker-komennuksilla

  • Liitännät yhteensopivat
  • Rinnakkaiskiinnikkeet
  • Suorakartoitus isäntätiedostojärjestelmään

Hyödyllistä kehitykselle (elävän koodin uudelleenlataus)

# 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

Asetukset-tiedostot, lokit, lataukset

Verkottuminen

**Verkot tarjoavat eristyneisyyttä.**Täällä tietokanta on saatavilla vain taustapalveluille, ei suoraan.

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

TerveystarkastuksetTerveystarkastusten perusteella Docker voi

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

**Määrittele, onko kontti todella valmis (ei vain käynnistynyt)**Aloita epäterveelliset kontit uudelleen

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

Anna status orkesterille (Kubernetes, Docker Swarm)

Yleiset dokkarin komennot

Kehitys vs Production Composite -tiedostot

# 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

Erilliset huolet useista koostetiedostoista:

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

docker-compose.yml

# 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

(pohja):

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

Docker-compose.override.yml

(kehittäminen – automaattisesti sulautettuna):docker-compose.prod.yml(tuotanto):

GPU-tuki Dockerissa: ML-työlatausten nopeuttaminen

  • **Koneoppiminen, tieteellinen tietojenkäsittely ja videonkäsittelysovellukset vaativat usein GPU-kiihdytystä.**Docker tukee NVIDIA GPU:ta NVIDIA Container Toolkitin kautta.
  • NVIDIA-konttipakkausten asennusGPU-kiihdytetyn Python/PyTorch-sovelluksen Docker-tiedosto
  • Käytössä olevat GPU-kontitGPU Dockerin kokoonpanossa
  • Real-World Example: Käännöspalvelu GPU:lla ja CPU:llaTässä on todellinen tuotantoesimerkki

enimmäkseen lusid-nmt

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:

, neurokonekäännöspalvelu, jonka rakensin tähän blogiin automaattikäännöksen.

Hanke osoittaa:

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:

GPU- ja CPU-variantit

  • scottgal/mostlylucid-nmt:gpu- Sama koodipohja, eri pohjakuvat
  • scottgal/mostlylucid-nmt:cpuMoniarkkitehtuurin rakennelmat
  • scottgal/mostlylucid-nmt:gpu-min- Tukee AMD64:ää ja ARM64:ää
  • scottgal/mostlylucid-nmt:cpu-minOptimoidut Docker-kuvat

- Täydet ja minimaaliset vaihtoehdot

  • Tuotantovalmiit- Terveystarkastukset, äänenvoimakkuuden pysyvyys, asianmukainen puunkorjuu
  • GPU-kiihdytetty käännöspalveluCPU-Vain vaihtoehto
  • **Ympäristöissä, joissa ei ole GPU:ita, sama palvelu toimii suorittimella:**Saatavilla olevat kuvaversiot:
  • - CUDA 12.6, jolla on PyTorch GPU -tuki (~5GB)- Vain prosessori, pienempi jalanjälki (~2.5GB)
  • - Minimaalinen GPU-rakenne, ei esiladattuja malleja (~4GB): /health- Minimaalinen prosessorirakenne (~1,5GB)/readyTärkeimmät ominaisuudet:
  • GPU-kiihdytys: 10-15x nopeampaa käännöstä CUDA:lla

Mallin automaattinen lataaminen: Lataukset käännösmallit tilauksestaVaratuki

: Tries Opus-MT → mBART50 → M2M100 mahdollisimman kattavalle kielelle

Volyymin pysyvyys

: Cache-mallit kontissa käynnistyvät uudelleen

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

Terveyden loppupäätteitä

sekä

# 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

orkesterille

Moniarkkitehtuuri

# 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

: Runs on x86_64 ja ARM64 (Apple Silicon, Vadelma Pi)

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

Katso

GitHubilla täysi projekti

Dockerfile-esimerkeille rakenna skriptejä ja API-dokumentaatioita.

# 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

Moniarkkitehtuuri rakentaa Docker Buildexilla

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

Nykyajan sovelluksia on käytettävä useissa eri sarjoissa: x86_64 (AMD64) palvelimille, ARM64 Vadelma Piille ja Apple Silicon Maceille, joskus jopa ARM32 sulautetuille laitteille.

Miksi moniarkkitehtisuus on tärkeää

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

Asetetaan buildxia

  • Docker Buildex on mukana Docker Desktopissa.
  • Linuxille:
  • Multi-Architecture Dockerfile
  • Useimmat Dockerfiles-tiedostot toimivat ilman muutoksia, mutta tässä muutamia vinkkejä:
  • Rakentaminen useille alustoille

Moniarkkitehtuuri Docker Compose -levyllä

Valitettavasti Docker Composite ei suoraan tue bundexia.

Työskentelyt:

Vaihtoehto 1: Esirakentamiskuvat

# 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

Vaihtoehto 2: Koosta skripti

Reaalimaailman esimerkki: CI/CD-putkisto.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>

Moniarkkitehtuurin GitHub-toiminnon työnkulku rakentuu:

dotnet publish -p:PublishProfile=DefaultContainer

Tämä työnkulku:

  1. Liittää pää- tai versiotallenteisiinAsettaa QEMU:n cross-platform-emulointiin
  2. Rakentaa AMD64:lle ja ARM64:lleLuo tunnisteet automaattisesti (sivunimi, semanttiset versiot, SHA)
  3. Käyttää rekisteriä välimuistina nopeammille rakennuksille.NET 9 Konttien parannustyöt
  4. **.NET 9 tuo konttitukeen merkittäviä parannuksia, mikä helpottaa .net-sovellusten pakkaamista ilman edes Dockerfileä.**Sisäänrakennettu konttikustantamo
  5. **.NET 9 -verkolla voit julkaista suljetun hakemuksen suoraan:**Kontin ominaisuuksien määrittely

Lisää ruutuusi

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

Julkaistaan sitten:

  • Sisäänrakennetun konttituen edutDocker-tiedostoa ei tarvita
  • : Vähentää monimutkaisuuttaOptimoidut kuvat
  • : Microsoft virittää kuvat suoritukseenJohdonmukainen

: Vakiokuvat kaikissa .net-sovelluksissa

Turvallisuus

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

: Automatisoitu pohjakuvapäivitys

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

Pienempiä kuvia

: Trimmingin ja AOT:n kokoelmatuki

Pienten kuvien karsinta ja AOT

  • Tulokset:
  • Standardi
  • ~220MB
  • joissa on trimmaus

~110MB

  • AOT:n kanssa
  • ~12MB yksinkertaisiin sovelluksiin!
  • Vertailu: Dockerfile vs sisäänrakennettu
  • Perinteinen Dockerfile-lähestymistapa:

Sisäänrakennettu konttilähestymistapa:

Molemmat tuottavat samanlaisia kuvia, mutta sisäänrakennettu lähestymistapa on yksinkertaisempi ja huollettavampi.

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

Milloin Dockerfileä käytetään vastaan sisäänrakennettu

  • **Käytä Dockerfileä, kun:**Kuvaa pitää hallita täysin.
  • Asennusjärjestelmän riippuvuudetMonivaiheiset monimutkaiset rakennelmat
  • Peruskuvat, jotka eivät ole normaalejaKäytä sisäänrakennettua, kun:

Standardi .NET-verkko/konsolisovellukset

  • Haluat yksinkertaisuutta
  • Microsoftin optimointien velkaantuminen

Nopea prototyypitys

Ripoteltuja Ubuntu-kuvia

.NET 9 tukee "piristettyjä" Ubuntu-kuvia - ultraminimaaliset pohjakuvat:

Hyödyt:

Pieni

  1. : ~50 % pienempi kuin tavalliset kuvatTurvallinen
  2. **: Minimaalinen hyökkäyspinta (ei pakettihallintaa, shell)**Nopea
  3. : Nopeammat vedot ja lähdötVastoinkäymiset:
  4. **Ei simpukkaa (kovempaa vianetsintään)**Rajalliset järjestelmähyödykkeet
  5. **Täydellinen tuotantoon, jossa turvallisuus ja koko ovat tärkeimpiä.**Johdatus .NET-hakuun

.NET Aspire on mielipiteellinen, pilvinen pino jaettujen sovellusten rakentamiseen.

Ajattele, että Docker Composite on steroideja, jotka on erityisesti suunniteltu .NET-mikropalveluihin.

  1. **Mitä tavoitteleminen on?**Tavoitteena on:
  2. Orkesteri: Suorita ja yhdistä useita palveluja paikallisesti
  3. Palvelun löytäminen: Palvelut löytävät toisensa automaattisesti

Telemetria

: Sisäänrakennettu puunkorjuu, metrit, jäljitys

dotnet new aspire-starter -n MyDistributedApp
cd MyDistributedApp

Komponentit

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

Esiasetetut integraatiot (Redis, PostgreSQL, RabbitMQ jne.)

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

// Aspireing
3.  Multi-stage builds to reduce image size
4.  Use `.dockerignore` generously
5.  Alpine/chiseled images for smaller size
6.  Use volume mounts for development
7.  Configure appropriate resource limits
8.  Use health checks for orchestration

## Troubleshooting Common Issues

### Container Won't Start

```bash
# 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

Käyttöönotto

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

: Luo Kubernetes/Docker Composite -luettelo

# 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

Pyri arkkitehtuuriin

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

Aspire-ratkaisussa on kolme projektityyppiä:

Sovelluspalvelin

  • : Järjestää palveluksiasiPalveluhankkeet
  • **: Varsinaiset palvelusi (Web-rajapinnat, työntekijät jne.)**Palvelun oletukset
  • **: Yhteinen kokoonpano (loggaus, terveystarkastukset jne.)**Pikainen esimerkki
  • 1 TäysosumaLuo Aspire-projekti:
  • **2.**App Host (MyDistributedApp.AppHost/Program.cs):
  • **3.**Käyttö palveluksessasi:

Hidas rakentaa

Verkkokysymyksiä

Happy containerizing! 🐳 Rakennussovellukset

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

: Leverage Docker Compose monen palvelun orkestrointiin

  • Nopeutetaan ML:ää: Valjasta GPU:n tuki laskentaintensiivisille työtahdille
  • Käynnissä oleva moniplanaatti: Käytä buildxia ARM- ja AMD64-yhteensopivuuteen
  • Yksinkertaistetaan .NET-verkkoa: Syleile sisäänrakennettuja kontteja

Rakennusmikropalvelut: Tutki .NET Havittele jaettuja sovelluksiaKonttiekosysteemi tarjoaa työkaluja jokaiseen skenaarioon.

Aloita yksinkertaisesta, iteroivasta ja omaksu edistyneitä ominaisuuksia vähitellen tarpeidesi kasvaessa.

Lisäresurssit

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:

Dockerin dokumentointi

  • Dockerin sävellysreferenssi.NET Container Images
  • .NET:n tavoitedokumentaatioNVIDIA Container Toolkitdocker logsDocker Buildex
  • **ch pyörittää vain sitä, mitä tarvitsee:**Miksi tämä toimii kehityksen hyväksi:
  • SMTP4Dev: Testaa sähköpostin toimivuus ilman todellista SMTP-palvelinta
  • PostgreSQL: Vastaa tuotantotietokantaa

Kokonaisjalanjälki

: ~200MB RAM vs 2-4GB täyteen pinoon

Katso

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

täyden kehityksen riippuvuusoppaat

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

asennusohjeita varten.

# Add everything
docker-compose up -d

Resurssien hillitsemä tuotantoasetelma

Budjetti VPS:lle (2-4GB RAM) priorisoi olennaiset palvelut:

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

**Mitä on poistettu ja vaihtoehtoja:**Ei Prometheus/Grafanaa

: Käytä ulkoista seurantaa (UptimeRobot, BetterStack Free Tier)

Ei Seqia

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

: Käytä tiedostopohjaista kirjausta +, tai Seq Cloud Free -tason

Ei Vartiotornia

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

: Manuaalinen päivitys GitHub-toimintoilmoituksilla

Ei käännöspalvelua

: Suorita tilauksesta erillisessä astiassa, jonka käynnistät/pysäytät manuaalisestiResurssirajat: Estä yhtäkään palvelua kuluttamasta kaikkea muistia

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

Progressiivinen tehostamisstrategiaAloita minimaalisesti, lisää palveluita tarpeen mukaan:

Vaihe 1: Core (512MB-1GB VPS)

Vaihe 2: Lisää havaintokyky (2GB VPS) |---------|-----------------|---------------------| Vaihe 3: Full Stack (4GB+ VPS) Resurssien optimointitekniikat 1 Täysosuma

Käytä alppikuviaSäästöt

: Alppikuvat ovat 50-70 prosenttia pienempiä

# 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

Jaettu tietokantaSen sijaan, että käytössä olisi yksi tietokanta per palvelu, käytä yhtä PostgreSQL-instanssia, jossa on useita tietokantoja:

Säästöt

: 400MB RAM/lisää tietokantaa kokoat

# 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

3.

  • Rajaussuoritin taustapalveluille
  • Tämä estää taustatyöpaikkoja näkemästä nälkää verkkosovelluksessasi.
  • Nelonen

Jatkuvat välimuistin volyymit

  • Kuten on esitetty
  • Kuvanvahvistaja Dockerilladocker logsAsentavat kätköhakemistot estävät tarpeettoman uudelleenkäsittelyn:
  • Miksi sillä on väliä?
  • : Ilman tätä jokainen kontti käynnistää uudelleen kaikki kuvakynnet/jalostetut kuvat.

Käytä ulkoisia palveluja (free Tiers)

Palvelu Omatoiminen RAM Ulkoinen vaihtoehto

Seq ~500MB Seq Cloud (10GB/kk ilmaiseksi)

# 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

Prometheus + Grafana ~600MB Grafana Cloud (vapaa taso)

# 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

Umami ~200MB Todennäköinen (palkallinen) tai itsekeskeinen muualla

# Quick resource check
docker stats --no-stream

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

Strategia

: Poista havainnointi vapaalle tasolle, pidä ydinsovellus VPS:ssä.

6.

On-demand-palvelut

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

Harvoin käytetyt palvelut, kuten kääntäminen:

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

Säästöt

: 1-2GB RAM kun käännöspalvelu ei toimiReaalimaailman budjetin isäntäesimerkkiTässä on 6 dollarin kuukausipalkkainen Hetzner VPS (2 vCPU, 4GB RAM):

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

Resurssien kokonaiskäyttö:

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

RAM: ~800MB (jättää 3,2GB ilmaiseksi)

Levy: ~2GB

  1. Suoritin: <10 % joutokäynnillä, <50 % kuormitettuna: dotnet run --project Mostlylucid.AppHostMikä on toisin:
  2. **Ei Prometheus/Grafanaa (käytä UptimeRobottia + Cloudflare Analyticsia)**Ei Seqiä (käytä
      • satunnaiset grepit)
    • Ei Umamia (käytä Cloudflare Web Analyticsia – ilmaiseksi)
    • Vartiotornin tarkistus tunnin välein viiden minuutin välein
    • Ei käännöspalvelua (käytä tarvittaessa manuaalisesti)
  3. Talousarvion seurantaIlman Prometheusta/Grafanaa käytä seuraavia ilmaisia vaihtoehtoja:
  4. **Terveyden seuranta:**Lokin seuranta:.envResurssien käyttö:

Aspire-versio: The .NET Way

Nyt reimagoidaan koko pino uudelleen .NET Aspire -palvelun avulla.

# 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

**Tämä antaa sinulle kaikki orkestrointiedut paremmalla .NET-integraatiolla ja hämmästyttävällä kehittäjäkokemuksella.**Enimmäkseen havittelemista

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

Luo ensin Aspire-sovelluksen isäntä:

Enimmäkseen lucid.AppHost/Program.cs: |---------|---------------|-------------| | Havittele palvelun oletuksiaLuo | Enimmäkseen lucid.ServiceDefaultsprojekti: | Päivitä Enimmäkseenlucid/Program.csPyrinnän edut | Kehityskokemus: | docker-compose up | dotnet runYksi komento | aloittaa kaikenKojelauta | : Kaunis käyttöliittymä osoitteessa http://localhost:1588, josta käy ilmi: | docker logsKaikki palvelut, joilla on live-status | Lokit kaikista palveluista samassa paikassaHajautetut jäljet eri palveluissa | Lääkintä ja terveystarkastuksetPalvelun löytäminen | : Palvelut löytävät toisensa automaattisesti nimien kauttaAsetukset

: Keskitetty AppHostiin, ei enää

jongleeraus

  • Tuotannon käyttöönotto:
  • Luo käyttöönoton manifestit Asposta:
  • Luotu docker-compose.yml
  • (yksinkertaistettu):
  • Pyri vastaan perinteinen docker-sävellys

Aihe: Dockerin sävellys .NET Tähtää

  • Asetukset
  • Manuaalinen YAML C#-koodi ja IntelliSense-koodi
  • Palvelun löytäminen
  • Manual env vars Automatic
  • Havainnointikelpoisuus

Tuo oma sisäänrakennettu (OpenTelemetria)

  • Kehitys
    • Dashboard
  • Vianetsintä

Liitä konttiin F5 Visual Studiossa

Lokit

  1. **Keskitetty kojelauta**Jäljitys
  2. **Asetukset manuaalisesti Automaattinen hajautettu jäljitys**Tuotanto
  3. **Käytä YAML:ää suoraan Luo manifestit**Opettele kurveja
  4. **YAML syntaksi C# tiedät jo**Milloin käyttää aspiraatiota docker-sävellystä vastaan
  5. **Käytä aspiraatiota, kun:**Rakentaminen .NET-mikropalvelut

Haluatko integroitua vianetsintää

  • Joukkue viihtyy C#:n kanssa
  • Tarvitset jaetun jäljityksen laatikon ulkopuolelta
  • Olet ottamassa käyttöön Azure Container Apps (natiivituki)
  • Käytä Docker Composite -valmistetta, kun:
  • Polyglot-palvelut (Node.js, Python, Go jne.)
  • Joukkue suosii infrastruktuuria koodina YAML

Deploying any Docker-yhteensopiva isäntä

Konttien kokoonpanoa on ohjattava maksimaalisesti

  1. Yksinkertaiset yhden palvelun käyttöönotot
  2. Käytä molempia:
  3. Paikallisen kehityksen tavoittelu
  4. Luo Docker Composite tuotannon käyttöönottoa vartenlatest)
  5. Molemmista maailmoista parhaat!
  6. Tämän blogin docker-asetelman kehitys.dockerignoreTämän blogin Docker-matka kertoo tyypillisestä etenemisestä:
  7. Heinäkuu 2024 - yksinkertainen alku
  8. : Vain sovellus, Cloudflared ja Vartiotorni

Elokuu 2024 - Haitat

  1. : Lisättäviä vain kehittämispalveluja
  2. Elokuu 2024 - ImageSharp Fix
  3. : ratkaistuja äänenvoimakkuusoikeuksia välimuistiin.envMarraskuu 2024 - Full Stack
  4. : Täydellinen havaintokyky Prometheuksella, Grafanalla, Seqillä
  5. Tänäändepends_on: Havittele vaihtoehtoa . NET-ensikehitykselle
  6. Havaintoja ja haasteita
  7. Aloita yksinkertainen, lisää monimutkaisuutta vain tarvittaessa
  8. Erilliset dev- ja tuotantokokoonpanot

Resurssirajat estävät yhden palvelun tappamisen

  1. Välimuistien äänenvoimakkuuden kiinnitykset säästävät merkittävää uudelleenkäsittelyaikaa
  2. Vartiotorni mahdollistaa nolla- pois päältä -ajan automaattisen päivityksen
  3. Havainnointi on tuotannon resurssikustannusten arvoista
  4. Parhaiden käytäntöjen yhteenveto
  5. Dockerfile parhaat käytännöt
  6. Käytä monivaiheisia rakennelmia
  7. Suorita non-root-käyttäjänä
  8. Tilausohjeet optimaaliseen välilyönteihin

Käytä erityisiä pohjakuvatunnisteita (ei

  1. Sisällytä terveystarkastukset
  2. Käyttö
  3. tarpeettomien tiedostojen poissulkeminen
  4. Minimoi kerrokset (komenna RUN-komentoja).dockerignoreKäytä joustavuuteen rakentavia argumentteja
  5. Docker sävelsi parhaat käytännöt
  6. Käytä dataan nimettyjä määriä
  7. Toteuta terveystarkastukset
  8. Käyttö

salaisuudet (ei koskaan sitoudu)

Määrittele tarkat verkostot

# 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

Käyttö

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

joilla on terveysongelmia

# 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

Aseta uudelleenkäynnistyksen toimintatavat

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

Erilliset dev/prod-konfiguraatiot

Resurssirajat tuotannossa

Turvallisuuden parhaat käytännöt

Suorita non-root-käyttäjänä

Vivutuskerros välimuistina

  • Monivaiheiset rakenteet pienentävät kuvan kokoa
  • Käyttö
  • avokätisesti
  • Pienemmän kokoisia alppi- ja hilsekuvia
  • Käytä äänenvoimakkuuden liittimiä kehittämiseen

Määrittele asianmukaiset resurssirajat

  • Käytä terveystarkastuksia orkestrointiin
  • Yhteisiä ongelmia
  • Kontti ei käynnisty
  • Hidas rakentaa
  • Verkkokysymyksiä
  • Volume licence issues

Päätelmät

  • Docker on kehittynyt yksinkertaisesta konttityökalusta kokonaisvaltaiseksi alustaksi nykyaikaisten sovellusten rakentamiseen, toimitukseen ja käyttöön.
  • Tämä opas on vienyt sinut perusasioista tuotantovalmiisiin, tosimaailman esimerkein lähinnälucid.comin pyörittämisestä.
  • Tärkeimmät takeawayt
  • Aloittelijoille:
  • Aloita

perus Docker Composite setup

    • vain kolme palvelua
  • Käyttö
  • kehitys- ja riippuvuussuhteet
  • paikalliselle työlle

Ratkaise yhteisiä asioita, kuten

äänenvoimakkuusoikeudet

varhain |-------|----------|-----------|------------| | **Budjetti VPS:n omatoimiset kannattajat:**Aloita minimaalisesti: Sovellus + Tietokanta + Käänteinen Proxy (~800MB RAM) | Käytä alppikuvia ja resurssirajojaPoista havainnointi vapaatasoille (Seq Cloud, Grafana Cloud, UptimeRobot) | Suorita kalliita palveluja (kääntäminen, ML) vain tilauksestaKuuden dollarin kuukausipalkalla VPS voi pyörittää tuotantoblogia, jossa on tilaa | **Tuotannon käyttöönotot:**Terveystarkastukset mahdollistavat nolla-ajan päivitykset Vartiotornilla | **Erilliset verkot tarjoavat turvallisuutta (etu-/tausta-eristys)**Band-kiinnikkeet dataa varten, joita tarvitset varmuuskopiointiin/lukitukseen

Dockerin hallinnoiman varaston nimetty määräCPU:n/muistin rajat estävät resurssien nälänhädän

Cloudflaren tunneli poistaa julkisten IP-osoitteiden tarpeen

.NET-kehittäjille:

  • Sisäänrakennettu konttijulkaisu .NET 9 poistaa Docker-tiedostot yksinkertaisista sovelluksistaTaotut Ubuntu-kuvat tarjoavat minimaalisen hyökkäyspinnan.NET Aspire tarjoaa parhaan luokan paikallisen kehityskokemuksen
  • Aspire voi tuottaa Docker Composea tuotannon käyttöönottoa vartenOpenTelemetria-integraatio tulee ilmaiseksi Aspirella
  • **Advanced Use -tapauksissa:**GPU-kontit mahdollistavat ML/AI-kuormat 10-15x-kiihdytyksellä
  • Moniarkkitehtuuri rakentaa tuen ARM64:lle ja AMD64:lle yhdestä lähteestäGitHub-toiminnot automatisoivat monialustan rakenteetTasovälitys nopeuttaa rajusti toistuvia rakennelmia
  • MatkaTämän blogin Dockerin evoluutio heijastaa tyypillistä kehitystä:

Lavan palvelut RAM-muistin käyttö Monimutkaisuus

Vaihe 1

(marras 2024) Täysi havainnoitavuus ~3,5GB tuotanto

  1. Vaihe 5(Tänään) + Pyri vaihtoehto Muuttuja Moderni
  2. Kaava: Aloita yksinkertainen, ratkaise ongelmia niiden ilmetessä, lisää monimutkaisuutta vain tarvittaessa.
  3. Mitä seuraavaksi?Riippuen polustasi:
  4. Opettele dokkaria

: Aloita

: Tutustu .NET-hakuun

Happy containerizing! 🐳

logo

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