J'ai tiré et exécuté l'image de conteneur SQL Server 2017 à l'aide de la commande suivante:
docker pull Microsoft/mssql-server-linux
docker run --name mssql -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=!Abcd123' -p 1433:1433 -d Microsoft/mssql-server-linux
Et j'ai également déployé une application d'API Web ASP.NET Core sur un conteneur Docker, à l'aide des commandes suivantes:
dotnet publish -c Release -o Output
docker build -t apitest .
docker run -p 3000:80 --name apitest_1 apitest
Le contenu de Dockerfile
:
FROM Microsoft/dotnet
COPY Output /app
WORKDIR /app
EXPOSE 80/tcp
ENTRYPOINT ["dotnet", "DockerSQLTest.dll"]
Dans mon application API Web, j'ai créé une migration Entity Framework Core qui créera la base de données et amorcera certaines données. Dans la méthode Configure
de la classe Startup
, j'ajoute le code suivant pour appliquer les migrations en attente à la base de données:
public async void Configure(IApplicationBuilder app,
IHostingEnvironment env,
StudentDbContext dbContext)
{
await dbContext.Database.MigrateAsync();
...
}
Et la chaîne de connexion à la base de données est extraite de appsettings.json
qui contient la section suivante:
"ConnectionStrings": {
"DefaultConnection": "Server=localhost,1433;Database=student;User Id=sa;Password=!Abcd123;"
}
Mais l'application ne peut pas fonctionner correctement, le message d'exception:
fail: WebApplication6.Startup[0]
System.Threading.Tasks.TaskCanceledException: A task was canceled.
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.<>c__DisplayClass20_0.<<ExistsAsync>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.ExistsAsync(CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.MigrateAsync(String targetMigration, CancellationToken cancellationToken)
Y a-t-il quelque chose qui ne va pas?
Tout d'abord, lorsque vous utilisez deux conteneurs ou plus, il ne peut pas y avoir de connexion localhost. Chaque conteneur Docker possède sa propre IP de réseau interne. Une fois que vous avez démarré un conteneur avec un port exposé pour pouvoir vous connecter à ce conteneur, vous devez spécifier l'hôte IP (où le conteneur s'exécute réellement).
Ainsi, comme exemple, vous devriez avoir la chaîne suivante pour la connexion:
Server=192.168.1.99,1433;Database=student;User Id=sa;Password=!Abcd123;
où: 192.168.1.99 - IP réelle de l'hôte où le conteneur Docker est en cours d'exécution.