Udostępnij za pośrednictwem


Definiowanie aplikacji wielokontenerowej przy użyciu docker-compose.yml

Wskazówka

Ta treść jest fragmentem eBooka "Architektura mikrousług .NET dla konteneryzowanych aplikacji .NET", dostępnego na .NET Docs lub jako bezpłatny plik PDF do pobrania i czytania w trybie offline.

Miniatura okładki eBooka „Architektura mikrousług platformy .NET dla konteneryzowanych aplikacji platformy .NET”.

W tym przewodniku plik docker-compose.yml został wprowadzony w sekcji Krok 4. Zdefiniuj usługi w docker-compose.yml podczas kompilowania aplikacji platformy Docker z wieloma kontenerami. Istnieją jednak dodatkowe sposoby korzystania z plików docker-compose, które warto dokładniej zbadać.

Możesz na przykład jawnie opisać sposób wdrażania aplikacji wielokontenerowej w pliku docker-compose.yml. Możesz również opisać sposób tworzenia niestandardowych obrazów Dockera, opcjonalnie. (Niestandardowe obrazy platformy Docker można również skompilować przy użyciu interfejsu wiersza polecenia platformy Docker).

Zasadniczo definiujesz każdy kontener, który chcesz wdrożyć, oraz pewne cechy dla każdego wdrożenia kontenera. Po utworzeniu pliku opisu wdrożenia z wieloma kontenerami można wdrożyć całe rozwiązanie w ramach jednej akcji koordynowanej za pomocą polecenia interfejsu wiersza polecenia (CLI) docker-compose up lub wdrożyć je bezpośrednio z Visual Studio. W przeciwnym razie musisz użyć Docker CLI, aby wdrażać kontenery jeden po drugim w kilku krokach przy użyciu polecenia docker run z wiersza polecenia. W związku z tym każda usługa zdefiniowana w docker-compose.yml musi określać dokładnie jeden obraz lub proces budowania. Inne klucze są opcjonalne i są analogiczne do ich docker run odpowiedników wiersza polecenia.

Poniższy kod YAML jest definicją możliwego pliku globalnego, ale pojedynczego docker-compose.yml dla przykładu eShopOnContainers. Ten kod nie jest rzeczywistym plikiem docker-compose z aplikacji eShopOnContainers. Zamiast tego jest to uproszczona i skonsolidowana wersja w jednym pliku, która nie jest najlepszym sposobem pracy z plikami docker-compose, jak wyjaśniono później.

version: '3.4'

services:
  webmvc:
    image: eshop/webmvc
    environment:
      - CatalogUrl=http://catalog-api
      - OrderingUrl=http://ordering-api
      - BasketUrl=http://basket-api
    ports:
      - "5100:80"
    depends_on:
      - catalog-api
      - ordering-api
      - basket-api

  catalog-api:
    image: eshop/catalog-api
    environment:
      - ConnectionString=Server=sqldata;Initial Catalog=CatalogData;User Id=sa;Password=[PLACEHOLDER]
    expose:
      - "80"
    ports:
      - "5101:80"
    #extra hosts can be used for standalone SQL Server or services at the dev PC
    extra_hosts:
      - "CESARDLSURFBOOK:10.0.75.1"
    depends_on:
      - sqldata

  ordering-api:
    image: eshop/ordering-api
    environment:
      - ConnectionString=Server=sqldata;Database=Services.OrderingDb;User Id=sa;Password=[PLACEHOLDER]
    ports:
      - "5102:80"
    #extra hosts can be used for standalone SQL Server or services at the dev PC
    extra_hosts:
      - "CESARDLSURFBOOK:10.0.75.1"
    depends_on:
      - sqldata

  basket-api:
    image: eshop/basket-api
    environment:
      - ConnectionString=sqldata
    ports:
      - "5103:80"
    depends_on:
      - sqldata

  sqldata:
    environment:
      - SA_PASSWORD=[PLACEHOLDER]
      - ACCEPT_EULA=Y
    ports:
      - "5434:1433"

  basketdata:
    image: redis

