- Published on
Deploy ABP Framework dotnet core tiered app to docker swarm. Part 9
Table of Contents
Intro
In this post we will see how to deploy your dotnet core app with docker container.
Create ABP Tired application
abp new AbpDocker -t app -u mvc --tiered -dbms PostgreSQL
Once the app is created update the connection string in all the project and run the DbMigration
project to setup the migrations and database seeding.
Create a same site cookies extension
you can find the code for that here: https://community.abp.io/articles/patch-for-chrome-login-issue-identityserver4-samesite-cookie-problem-weypwp3n
Here is the code
public static class SameSiteCookiesServiceCollectionExtensions
{
public static IServiceCollection AddSameSiteCookiePolicy(this IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Lax;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
return services;
}
private static void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (!httpContext.Request.IsHttps || DisallowsSameSiteNone(userAgent))
{
// For .NET Core < 3.1 set SameSite = (SameSiteMode)(-1)
options.SameSite = SameSiteMode.Lax;
}
}
}
private static bool DisallowsSameSiteNone(string userAgent)
{
// Cover all iOS based browsers here. This includes:
// - Safari on iOS 12 for iPhone, iPod Touch, iPad
// - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
// - Chrome on iOS 12 for iPhone, iPod Touch, iPad
// All of which are broken by SameSite=None, because they use the iOS networking stack
if (userAgent.Contains("CPU iPhone OS 12") || userAgent.Contains("iPad; CPU OS 12"))
{
return true;
}
// Cover Mac OS X based browsers that use the Mac OS networking stack. This includes:
// - Safari on Mac OS X.
// This does not include:
// - Chrome on Mac OS X
// Because they do not use the Mac OS networking stack.
if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&
userAgent.Contains("Version/") && userAgent.Contains("Safari"))
{
return true;
}
// Cover Chrome 50-69, because some versions are broken by SameSite=None,
// and none in this range require it.
// Note: this covers some pre-Chromium Edge versions,
// but pre-Chromium Edge does not require SameSite=None.
if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
{
return true;
}
return false;
}
}
Add the following line to ConfigureServices()
method in all 3 projects.
context.Services.AddSameSiteCookiePolicy();
Go to OnApplicationInitialization()
method in AcmeBookStoreWebModule.cs add app.UseCookiePolicy();
in all 3 projects.
app.UseCookiePolicy(); // added this, Before UseAuthentication or anything else that writes cookies.
Create a new client for the production app
Update the appsettings.json
from the DbMigrator
to add the new client.
"AbpDocker_Web_Docker": {
"ClientId": "AbpDocker_Web_Docker",
"ClientSecret": "1q2w3e*",
"RootUrl": "http://host.docker.internal:9005"
},
Update the IdentityServerDataSeedContributor
in the Domain
project and add the new client to the identity server.
//webDockerClient Client
var webDockerClientId = configurationSection["AbpDocker_Web_Docker:ClientId"];
if (!webClientId.IsNullOrWhiteSpace())
{
var webClientRootUrl = configurationSection["AbpDocker_Web_Docker:RootUrl"].EnsureEndsWith('/');
await CreateClientAsync(
name: webDockerClientId,
scopes: commonScopes,
grantTypes: new[] { "hybrid" },
secret: (configurationSection["AbpDocker_Web_Docker:ClientSecret"] ?? "1q2w3e*").Sha256(),
redirectUri: $"{webClientRootUrl}signin-oidc",
postLogoutRedirectUri: $"{webClientRootUrl}signout-callback-oidc",
frontChannelLogoutUri: $"{webClientRootUrl}Account/FrontChannelLogout",
corsOrigins: new[] { webClientRootUrl.RemovePostFix("/") }
);
}
Run the DbMigrator
project again to see the new client.
Create production config
Create the appsettings.Production.json
in all the three projects.
HttpApi.Host
{
"App": {
"CorsOrigins": "https://*.AbpDocker.com"
},
"ConnectionStrings": {
"Default": "Host=host.docker.internal;Port=5432;Database=AbpDocker;User ID=postgres;Password=postgres;"
},
"Redis": {
"Configuration": "host.docker.internal"
},
"AuthServer": {
"Authority": "http://host.docker.internal:9006",
"RequireHttpsMetadata": "false",
"SwaggerClientId": "AbpDocker_Swagger",
"SwaggerClientSecret": "1q2w3e*"
},
"StringEncryption": {
"DefaultPassPhrase": "WBN0szwYr7wL8Dou"
}
}
IdentityServer
{
"App": {
"SelfUrl": "http://host.docker.internal:9006",
"ClientUrl": "http://localhost:4200",
"CorsOrigins": "https://*.AbpDocker.com,http://localhost:4200,https://localhost:44307,https://localhost:44375,http://host.docker.internal:9006,http://host.docker.internal:9005,http://host.docker.internal:9007",
"RedirectAllowedUrls": "http://localhost:4200,https://localhost:44307,http://host.docker.internal:9006,http://host.docker.internal:9005,http://host.docker.internal:9007"
},
"ConnectionStrings": {
"Default": "Host=host.docker.internal;Port=5432;Database=AbpDocker;User ID=postgres;Password=postgres;"
},
"Redis": {
"Configuration": "host.docker.internal"
}
}
Web
{
"App": {
"SelfUrl": "http://host.docker.internal:9005"
},
"RemoteServices": {
"Default": {
"BaseUrl": "http://host.docker.internal:9007/"
}
},
"Redis": {
"Configuration": "host.docker.internal"
},
"AuthServer": {
"Authority": "http://host.docker.internal:9006",
"RequireHttpsMetadata": "false",
"ClientId": "AbpDocker_Web_Docker",
"ClientSecret": "1q2w3e*"
}
}
Add docker support
Do the following in all 3 projects.
Right Click -> Add -> Docker Support
This will add
Docker
file into the project.Right Click -> Add -> Container Orchestrator Support
This will add the docker file to the
docker-compose.yml
Add port mapping to the services to the expose the services.
Final docker-compose.yml
will look like this.
version: '3.4'
services:
web:
image: abpdockerweb
ports:
- 9005:80
build:
context: .
dockerfile: src/AbpDocker.Web/Dockerfile
identityserver:
image: abpdockeridentityserver
ports:
- 9006:80
build:
context: .
dockerfile: src/AbpDocker.IdentityServer/Dockerfile
httpapi:
image: abpdockerhttpapihost
ports:
- 9007:80
build:
context: .
dockerfile: src/AbpDocker.HttpApi.Host/Dockerfile
Build docker containers
Navigate to the directory where the docker-compose.yml
file is present and then run the following command.
docker-compose build
Deploy the docker stack
docker stack deploy -c .\docker-compose.yml abpdocker
Run the app
Visit the web app in http://host.docker.internal:9005
Visit the identity server in http://host.docker.internal:9006
Visit the api in http://host.docker.internal:9007
Repo: https://github.com/antosubash/AbpWithDocker
Related Posts
Changing theme for your ABP app. Part 10
In this post we will explore how to change the theme for your ABP application.
Centralized logging for .net core ABP microservices app using Seq. Part 8
In this post we will see how to implement a central logging system for your ABP app using Seq.
Extend Tenant management and add custom host to your ABP App. Part 7
In this post we will see how to extent the tenant entity and Add a custom tenant resolver for your ABP app.