MSSQLに依存するservice(ASP.NET Core Webアプリケーション)があります。サービスはDocker composeを使用して調整されます。Dockercomposeが最初にデータベースを起動し、サービスが実行される前にデータベースがreadyになるまで待機します。そのため、docker-compose.yml
を次のように定義しています。
version: '3.7'
services:
sql.data:
container_name: db_service
image: Microsoft/mssql-server-linux:2017-latest
healthcheck:
test: ["CMD", "/opt/mssql-tools/bin/sqlcmd", "-S", "http://localhost:1433", "-U", "sa", "-P", "Pass_Word", "-Q", "SELECT 1", "||", "exit 1"]
my_service:
container_name: my_service_container
image: ${DOCKER_REGISTRY-}my_service
build:
context: .
dockerfile: MyService/Dockerfile
depends_on:
- sql.data
このヘルスチェックにより、Docker composeはデータベースサービスの準備が整うまで待機せず、直後にmy_service
を開始し、予想どおり、my_service
がデータベースへの接続に失敗します。ログの一部は次のとおりです。
Recreating db_service ... done
Recreating my_service_container ... done
Attaching to db_service, my_service_container
my_service_container | info: ...Context[0]
my_service_container | Migrating database associated with context Context
my_service_container | info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
my_service_container | Entity Framework Core 3.1.1 initialized 'Context' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: MigrationsAssembly=MyService
my_service_container | fail: Context[0]
my_service_container | An error occurred while migrating the database used on context Context
my_service_container | Microsoft.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 40 - Could not open a connection to SQL Server)
...
exception details
...
my_service_container | ClientConnectionId:00000000-0000-0000-0000-000000000000
my_service_container exited with code 0
db_service | 2020-03-05 05:45:51.82 Server Microsoft SQL Server 2017 (RTM-CU13) (KB4466404) - 14.0.3048.4 (X64)
Nov 30 2018 12:57:58
Copyright (C) 2017 Microsoft Corporation
Developer Edition (64-bit) on Linux (Ubuntu 16.04.5 LTS)
2020-03-05 05:45:51.82 Server UTC adjustment: 0:00
2020-03-05 05:45:51.82 Server (c) Microsoft Corporation.
2020-03-05 05:45:51.82 Server All rights reserved.
2020-03-05 05:45:51.82 Server Server process ID is 4120.
2020-03-05 05:45:51.82 Server Logging SQL Server messages in file '/var/opt/mssql/log/errorlog'.
2020-03-05 05:45:51.82 Server Registry startup parameters:
-d /var/opt/mssql/data/master.mdf
-l /var/opt/mssql/data/mastlog.ldf
-e /var/opt/mssql/log/errorlog
ログに示されているように、Docker Composeは最初にDBを起動しますが、サービスが実行される前に準備が整うまで待機しません。
私はhealthcheck
に別の構文を試しました、例えば:
test: /opt/mssql-tools/bin/sqlcmd -S http://localhost:1433 -U sa -P ${SA_PASSWORD} -Q "SELECT 1" || exit 1
しかし、どちらも期待どおりに機能しませんでした。
以下の情報源をオンラインで確認しましたが、どちらを使用しても問題を解決できませんでした。
この機能はversion 3.7
でもサポートされていますか? この混乱するコメントのため
MSSQLサービスが開始するのをどのくらい待つことができるかについての考えはありますか?
多くのさまざまなシナリオを検索して試した後、次のcomposerファイルを使用して待機を追加できました。これはasp.netコアソリューション用です。重要なのは、エントリポイントを上書きする必要があることです。 dockerfileで指定します。また、 "wait-for-it.sh" LFをCRLFではなく行末として保存する必要があります。そうしないと、ファイルが見つからないというエラーが発生します。
Dockerfileには次のものが必要です(ここからダウンロードしてください: https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh 、必ず確認してくださいファイルを保存します):
COPY ./wait-for-it.sh /wait-for-it.sh
RUN chmod +x wait-for-it.sh
docker-compose.yml
version: '3.7'
services:
vc-db:
image: mcr.Microsoft.com/mssql/server:latest
ports:
- "${DOCKER_SQL_PORT:-1433}:1433"
expose:
- 1433
environment:
- ACCEPT_EULA=Y
- MSSQL_PID=Express
- SA_PASSWORD=v!rto_Labs!
networks:
- virto
vc-platform-web:
image: virtocommerce/platform:${DOCKER_TAG:-latest}
ports:
- "${DOCKER_PLATFORM_PORT:-8090}:80"
environment:
- ASPNETCORE_URLS=http://+
depends_on:
- vc-db
entrypoint: ["/wait-for-it.sh", "vc-db:1433", "-t", "120", "--", "dotnet", "VirtoCommerce.Platform.Web.dll"]
networks:
- virto
depends_on
を使用すると、docker-composeはベースサービスをより優先して起動し、サービスの開始を待ちません。
特定のサービス(ポート)を待ってから別のサービスを実行するのに役立つ、いくつかの便利な外部プログラムがあります。
vishnubob/wait-for-it は、特定のポートが準備ができるまで実行フローをブロックするそれらの1つです。
別の良い選択は eficode/wait-for で、これは既にdocker-composeのために準備されています。
使用例(eficode/wait-for docsによる)
version: '2'
services:
db:
image: postgres:9.4
backend:
build: backend
# Blocks execution flow util db:5432 is ready (Or you can use localhost instead)
command: sh -c './wait-for db:5432 -- npm start'
depends_on:
- db
-更新-
PostgreSQLのようなデータベースに依存するPythonアプリケーションがあるとします。また、アプリケーションは次のコマンドで実行されます:python app.py
Official Docker Document が言ったように、vishnubob/wait-for-it
をイメージに(app.py
などの他のプロジェクトファイルの中に)挿入します
次に、この行をdocker-compose.yml
に挿入します。
version: "3"
services:
web:
build: .
ports:
- "80:8000"
depends_on:
- "db"
# This command waits until `db:5432` respond (5432 is default PostgreSQL port)
# then runs our application by this command: `python app.py`
command: ["./wait-for-it.sh", "db:5432", "--", "python", "app.py"]
db:
image: postgres
注:画像ファイル内のDockerfile
にこのコマンドを含めることを忘れないでください:
# Copy wait-for-it.sh into our image
COPY wait-for-it.sh wait-for-it.sh
# Make it executable, in Linux
RUN chmod +x wait-for-it.sh
2つの個別のdockerfileを作成します(例):
Docker-compose.yml内でシーケンスを設定する
Mssql.Dockerfile
FROM mcr.Microsoft.com/mssql/server AS base
ENV ACCEPT_EULA=Y
ENV SA_PASSWORD=Password123
COPY . .
COPY ["Db/Scripts/*", "Db/Scripts/"]
VOLUME ./Db:/var/opt/mssql/data
HEALTHCHECK --interval=10s --timeout=5s --start-period=10s --retries=10 \
CMD /opt/mssql-tools/bin/sqlcmd -S . -U sa -P Password123 -i Db/Scripts/SetupDb.sql || exit 1
App.Dockerfile:
FROM mcr.Microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.Microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["AspNetCoreWebApplication/AspNetCoreWebApplication.csproj", "AspNetCoreWebApplication/"]
COPY ["WebApp.Data.EF/WebApp.Data.EF.csproj", "WebApp.Data.EF/"]
COPY ["WebApp.Service/WebApp.Service.csproj", "WebApp.Service/"]
RUN dotnet restore "AspNetCoreWebApplication/AspNetCoreWebApplication.csproj"
COPY . .
WORKDIR "/src/AspNetCoreWebApplication"
RUN dotnet build "AspNetCoreWebApplication.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "AspNetCoreWebApplication.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "AspNetCoreWebApplication.dll"]
Docker-compose.yml:
version: '3.7'
services:
api:
image: aspnetcore/mentoring_api
container_name: mentoring_api
build:
context: .
dockerfile: App.Dockerfile
ports:
- 8081:80
expose:
- 8081
environment:
ASPNETCORE_ENVIRONMENT: Development
depends_on:
- sqlserver
sqlserver:
image: aspnetcore/mentoring_db
container_name: mentoring_db
build:
context: .
dockerfile: Mssql.Dockerfile
ports:
- "1433:1433"
expose:
- 1433
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=Password123
volumes:
- ./Db:/var/opt/mssql/data
注:接続文字列は次のようになります:"Server=sqlserver;Database=Northwind;Trusted_Connection=False;User Id=sa;Password=Password123;MultipleActiveResultSets=true"
アプリのコンテナーで起動される簡単なスクリプトを記述できます。たとえば、sleep N
(NはDBの起動に必要な時間)を使用して遅延を設定するか、またはuntil
サイクルを使用して試すことができますDBに接続し、可能な場合はアプリを起動できます。
これは完璧な解決策ではないことはわかっていますが、同様の問題があったときに役に立ちました