Kluczem głównym w tym pliku są usługi. W tym kluczu zdefiniujesz usługi, które chcesz wdrożyć i uruchomić podczas wykonywania docker-compose up polecenia lub podczas wdrażania z programu Visual Studio przy użyciu tego pliku docker-compose.yml. W tym przypadku plik docker-compose.yml zawiera wiele zdefiniowanych usług, zgodnie z opisem w poniższej tabeli.

Nazwa usługi Opis
webmvc Kontener zawierający aplikację ASP.NET Core MVC korzystającą z mikrousług po stronie serwera C#
katalog-API Kontener zawierający mikrousługę Katalogu dla internetowego interfejsu API ASP.NET Core
zamawianie-API Kontener zawierający mikrousługę interfejsu API sieci Web ASP.NET Core do obsługi zamówień
sqldata Kontener z uruchomionym programem SQL Server dla systemu Linux, który przechowuje bazy danych mikrousług
koszyk-api Kontener z mikrousługą Web API ASP.NET Core dla Koszyka
koszykdata Kontener z uruchomioną usługą pamięci podręcznej REDIS z bazą danych koszyka jako pamięcią podręczną REDIS

Prosty kontener interfejsu API usługi internetowej

Koncentrując się na jednym kontenerze, mikrousługa catalog-api container-microservice ma prostą definicję:

  catalog-api:
    image: eshop/catalog-api
    environment:
      - ConnectionString=Server=sqldata;Initial Catalog=CatalogData;User Id=sa;Password=[PLACEHOLDER]
    expose:
      - "80"
    ports:
      - "5101:80"
    #extra hosts can be used for standalone SQL Server or services at the dev PC
    extra_hosts:
      - "CESARDLSURFBOOK:10.0.75.1"
    depends_on:
      - sqldata

Ta konteneryzowana usługa ma następującą podstawową konfigurację:

  • Jest on oparty na niestandardowym obrazie eshop/catalog-api . Dla uproszczenia, w pliku nie ma ustawienia klucza dotyczącego budowy. Oznacza to, że obraz musi zostać wcześniej zbudowany (za pomocą polecenia docker build) lub pobrany (za pomocą polecenia docker pull) z dowolnego rejestru Docker.

  • Definiuje zmienną środowiskową o nazwie ConnectionString z parametrami połączenia, które mają być używane przez program Entity Framework w celu uzyskania dostępu do wystąpienia programu SQL Server zawierającego model danych wykazu. W takim przypadku ten sam kontener programu SQL Server przechowuje wiele baz danych. W związku z tym potrzebna jest mniejsza ilość pamięci na maszynie deweloperów dla platformy Docker. Można jednak również wdrożyć jeden kontener programu SQL Server dla każdej bazy danych mikrousług.

  • Nazwa programu SQL Server to sqldata, czyli taka sama nazwa, która jest używana dla kontenera z uruchomionym wystąpieniem programu SQL Server dla systemu Linux. Jest to wygodne; możliwość używania tego rozpoznawania nazw (wewnętrznego hosta platformy Docker) rozpozna adres sieciowy, dzięki czemu nie musisz znać wewnętrznego adresu IP kontenerów, do których uzyskujesz dostęp z innych kontenerów.

