Wednesday, February 28, 2018

Dockerising an ASP.NET Core 2.0 and MySQL App

In a previous post I showed how you can have an ASP.NET Core 2.0 application work with a containerized MySQL database server. In this post I will take this one step further by also containerizing the ASP.NET Core 2.0 application.

Please go through my previous post before continuing with this tutorial.

We will generate the release version of the application by executing the following command from a terminal window in the root directory of your ASP.NET 2.0 project:

dotnet publish -o dist

The above command instructs the dotnet utility to produce the release version of the application in the dist directory. This results in output similar to the following:

Microsoft (R) Build Engine version 15.5.180.51428 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 315.96 ms for D:\demo\_aspnet\AspCoreMySQL\AspCoreMySQL.csproj.
  Restore completed in 409.11 ms for D:\demo\_aspnet\AspCoreMySQL\AspCoreMySQL.csproj.
  Restore completed in 448.93 ms for D:\demo\_aspnet\AspCoreMySQL\AspCoreMySQL.csproj.
  Restore completed in 476.7 ms for D:\demo\_aspnet\AspCoreMySQL\AspCoreMySQL.csproj.
  AspCoreMySQL -> D:\demo\_aspnet\AspCoreMySQL\bin\Debug\netcoreapp2.0\AspCoreMySQL.dll
  AspCoreMySQL -> D:\demo\_aspnet\AspCoreMySQL\dist\

If you inspect the dist directory, you will see content similar to the following:


The highlighted file in the above screen capture is my main DLL file that is the entry point into the web application.

Let us run the release version of your application. To do this, change directory to the dist directory with the following terminal instruction:

cd dist

You can then run your main DLL file. In my case, this file is AspCoreMySQL.dll. I executed the following command:

dotnet AspCoreMySQL.dll

This generates an understandable error because the application is unable to connect to a database:

Application startup exception: MySql.Data.MySqlClient.MySqlException (0x80004005): Unable to connect to any of the specified MySQL hosts.

This gives us a good idea about what ASP.NET Core 2.0 artifacts need to be copied into a container. We shall simply copy contents of the dist directory into a Docker container that has the dotnet core 2.0 runtime.

return to the root directory of your project by typing the following in a terminal window:

cd ..

We need to create a docker image that will contain the dotnet core 2.0 runtime. A suitable image for this purpose is: microsoft/aspnetcore:2-jessie

Create a text file named Dockerfile.mvc and add to it the following content:

FROM microsoft/aspnetcore:2-jessie
COPY dist /app
WORKDIR /app
EXPOSE 80/tcp
ENTRYPOINT ["dotnet", "AspCoreMySQL.dll"]

Above are instructions to create a Docker image that will contain our ASP.NET Core 2.0 application. I describe each line below:

FROM microsoft/aspnetcore:2-jessie Base image microsoft/aspnetcore:2-jessie will be used
COPY dist /app Contents of the dist directory on the host computer will be copied to directory /app in the container
WORKDIR /app The working directory in the container is /app
EXPOSE 80/tcp Port 80 will be exposed in the container
ENTRYPOINT ["dotnet", "AspCore4Docker.dll"] The main ASP.NET Core 2.0 web application will be launched by executing "dotnet AspCore4Docker.dll"

We will next compose a docker yml file that orchestrates the entire system which involves two containers: a MySQL database server container and a container that holds our application. In the root folder of your application, create a text file named docker-compose-aspnetcore-mysql.yml and add to it the following content:

version: '3'

volumes:
  datafiles:

services:
  db:
    image: mysql:8.0.0
    volumes:
      - datafiles:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_TCP_PORT: 3306

  mvc:
    build:
      context: .
      dockerfile: Dockerfile.mvc
    depends_on:
      - db
    ports:
      - "8888:80"
    restart: always
    environment:
      - DBHOST=db
      - DBPORT=3306
      - DBPASSWORD=secret
      - ASPNETCORE_ENVIRONMENT=Development


Below is an explanation of what this file does.

We will be having two containers. Each container is considered to be a service. The first service is named db and will host MySQL. The second service is named mvc and will host our ASP.NET Core 2.0 web app.

The most current version of docker-compose is version 3. This is the first line in our docker-compose file.

The MySQL Container

Image mysql:8.0.0 will be used for the MySQL container.

A volume named datafiles is declared that will host MySQL data outside of the container. This ensures that even if the MySQL container is decommissioned, data will not be lost.

restart: always is so that if the container stops, it will be automatically restarted.

The root password will be secret when MySQL is configured. This is set by the MYSQL_ROOT_PASSWORD environment variable.

The ASP.NET Core 2.0 Web Application Container

The container will be built using the instructions in the Dockerfile.aspnetcore2 file and the context used is the current directory.

depends_on indicated that the web app relies on the MySQL container (db) to properly function.

Port 80 in the mvc container is mapped to port 8888 on the host computer.

Just like in the db container, restart: always is so that if the container stops, it will be automatically restarted.

The environment variables needed by the web app are:

DBHOST pointing to the MySQL service and  
- ASPNETCORE_ENVIRONMENT set to Development more. In reality, you should change this to Production one you determine that your web app container works as expected.

Running the yml file

To find out if this all works, go to a terminal window and run the following command:

docker-compose -f  docker-compose-aspnetcore-mysql.yml up

Point your browser to http://localhost:8888/ and you should see the main web page. To ensure that the database works properly, register a user by clicking on the Register link in the top right corner.

In my case, I received confirmation that a user was indeed registered:

As you can see in the top-right corner, the user with email a@a.a has been successfully registered.

This opens up a whole new world for containerizing your ASP.NET Core 2.0 web applications.




No comments:

Post a Comment