The main issue is that we cannot get the container to run locally in release mode. While the container environmental variables indicate it should be running in release mode, a license check always occurred on startup.
I believe the issue is that the application discussed here has a dependency on several other projects and it seems we'd have to get all those projects configured to run in release mode in Docker also.
An alternative solution was to solve the license check issue and let the app run in debug mode. My confusion about how the license check works has been cleared up for me, so I marked this ticket as resolved.
We will work on moving our entire microservice solution for local development to Docker and compose files, but that is separate work. If we get stuck later with the issue of running containers in Release mode, we'll open another ticket.
Ahhh. Okay it finally makes sense for me. To get the project to run in the container you need two things:
AbpLicenseCode
in the app configurationI was interpreting the requirements as doing option 1 **OR ** 2, but I have to do both things.
We have eight solutions with licenses and they all have invalid license codes now for some reason. I regenerated one project to generate a valid license code and successfully started in a container. I didn't want to do that for our 7 other solutions, but it appears I will have to if I want to run them in debug mode in containers.
System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile), ".abp", "cli", "access-token.bin");
I confirmed this just prints the path to the correct location of the access-token.bin
file.
I was able to properly transfer the token from the host to the Docker container. The file is indeed in the container's file system in the location noted in previous links. But startup always fails due to license check error despite the token being present in the container.
We are trying to debug in Development environment using Docker. That is the only goal here.
We can use the AbpLicenseCode
value, but we have 8 solutions which means we have to go back and regenerate 8 projects in Suite to have a correct code generated. We've never had to deal with this value before because we've always just used the CLI to login and that just works.
Can you confirm whether the alternative approach documented in other support tickets should or should not work: https://gist.github.com/ebicoglu/f7cd77069fa053cbe9cf9e9ffcc2f2d2
We don't have any issues with our production deployments. The issue is that we are having trouble launching in a Docker container for debugging. Additionally, our AbpLicenseCode
values were invalid. As mentioned, I was able to regenerate a new project with the same name and include in appsettings and this worked.
We did get the app to run with the "Release" environment variable, but the license check still occurred. Is ABP looking at something other than just the ASPNETCORE_ENVIRONMENT
to determine if a license check should occur?
I couldn't get this process to work (is this still a valid option): https://gist.github.com/ebicoglu/f7cd77069fa053cbe9cf9e9ffcc2f2d2
So I did finally get the right AbpLicenseCode
value generated and I was able to start the application by copying that value from a the new ABP project to our existing project. This process was not clearly documented anywhere, but I finally pieced it together from comments from many places.
I do still wonder why I can't get the other approach to work where the access token is copied into the Docker container. I've tried multiple directories. I can confirm the token is copied to the container, but startup always fails the license check with a message that the AbpLicensecode
is missing.
Example comment (though it's a bit old): https://support.abp.io/QA/Questions/69/#answer-00f7ebd2-d7c6-5c6b-e952-39f7557f2968
I'm currently copying the token into two separate locations:
COPY ["access-token.bin", "/root/.abp/cli/"]
COPY ["access-token.bin", "/home/user/.abp/cli/"]
Can anyone explain how to use this access token method of passing the license check?
Hi
Can you set
ASPNETCORE_ENVIRONMENT
to Release and then try?
The container shows "Release" for ASPNETCORE_ENVIRONMENT
value, but I still get:
2023-09-26 13:39:29 [18:39:29 ERR] ABP-LIC-0020 - License code not found! Ensure that your appsettings.json or appsettings.secrets.json has "AbpLicenseCode" key with your license code. 2023-09-26 13:39:29 [18:39:29 ERR] ABP-LIC-ERROR - License check failed for 'Volo.Saas.Domain-v7.0.1.0'. 2023-09-26 13:39:29 2023-09-26 13:39:29 For more information, contact to license@abp.io.
I should note that we have many dependencies. For instance, we've extended the Saas, Identity, and Administration modules. Do all of those need to be built in release also?
I'm trying to get one of our microservices running in a Docker container and I am not able to handle the licensing part. We have a AbpLicenseCode
value, but when I put it in the appsettings file I get:
ABP-LIC-0013 - License exception: ABP-LIC-0023: An error occured while calling the license server! The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
I'm not sure this code ever worked as we've always used the abp login
during development.
Multiple people have reference copying the access-token.bin
file to the Docker container. We're using linux container, and I've tried copying to the /root/.abp/cli/
folder as described here: https://gist.github.com/ebicoglu/f7cd77069fa053cbe9cf9e9ffcc2f2d2. I can inspect the container and confirm that the file is indeed in the right place, but I only receive:
**Error: ABP-LIC-002 -License code not found! Ensure that your appsettings.json or appsettings.secrets.json has "AbpLicenseCode" key with your license code.**
We started out over 2 years ago on a Tiered solution. But we've made many changes including moving to microservice template. I've seen comments about regenerating the project to generate the license code, but I can't get this to work. I just get the same error as above when trying to use a license code from a newly-generated project (ABP-LIC-0013).
Currently, the Dockerfile is the most basic version. We've only added the access token copying so far (Note, this sample is from a demo project, but it's identical to our current file other than the project name/path). Note the fourth line about copying the access token. Again, the token is confirmed to be in that folder in the Docker container.
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
COPY ["access-token.bin", "/root/.abp/cli/"]
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["CarvedRock.Api/CarvedRock.Api.csproj", "CarvedRock.Api/"]
RUN dotnet restore "CarvedRock.Api/CarvedRock.Api.csproj"
COPY . .
WORKDIR "/src/CarvedRock.Api"
RUN dotnet build "CarvedRock.Api.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "CarvedRock.Api.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "CarvedRock.Api.dll"]
Can you share a project that can reproduce the problem? thanks, shiwei.liang@volosoft.com
We can't share the project, but it also can't be reproduced locally. I probably should have mentioned that this is only happening in a hosted environment (Kubernetes cluster on Azure).
We followed: https://docs.abp.io/en/commercial/latest/startup-templates/microservice/synchronous-interservice-communication
I'm really just looking for information about what exactly is happening to get this exception? Is the endpoint simply not found? The not found response always comes back immediately, it's never a timeout situation.
at Volo.Abp.Http.Client.ClientProxying.ClientProxyBase`1.ThrowExceptionForResponseAsync(HttpResponseMessage response)
at Volo.Abp.Http.Client.ClientProxying.ClientProxyBase`1.RequestAsync(ClientProxyRequestContext requestContext)
at Volo.Abp.Http.Client.ClientProxying.ClientProxyBase`1.RequestAsync[T](ClientProxyRequestContext requestContext)
at Volo.Abp.Http.Client.ClientProxying.ClientProxyBase`1.RequestAsync[T](String methodName, ClientProxyRequestTypeValue arguments)
at Volo.Abp.Identity.ClientProxies.IdentityUserClientProxy.CreateAsync(IdentityUserCreateDto input)
at Tryl.InvitationService.Invitations.InvitationsAppService.CreateWithUserAsync(InvitationCreateDto input) in /src/src/InvitationService.Application/Invitations/InvitationsAppServiceExt.cs:line 89
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Authorization.AuthorizationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope)
at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at lambda_method2604(Closure, Object)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
Steps to reproduce the issue: We cannot reliably re-produce the issue as it is intermittent. But what we are currently seeing:
There are three services currently involved: Service A, B, and C
During one process, Service A will call Service B to create a user (not the Identity Service). If required, Service B will then call Service C (which is the Identity Service) to create the user record.
We frequently get Service A return a 404 with this response:
---------- RemoteServiceErrorInfo ----------
{
"code": "NotFound",
"message": "Not Found",
"details": null,
"data": null,
"validationErrors": null
}
However, in some instances, Service A successfully reaches Service B, but Service B has the same type of 404 error reaching Service C.
It is never predictable. Sometimes I'll get 20 successful Service A requests in a row, then several fail. Sometimes they seem to almost alternate between pass/fail. It took us a while to realize that sometimes it was the call between B & C failing and not A & B.
Our assumption is that we have an incorrect configuration either in our ABP application or maybe in our hosting environment. What we're looking for are recommendations on how we could identify what the heck is happening. (In the above stacktrace, this is logging from Service B failing to reach Service C).
The "Not found" response, does that indicate it found the correct API and just not the correct resource? Or could it not reach the target service at all? Any suggestions are appreciated