Ponieważ parametry połączenia są definiowane przez zmienną środowiskową, można ustawić zmienną za pomocą innego mechanizmu i w innym czasie. Na przykład można ustawić inne parametry połączenia podczas wdrażania w środowisku produkcyjnym na hostach końcowych lub wykonując je z potoków ciągłej integracji/ciągłego wdrażania w usługach Azure DevOps Services lub preferowanym systemie DevOps.

  • Udostępnia port 80 dla wewnętrznego dostępu do usługi catalog-api na hoście platformy Docker. Host jest obecnie maszyną wirtualną z systemem Linux, ponieważ jest oparty na obrazie platformy Docker dla systemu Linux, ale zamiast tego można skonfigurować kontener do uruchamiania na obrazie systemu Windows.

  • Przekierowuje uwidoczniony port 80 w kontenerze na port 5101 na maszynie hosta Docker (maszynie wirtualnej z systemem Linux).

  • Łączy usługę internetową z usługą sqldata (instancja SQL Server dla bazy danych systemu Linux uruchomionej w kontenerze). Po określeniu tej zależności kontener catalog-api nie zostanie uruchomiony, dopóki kontener sqldata nie zostanie już uruchomiony. Ten aspekt jest ważny, ponieważ najpierw musi być uruchomiona baza danych programu SQL Server. Jednak ten rodzaj zależności kontenera nie jest wystarczający w wielu przypadkach, ponieważ platforma Docker sprawdza tylko na poziomie kontenera. Czasami usługa (w tym przypadku serwer SQL Server) może nadal nie być gotowa, dlatego zaleca się zaimplementowanie logiki ponawiania prób z opóźnieniem wykładniczym w mikrousługach klienckich. W ten sposób, jeśli kontener zależności nie jest gotowy przez krótki czas, aplikacja będzie nadal odporna.

  • Jest on skonfigurowany do zezwalania na dostęp do serwerów zewnętrznych: ustawienie extra_hosts umożliwia dostęp do zewnętrznych serwerów lub maszyn spoza hosta platformy Docker (czyli poza domyślną maszyną wirtualną z systemem Linux, która jest hostem deweloperskim platformy Docker), takim jak lokalne wystąpienie programu SQL Server na komputerze deweloperskim.

Istnieją również inne, bardziej zaawansowane docker-compose.yml ustawienia, które omówimy w poniższych sekcjach.

Używanie plików docker-compose do pracy z wieloma środowiskami

Pliki docker-compose.*.yml są plikami definicji i mogą być używane przez wiele infrastruktur, które rozumieją ten format. Najprostszym narzędziem jest polecenie docker-compose.

W związku z tym, za pomocą polecenia "docker-compose" można obsługiwać następujące główne scenariusze.

Środowiska projektowe

Podczas tworzenia aplikacji ważne jest, aby móc uruchamiać aplikację w izolowanym środowisku projektowym. Możesz użyć polecenia Docker-compose CLI, aby utworzyć to środowisko lub programu Visual Studio, który używa narzędzia docker-compose w tle.

Plik docker-compose.yml umożliwia konfigurowanie i dokumentowanie wszystkich zależności usługi aplikacji (innych usług, pamięci podręcznej, baz danych, kolejek itp.). Za pomocą polecenia interfejsu wiersza polecenia docker-compose można utworzyć i uruchomić co najmniej jeden kontener dla każdej zależności za pomocą jednego polecenia (docker-compose up).

Pliki docker-compose.yml to pliki konfiguracji interpretowane przez aparat platformy Docker, ale także służą jako wygodne pliki dokumentacji dotyczące kompozycji aplikacji wielokontenerowej.

Środowiska testowe

Ważną częścią każdego procesu ciągłego wdrażania (CD) lub ciągłej integracji (CI) są testy jednostkowe i testy integracji. Te testy automatyczne wymagają środowiska izolowanego, więc nie mają one wpływu na użytkowników ani inne zmiany w danych aplikacji.

Za pomocą narzędzia Docker Compose można utworzyć i zniszczyć środowisko izolowane bardzo łatwo w kilku poleceniach z poziomu wiersza polecenia lub skryptów, takich jak następujące polecenia:

docker-compose -f docker-compose.yml -f docker-compose-test.override.yml up -d
./run_unit_tests
docker-compose -f docker-compose.yml -f docker-compose-test.override.yml down

Wdrożenia produkcyjne

Możesz również użyć Compose do uruchomienia na zdalnym silniku Docker. Typowym przypadkiem jest wdrożenie na jednym wystąpieniu hosta Docker.

Jeśli używasz innego koordynatora (na przykład usługi Azure Service Fabric lub Kubernetes), może być konieczne dodanie ustawień konfiguracji i metadanych, takich jak te w docker-compose.yml, ale w formacie wymaganym przez innego koordynatora.

