# Docker Development Deep Sukellus: Perusasioista edistyneeseen .NET Containerization

<datetime class="hidden">2025-11-09T14:00</datetime>

<!--category-- Docker, .NET, DevOps, Containers -->
## 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.](/dockercompose)**Jos olet uusi Dockerissa, kannattaa aloittaa:
2. **[Dockerin sävellys](/dockercomposedevdeps)**- Aloittaminen monipakkausten perussarjoilla (heinäkuu 2024)
3. **[Docker Compose -levyn kehitysriippuvuus](/imagesharpwithdocker)**- 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

[TOC]

## 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 Containers**Mikä 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:

```bash
# 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äynnistys**Kontit
2. **: Jaa isäntäydin, paketti vain sovelluskoodi ja riippuvuudet - kevyt ja nopea**Miksi konteilla on merkitystä kehittäjille
3. **Kontit ratkaisevat useita kriittisiä ongelmia:**Ympäristön yhtenäisyys
4. **: Kehitys-, testaus- ja tuotantoympäristöt ovat identtiset**Riippuvuuseristys
5. **Ei enää "DLL Hell" tai ristiriitaisia kirjastoversioita**Toistuvia rakennelmia

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

#### Nopea käyttöönotto

```bash
# 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 minuuteissa**Resurssitehokkuus

```dockerfile
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äsitteet**Kuvat vs. kontit
- **Kuvat**Ne 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

```dockerfile
# 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 pohjakerroksia**Tehokkuus
2. **: Vain vaihdetut kerrokset on ladattava/ladattava**Dockerfile 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

```bash
# 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 run`Harkitse tyypillistä .NET-verkkosovellusta:

### ASP.NET Core -verkkosovellus

PostgreSQL-tietokanta**Uusi välimuisti`docker-compose.yml`**Seq puunkorjuuta varten

