Series navigation and source code
demand
The most used scenario of. NET 6 Web API application is as a back-end microservice application. In actual projects, we generally publish the application by packaging it into a docker image for better deployment, including the microservice project deployment based on Kubernetes platform.
Generally speaking, applications deployed as microservices are located under a virtual subnet, that is, they are not directly exposed to external users, and the requests go through the internal network, so there are few HTTPS requirements. However, as a demonstration, we will introduce how to implement HTTPS to access applications in docker in this article.
target
Implement the packaging and operation of docker image of application, including HTTPS based access.
Principles and ideas
The implementation idea of application docker image packaging is very simple. Prepare a correct dockerfile, configure HTTPS as needed, and finally build the image correctly.
realization
Implement Docker image packaging
When creating a dockerfile file in the Api project, we generally build the application in two steps: the first step is to compile and publish, and the second step is to copy the published file to the runtime environment, which can reduce the size of the image.
If you are developing a project using Visual Studio or Rider, you can select whether to use Docker support when creating the project. You can select the container environment as Linux, and the project template will automatically generate the correct Dockerfile for us. Or we can right-click the project and select Add Docker support.
The following is the content of our handwritten dockerfile. For the little partners who have little experience in writing dockerfile, the most error prone place is the path problem. Because we have generated the dockefile in the Api project, there is a problem only from the path in the file content, but it doesn't matter. When packaging the image, we can specify the execution context of the dockefile. As long as we execute docker build in the solution directory, there is no problem.
ARG NET_IMAGE=6.0-bullseye-slim FROM mcr.microsoft.com/dotnet/aspnet:${NET_IMAGE} AS base WORKDIR /app EXPOSE 80 EXPOSE 443 ENV ASPNETCORE_ENVIRONMENT=Development FROM mcr.microsoft.com/dotnet/sdk:${NET_IMAGE} AS build WORKDIR /src COPY ["src/TodoList.Api/TodoList.Api.csproj", "TodoList.Api/"] COPY ["src/TodoList.Application/TodoList.Application.csproj", "TodoList.Application/"] COPY ["src/TodoList.Domain/TodoList.Domain.csproj", "TodoList.Domain/"] COPY ["src/TodoList.Infrastructure/TodoList.Infrastructure.csproj", "TodoList.Infrastructure/"] RUN dotnet restore "TodoList.Api/TodoList.Api.csproj" COPY ./src . WORKDIR "/src/TodoList.Api" RUN dotnet build "TodoList.Api.csproj" -c Release -o /app/build FROM build AS publish RUN dotnet publish --no-restore "TodoList.Api.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "TodoList.Api.dll"]
Before constructing the image, there are several small pits to note:
- Temporarily delete the usehttpsreduction Middleware in the Program because we have not configured the HTTPS certificate;
- In the csproj file of the API project, todolist Api. The configuration of the XML file in Debug mode is copied to the Release. Otherwise, an error will be reported: could not find file '/ APP / todolist Api. xml;
- Modify the corresponding Appsettings {env}. For the database connection string in JSON, use the docker network model to obtain other containers. Change localhost to mssql. This name is the name of the container running sql server docker locally. We will use the docker network to allow applications to connect to the database docker container.
Now let's build this image, make sure it is in the solution directory, and pay attention to the last one Indicates the execution context path of the currently selected dockerfile file, i.e. solution directory:
$ docker build -t todo-list -f src/TodoList.Api/Dockerfile .
Generated image:
Run, expose port 80, use the -- link parameter to indicate that the current application container needs to be connected to the network where the database container is located, and use the API client to verify the login request:
$ docker run -p 80:80 --name=todo_list_in_docker --link=mssql -d todo-list 4733f35c2c9558b78e3c7b9281536d8891f19bf87b18fa0ad953e94f7b984184
Request authentication:
Enable HTTPS access
Next, we add HTTPS support to the container. In order to achieve this, of course, we still need to continue to use the usehttpsredirect middleware, and then we need to add a certificate and add this certificate when starting the container.
dotnet dev-certs https -ep ${HOME}/.aspnet/https/aspnetapp.pfx -p Test@Password dotnet dev-certs https --trust
Re build and run the container. This time, we use port 5001 of HTTPS to access the API in the container. We need to expose port 443 in the HTTPS container to the port on the host (I choose port 5001), formulate relevant HTTPS environment variables, specify the certificate, and mount the path to save the certificate on the host into the container for access.
docker run \ -p 80:80 \ -p 5001:443 \ --name=todo_list_in_docker \ --link=mssql \ -e ASPNETCORE_URLS="https://+;http://+" \ -e ASPNETCORE_HTTPS_PORT=5001 \ -e ASPNETCORE_Kestrel__Certificates__Default__Password="Test@Password" \ -e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx \ -v ${HOME}/.aspnet/https:/https/ \ -d \ todo-list
Add docker compose function
Here, we found a troublesome problem that we need to remember these configurations, and we need to manually start the database container and application container respectively each time. We can complete it through docker compose, so we first stop and delete the application container and database container, and start creating a docker compose file in the solution directory:
version: '3.4' services: todo-list: image: todo-list # Configure port forwarding ports: - "80:80" - "5001:443" # Configure container environment variables environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=https://+;http://+ - ASPNETCORE_HTTPS_PORT=5001 - ASPNETCORE_Kestrel__Certificates__Default__Password=Test@Password - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx # Mount certificate path volumes: - ~/.aspnet/https:/https:ro # You need to start the database container first depends_on: - mssql # Todo list responds to the request through the public network and connects to the database container through the private network networks: - private - public mssql: image: mcr.microsoft.com/mssql/server:2019-latest # Port forwarding is configured to directly access the database from the host. If there is no need to directly access the database from the host, you only need to declare that container port 1433 does not forward ports: - "1433:1433" environment: - SA_PASSWORD=StrongPwd123 - ACCEPT_EULA=Y # Mount data directory for persistence volumes: - mssqldata:/var/opt/mssql networks: - private - public # Because the mssqldata path has been created before, you need to declare to use the existing path here volumes: mssqldata: networks: private: public:
Continue to request authentication after running:
$ docker-compose up --build Creating network "todolist_private" with the default driver Creating network "todolist_public" with the default driver Recreating todolist_mssql_1 ... done Recreating todolist_todo-list_1 ... done Attaching to todolist_mssql_1, todolist_todo-list_1 // Omit the following log
Request result:
So far, the demonstration of how to use containers for application packaging and deployment is over. How to apply these steps in Kubernetes and CI/CD will be covered again in the series of microservices later.
summary
The error prone part of docker packaging application lies in the dockerfile path. In addition, if there are other operations in the container, such as installing some third-party agents (such as splunk agent), you also need to operate carefully. For how to Debug Docker Build, you can refer to articles written by others, such as this: Debugging Docker builds.