W każdym razie narzędzie docker-compose jest wygodnym narzędziem i formatem metadanych dla przepływów pracy tworzenia, testowania i produkcji, chociaż przepływ pracy produkcji może się różnić w zależności od używanego orkiestratora.

Używanie wielu plików docker-compose do obsługi kilku środowisk

Podczas celowania w różne środowiska należy użyć wielu plików compose. Takie podejście umożliwia utworzenie wielu wariantów konfiguracji w zależności od środowiska.

Zastępowanie podstawowego pliku docker-compose

Można użyć pojedynczego pliku docker-compose.yml, jak w uproszczonych przykładach przedstawionych w poprzednich sekcjach. Nie jest to jednak zalecane w przypadku większości aplikacji.

Domyślnie compose odczytuje dwa pliki, docker-compose.yml i opcjonalny plik docker-compose.override.yml. Jak pokazano na rysunku 6–11, jeśli używasz programu Visual Studio i włączasz obsługę platformy Docker, program Visual Studio tworzy również dodatkowy plik docker-compose.vs.debug.g.yml do debugowania aplikacji, możesz przyjrzeć się temu plikowi w folderze obj\Docker\ w głównym folderze rozwiązania.

Pliki w projekcie docker compose.

Rysunek 6–11. pliki docker-compose w programie Visual Studio 2019

struktura pliku projektu docker-compose:

  • .dockerignore — używany do ignorowania plików
  • docker-compose.yml — służy do tworzenia mikrousług
  • docker-compose.override.yml — służy do konfigurowania środowiska mikrousług

Możesz edytować pliki docker-compose za pomocą dowolnego edytora, takiego jak Visual Studio Code lub Sublime, i uruchomić aplikację za pomocą polecenia docker-compose up.

Zgodnie z konwencją plik docker-compose.yml zawiera konfigurację podstawową i inne ustawienia statyczne. Oznacza to, że konfiguracja usługi nie powinna się zmieniać w zależności od docelowego środowiska wdrażania.

Plik docker-compose.override.yml, jak sugeruje jego nazwa, zawiera ustawienia konfiguracji, które zastępują podstawową konfigurację, taką jak konfiguracja, która zależy od środowiska wdrażania. Można również mieć wiele plików zastępczych o różnych nazwach. Pliki nadpisujące zwykle zawierają dodatkowe informacje wymagane przez aplikację, a związane ze środowiskiem lub wdrożeniem.

Określanie wielu środowisk

Typowy przypadek użycia polega na zdefiniowaniu wielu plików kompozycji, dzięki czemu można kierować do wielu środowisk, takich jak produkcja, testowanie, ciągła integracja lub rozwój. Aby uwzględniać te różnice, możesz podzielić konfigurację Compose na wiele plików, jak pokazano na rysunku 6–12.

Diagram przedstawiający trzy pliki docker-compose ustawione w celu zastąpienia pliku podstawowego.

Rysunek 6–12. Wiele plików docker-compose przesłaniających wartości w pliku podstawowym docker-compose.yml

W celu obsługi różnych środowisk można połączyć wiele plików docker-compose*.yml. Zaczynasz od podstawowego pliku docker-compose.yml. Ten plik podstawowy zawiera podstawowe lub statyczne ustawienia konfiguracji, które nie zmieniają się w zależności od środowiska. Na przykład aplikacja eShopOnContainers ma następujący plik docker-compose.yml (uproszczony z mniejszą liczbą usług) jako plik podstawowy.