```yaml
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 hallinnoiminen**käskyistä tulee kankeita.`app_network`Docker Compose ratkaisee tämän.
2. **Complete Real-World Example: Production Blog Platform**Tässä on`/mnt/*`Todellinen tuotanto
3. **joka pyörittää juuri tätä sivustoa (useimmitenlucid.com):**Avaintuotantomallit:
4. **Yhtenäinen verkko**: Kaikki palvelut
5. **yksinkertaisuuden puolesta**Rinnakkaiskiinnikkeet
6. **: Hosting-polut (**) Pysyvien tietojen varmuuskopiointi/käyttö
7. **Nimetyt volyymit**: Docker-hallittu tietojen tallennus, johon ei tarvita suoraa pääsyä`.env`Vartiotornin tarroja

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

#### Resurssirajat

```yaml
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än`condition: service_healthy`Ulkoinen satamakartoitus

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

```bash
# .env file (never commit to git!)
DB_PASSWORD=super_secret_password
SMTP_PASSWORD=another_secret
```

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

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

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

```yaml
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)

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

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

**Terveystarkastukset**Terveystarkastusten perusteella Docker voi

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

```yaml
services:
  web:
    image: registry.example.com/myapp:${VERSION}
    restart: always
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '2'
          memory: 2G
```

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

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

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

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

```yaml
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](https://github.com/scottgal/mostlylucid-nmt)(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 asennus**GPU-kiihdytetyn Python/PyTorch-sovelluksen Docker-tiedosto
- **Käytössä olevat GPU-kontit**GPU Dockerin kokoonpanossa
- **Real-World Example: Käännöspalvelu GPU:lla ja CPU:lla**Tässä on todellinen tuotantoesimerkki

#### enimmäkseen lusid-nmt

```yaml
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:

```yaml
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:cpu`Moniarkkitehtuurin rakennelmat
- `scottgal/mostlylucid-nmt:gpu-min`- Tukee AMD64:ää ja ARM64:ää
- `scottgal/mostlylucid-nmt:cpu-min`Optimoidut Docker-kuvat

**- Täydet ja minimaaliset vaihtoehdot**

- **Tuotantovalmiit**- Terveystarkastukset, äänenvoimakkuuden pysyvyys, asianmukainen puunkorjuu
- **GPU-kiihdytetty käännöspalvelu**CPU-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)`/ready`Tärkeimmät ominaisuudet:
- **GPU-kiihdytys**: 10-15x nopeampaa käännöstä CUDA:lla

Mallin automaattinen lataaminen[: Lataukset käännösmallit tilauksesta](https://github.com/scottgal/mostlylucid-nmt)Varatuki

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

Volyymin pysyvyys

### : Cache-mallit kontissa käynnistyvät uudelleen

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

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

```dockerfile
# 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)

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

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

# Then use in compose
```

```yaml
services:
  web:
    image: myapp:latest  # Already built for multiple architectures
```

**Moniarkkitehtuuri rakentaa Docker Buildexilla**

```bash
#!/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ää

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

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

```xml
<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:

```bash
dotnet publish -p:PublishProfile=DefaultContainer
```

### Tämä työnkulku:

1. **Liittää pää- tai versiotallenteisiin**Asettaa QEMU:n cross-platform-emulointiin
2. **Rakentaa AMD64:lle ja ARM64:lle**Luo 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

```xml
<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 edut**Docker-tiedostoa ei tarvita
- **: Vähentää monimutkaisuutta**Optimoidut kuvat
- **: Microsoft virittää kuvat suoritukseen**Johdonmukainen

### : Vakiokuvat kaikissa .net-sovelluksissa

**Turvallisuus**

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

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

**: Automatisoitu pohjakuvapäivitys**

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

```xml
<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 riippuvuudet**Monivaiheiset monimutkaiset rakennelmat
- **Peruskuvat, jotka eivät ole normaaleja**Kä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 kuvat**Turvallinen
2. **: Minimaalinen hyökkäyspinta (ei pakettihallintaa, shell)**Nopea
3. **: Nopeammat vedot ja lähdöt**Vastoinkä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**

```bash
dotnet new aspire-starter -n MyDistributedApp
cd MyDistributedApp
```

**Komponentit**

```csharp
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.)**

```csharp
// 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

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

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

```bash
# 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ää palveluksiasi**Palveluhankkeet
- **: Varsinaiset palvelusi (Web-rajapinnat, työntekijät jne.)**Palvelun oletukset
- **: Yhteinen kokoonpano (loggaus, terveystarkastukset jne.)**Pikainen esimerkki
- **1 Täysosuma**Luo Aspire-projekti:
- **2.**App Host (MyDistributedApp.AppHost/Program.cs):
- **3.**Käyttö palveluksessasi:

Hidas rakentaa

### Verkkokysymyksiä

- [Volume licence issues](https://docs.docker.com/)
- [Päätelmät](https://docs.docker.com/compose/compose-file/)
- [Docker on kehittynyt yksinkertaisesta konttityökalusta kokonaisvaltaiseksi alustaksi nykyaikaisten sovellusten rakentamiseen, toimitukseen ja käyttöön.](https://github.com/dotnet/dotnet-docker)
- [Oletpa sitten:](https://learn.microsoft.com/en-us/dotnet/aspire/)
- [Aloittaminen](https://github.com/NVIDIA/nvidia-container-toolkit)
- [: Master Dockerfile perusasiat ja konttiperusasiat](https://github.com/docker/buildx)

Happy containerizing! 🐳
Rakennussovellukset

```yaml
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 sovelluksia](/dockercomposedevdeps)Konttiekosysteemi tarjoaa työkaluja jokaiseen skenaarioon.

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

Lisäresurssit

```yaml
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 tavoitedokumentaatio**NVIDIA Container Toolkit`docker logs`Docker 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**

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

**täyden kehityksen riippuvuusoppaat**

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

**asennusohjeita varten.**

```bash
# Add everything
docker-compose up -d
```

### Resurssien hillitsemä tuotantoasetelma

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

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

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

```yaml
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 manuaalisesti[Resurssirajat](/imagesharpwithdocker): Estä yhtäkään palvelua kuluttamasta kaikkea muistia

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

**Progressiivinen tehostamisstrategia**Aloita 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ä alppikuvia**Säästöt

#### : Alppikuvat ovat 50-70 prosenttia pienempiä

2.

```bash
# 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 tietokanta**Sen 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

```yaml
# 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 Dockerilla`docker logs`Asentavat 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.
- 5.

### Käytä ulkoisia palveluja (free Tiers)

Palvelu Omatoiminen RAM Ulkoinen vaihtoehto

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

```bash
# Simple health check script
#!/bin/bash
while true; do
  curl -f http://localhost/healthz || echo "Health check failed!" | mail -s "Alert" you@example.com
  sleep 300
done
```

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

```bash
# 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" you@example.com
done
```

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

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

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

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

```csharp
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 toimi**Reaalimaailman budjetin isäntäesimerkki**Tässä on 6 dollarin kuukausipalkkainen Hetzner VPS (2 vCPU, 4GB RAM):

```csharp
// 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ö:

```csharp
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.AppHost`Mikä 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 seuranta**Ilman Prometheusta/Grafanaa käytä seuraavia ilmaisia vaihtoehtoja:
4. **Terveyden seuranta:**Lokin seuranta:`.env`Resurssien käyttö:

**Aspire-versio: The .NET Way**

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

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

```yaml
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 oletuksia**Luo
| **Enimmäkseen lucid.ServiceDefaults**projekti:
| **Päivitä Enimmäkseenlucid/Program.cs**Pyrinnän edut
| **Kehityskokemus:** | `docker-compose up` | `dotnet run`Yksi komento
| **aloittaa kaiken**Kojelauta
| **: Kaunis käyttöliittymä osoitteessa http://localhost:1588, josta käy ilmi:** | `docker logs`Kaikki palvelut, joilla on live-status
| **Lokit kaikista palveluista samassa paikassa**Hajautetut jäljet eri palveluissa
| **Lääkintä ja terveystarkastukset**Palvelun löytäminen
| **: Palvelut löytävät toisensa automaattisesti nimien kautta**Asetukset

### : 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](/dockercompose)**Jäljitys
2. **[Asetukset manuaalisesti Automaattinen hajautettu jäljitys](/dockercomposedevdeps)**Tuotanto
3. **[Käytä YAML:ää suoraan Luo manifestit](/imagesharpwithdocker)**Opettele kurveja
4. **[YAML syntaksi C# tiedät jo](/dockercompose)**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 varten`latest`)
5. Molemmista maailmoista parhaat!
6. Tämän blogin docker-asetelman kehitys`.dockerignore`Tä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`.env`Marraskuu 2024 - Full Stack
4. : Täydellinen havaintokyky Prometheuksella, Grafanalla, Seqillä
5. Tänään`depends_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)`.dockerignore`Kä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

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

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

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

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

- Käytä talioituja/pieniä pohjakuvia[Skannaa kuvat haavoittuvuuksien varalta](/dockercompose)Pidä pohjakuvat ajan tasalla
- Älä liitä kuviin salaisuuksia[Käytä mahdollisuuksien mukaan vain lukutiedostojärjestelmiä](/dockercomposedevdeps)Rajasäiliön ominaisuudet
- Käytä Docker-salaisuuksia tai ulkoisia salaisia johtajia[Parhaita käytäntöjä suorituskyvylle](/imagesharpwithdocker)Käytä BuildKitiä nopeampiin rakennuksiin

**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 resurssirajoja**Poista havainnointi vapaatasoille (Seq Cloud, Grafana Cloud, UptimeRobot)
| **Suorita kalliita palveluja (kääntäminen, ML) vain tilauksesta**Kuuden 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 sovelluksista**Taotut Ubuntu-kuvat tarjoavat minimaalisen hyökkäyspinnan[.NET Aspire tarjoaa parhaan luokan paikallisen kehityskokemuksen](/dockercompose)
- **Aspire voi tuottaa Docker Composea tuotannon käyttöönottoa varten**OpenTelemetria-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 rakenteet[Tasovälitys nopeuttaa rajusti toistuvia rakennelmia](https://github.com/scottgal/mostlylucid-nmt)
- **Matka**Tämän blogin Dockerin evoluutio heijastaa tyypillistä kehitystä:

### Lavan palvelut RAM-muistin käyttö Monimutkaisuus

**Vaihe 1**

- [(heinäkuu 2024) App + Tunnel ~ 300MB simppeli](https://docs.docker.com/)
- [Vaihe 2](https://docs.docker.com/compose/compose-file/)
- [(Aug 2024) + riippuvuussuhteet ~500MB](https://github.com/dotnet/dotnet-docker)
- [Vaihe 3](https://learn.microsoft.com/en-us/dotnet/aspire/)
- [(Aug 2024) + Volume fixes ~ 500MB](https://github.com/NVIDIA/nvidia-container-toolkit)
- [Vaihe 4](https://github.com/docker/buildx)

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

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

**: Aloita**

- [Docker säveltää perusasiat](https://github.com/scottgal/mostlylucid-nmt)Omaehtoisuus
- [: Kokeile minimaalista VPS-asetusta tästä artikkelista](https://github.com/scottgal/mostlylucidweb)Rakennusmikropalvelut

: Tutustu .NET-hakuun

Happy containerizing! 🐳