#docker-compose.yml (Base)
version: '3.4'
services:
  basket-api:
    image: eshop/basket-api:${TAG:-latest}
    build:
      context: .
      dockerfile: src/Services/Basket/Basket.API/Dockerfile
    depends_on:
      - basketdata
      - identity-api
      - rabbitmq

  catalog-api:
    image: eshop/catalog-api:${TAG:-latest}
    build:
      context: .
      dockerfile: src/Services/Catalog/Catalog.API/Dockerfile
    depends_on:
      - sqldata
      - rabbitmq

  marketing-api:
    image: eshop/marketing-api:${TAG:-latest}
    build:
      context: .
      dockerfile: src/Services/Marketing/Marketing.API/Dockerfile
    depends_on:
      - sqldata
      - nosqldata
      - identity-api
      - rabbitmq

  webmvc:
    image: eshop/webmvc:${TAG:-latest}
    build:
      context: .
      dockerfile: src/Web/WebMVC/Dockerfile
    depends_on:
      - catalog-api
      - ordering-api
      - identity-api
      - basket-api
      - marketing-api

  sqldata:
    image: mcr.microsoft.com/mssql/server:2019-latest

  nosqldata:
    image: mongo

  basketdata:
    image: redis

  rabbitmq:
    image: rabbitmq:3-management

Wartości w podstawowym pliku docker-compose.yml nie powinny zmieniać się z powodu różnych docelowych środowisk wdrażania.

Jeśli na przykład skoncentrujesz się na definicji usługi webmvc, możesz zobaczyć, jak te informacje są w dużej mierze podobne, niezależnie od tego, jakie środowisko docelowe wybierzesz. Masz następujące informacje:

  • Nazwa usługi: webmvc.

  • Obraz niestandardowy kontenera: eshop/webmvc.

  • Polecenie budowania niestandardowego obrazu Docker, wskazując, który plik Dockerfile użyć.

  • Ten kontener ma zależności na inne usługi, więc nie zostanie uruchomiony, dopóki nie zostaną uruchomione inne kontenery zależności.

Możesz mieć dodatkową konfigurację, ale ważnym punktem jest to, że w pliku podstawowym docker-compose.yml chcesz po prostu ustawić informacje wspólne w różnych środowiskach. Następnie w docker-compose.override.yml lub podobnych plikach dla środowiska produkcyjnego lub przejściowego należy umieścić konfigurację specyficzną dla każdego środowiska.

Zazwyczaj plik docker-compose.override.yml jest używany w środowisku deweloperskim, co ilustruje poniższy przykład zaczerpnięty z eShopOnContainers.

#docker-compose.override.yml (Extended config for DEVELOPMENT env.)
version: '3.4'

services:
# Simplified number of services here:

  basket-api:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://0.0.0.0:80
      - ConnectionString=${ESHOP_AZURE_REDIS_BASKET_DB:-basketdata}
      - identityUrl=http://identity-api
      - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
      - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
      - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
      - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
      - AzureServiceBusEnabled=False
      - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
      - OrchestratorType=${ORCHESTRATOR_TYPE}
      - UseLoadTest=${USE_LOADTEST:-False}

    ports:
      - "5103:80"

  catalog-api:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://0.0.0.0:80
      - ConnectionString=${ESHOP_AZURE_CATALOG_DB:-Server=sqldata;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=[PLACEHOLDER]}
      - PicBaseUrl=${ESHOP_AZURE_STORAGE_CATALOG_URL:-http://host.docker.internal:5202/api/v1/catalog/items/[0]/pic/}
      - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
      - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
      - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
      - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME}
      - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY}
      - UseCustomizationData=True
      - AzureServiceBusEnabled=False
      - AzureStorageEnabled=False
      - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
      - OrchestratorType=${ORCHESTRATOR_TYPE}
    ports:
      - "5101:80"

  marketing-api:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://0.0.0.0:80
      - ConnectionString=${ESHOP_AZURE_MARKETING_DB:-Server=sqldata;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=[PLACEHOLDER]}
      - MongoConnectionString=${ESHOP_AZURE_COSMOSDB:-mongodb://nosqldata}
      - MongoDatabase=MarketingDb
      - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
      - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
      - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}
      - identityUrl=http://identity-api
      - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
      - CampaignDetailFunctionUri=${ESHOP_AZUREFUNC_CAMPAIGN_DETAILS_URI}
      - PicBaseUrl=${ESHOP_AZURE_STORAGE_MARKETING_URL:-http://host.docker.internal:5110/api/v1/campaigns/[0]/pic/}
      - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_MARKETING_NAME}
      - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_MARKETING_KEY}
      - AzureServiceBusEnabled=False
      - AzureStorageEnabled=False
      - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
      - OrchestratorType=${ORCHESTRATOR_TYPE}
      - UseLoadTest=${USE_LOADTEST:-False}
    ports:
      - "5110:80"

  webmvc:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://0.0.0.0:80
      - PurchaseUrl=http://webshoppingapigw
      - IdentityUrl=http://10.0.75.1:5105
      - MarketingUrl=http://webmarketingapigw
      - CatalogUrlHC=http://catalog-api/hc
      - OrderingUrlHC=http://ordering-api/hc
      - IdentityUrlHC=http://identity-api/hc
      - BasketUrlHC=http://basket-api/hc
      - MarketingUrlHC=http://marketing-api/hc
      - PaymentUrlHC=http://payment-api/hc
      - SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
      - UseCustomizationData=True
      - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
      - OrchestratorType=${ORCHESTRATOR_TYPE}
      - UseLoadTest=${USE_LOADTEST:-False}
    ports:
      - "5100:80"
  sqldata:
    environment:
      - SA_PASSWORD=[PLACEHOLDER]
      - ACCEPT_EULA=Y
    ports:
      - "5433:1433"
  nosqldata:
    ports:
      - "27017:27017"
  basketdata:
    ports:
      - "6379:6379"
  rabbitmq:
    ports:
      - "15672:15672"
      - "5672:5672"

W tym przykładzie konfiguracja nadpisywania dla rozwoju udostępnia niektóre porty dla hosta, definiuje zmienne środowiskowe z adresami URL przekierowania i określa parametry połączenia dla środowiska deweloperskiego. Te ustawienia są przeznaczone tylko dla środowiska deweloperskiego.

Po uruchomieniu docker-compose up (lub jego uruchomieniu z programu Visual Studio), polecenie odczytuje nadpisania automatycznie, tak jakby scalało oba pliki.

Przypuśćmy, że chcesz utworzyć inny plik Compose dla środowiska produkcyjnego, z różnymi wartościami konfiguracji, portami lub ciągami połączeń. Możesz utworzyć inny plik zastąpienia, taki jak plik o nazwie docker-compose.prod.yml z różnymi ustawieniami i zmiennymi środowiskowymi. Ten plik może być przechowywany w innym repozytorium Git lub zarządzanym i zabezpieczonym przez inny zespół.

Jak wdrożyć używając określonego pliku nadpisania

Aby użyć wielu przesłonięć plików lub przesłonić plik o innej nazwie, możesz użyć opcji -f z poleceniem docker-compose i określić pliki. Komponowanie scala pliki w kolejności, w jakiej są określone w wierszu poleceń. W poniższym przykładzie pokazano, jak wdrożyć za pomocą plików zastępujących.

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

Używanie zmiennych środowiskowych w plikach docker-compose

Jest to wygodne, szczególnie w środowiskach produkcyjnych, aby móc uzyskać informacje o konfiguracji ze zmiennych środowiskowych, jak pokazano w poprzednich przykładach. Możesz odwołać się do zmiennej środowiskowej w plikach docker-compose przy użyciu składni ${MY_VAR}. Poniższy wiersz z pliku docker-compose.prod.yml pokazuje, jak odwoływać się do wartości zmiennej środowiskowej.

IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105

Zmienne środowiskowe są tworzone i inicjowane na różne sposoby w zależności od środowiska hosta (Linux, Windows, Cloud cluster itp.). Jednak wygodnym podejściem jest użycie pliku env. Pliki docker-compose obsługują deklarowanie domyślnych zmiennych środowiskowych w pliku env. Te wartości zmiennych środowiskowych są wartościami domyślnymi. Można je jednak zastąpić wartościami zdefiniowanymi w poszczególnych środowiskach (system operacyjny hosta lub zmienne środowiskowe z klastra). Ten plik env należy umieścić w folderze, z którego jest wykonywane polecenie docker-compose.

W poniższym przykładzie pokazano plik env, taki jak plik env dla aplikacji eShopOnContainers.

# .env file

ESHOP_EXTERNAL_DNS_NAME_OR_IP=host.docker.internal

ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP=10.121.122.92

Docker-compose oczekuje, że każdy wiersz w pliku env będzie w formacie <variable>=<value>.

Wartości ustawione w środowisku czasu wykonywania zawsze zastępują wartości zdefiniowane w pliku env. W podobny sposób wartości przekazywane za pośrednictwem argumentów wiersza polecenia zastępują również wartości domyślne ustawione w pliku env.

Dodatkowe zasoby

Tworzenie zoptymalizowanych obrazów Docker dla ASP.NET Core

Jeśli eksplorujesz platformę Docker i platformę .NET w źródłach w Internecie, znajdziesz pliki Dockerfile, które pokazują prostotę tworzenia obrazu platformy Docker przez skopiowanie źródła do kontenera. Te przykłady sugerują, że korzystając z prostej konfiguracji, możesz mieć obraz Docker ze środowiskiem spakowanym razem z aplikacją. W poniższym przykładzie pokazano prosty plik Dockerfile w tym środowisku.

FROM mcr.microsoft.com/dotnet/sdk:8.0
WORKDIR /app
ENV ASPNETCORE_URLS http://+:80
EXPOSE 80
COPY . .
RUN dotnet restore
ENTRYPOINT ["dotnet", "run"]

Plik Dockerfile podobny do tego będzie działać. Możesz jednak znacznie zoptymalizować swoje obrazy, zwłaszcza te wykorzystywane w produkcji.

W modelu kontenerów i mikrousług stale uruchamiasz kontenery. Typowy sposób korzystania z kontenerów nie powoduje ponownego uruchomienia kontenera uśpienia, ponieważ kontener jest jednorazowy. Orkiestratory (takie jak Kubernetes i Azure Service Fabric) tworzą nowe instancje obrazów. Oznacza to, że należy zoptymalizować aplikację przez jej przedkompilowanie, aby proces instancjacji był szybszy. Po uruchomieniu kontenera powinien być gotowy do działania. Nie przywracaj i nie kompiluj podczas działania przy użyciu poleceń CLI dotnet restore i dotnet build, jak pokazano we wpisach na blogu o .NET i Dockerze.

Zespół platformy .NET wykonuje ważną pracę, aby platforma .NET i ASP.NET Core stała się strukturą zoptymalizowaną pod kątem kontenerów. Nie tylko platforma .NET jest uproszczoną strukturą o małym rozmiarze pamięci; zespół skupił się na zoptymalizowanych obrazach platformy Docker pod kątem trzech głównych scenariuszy i opublikował je w rejestrze usługi Docker Hub pod adresem dotnet/, począwszy od wersji 2.1:

  • Rozwój: Priorytetem jest możliwość szybkiego iterowania i debugowania zmian, gdzie rozmiar jest drugorzędny.
  • Kompilacja: Priorytetem jest kompilowanie aplikacji, a obraz zawiera pliki binarne i inne zależności w celu optymalizacji plików binarnych.
  • Produkcja: Skupiamy się na szybkim wdrażaniu i uruchamianiu kontenerów, więc te wizerunki kontenerów są ograniczone do plików binarnych i zawartości potrzebnej do uruchomienia aplikacji.

Zespół platformy .NET udostępnia kilka podstawowych wariantów w dotnet/, na przykład:

  • zestaw SDK: na potrzeby scenariuszy programowania i kompilacji
  • aspnet: w przypadku scenariuszy produkcyjnych ASP.NET
  • środowisko uruchomieniowe: w scenariuszach produkcyjnych platformy .NET
  • runtime-deps: w przypadku scenariuszy produkcyjnych aplikacji autonomicznych

W celu szybszego uruchamiania obrazy środowiska uruchomieniowego również automatycznie ustawiają aspnetcore_urls na port 80 i używają narzędzia Ngen do utworzenia natywnej pamięci podręcznej obrazów zestawów.

Dodatkowe zasoby