Создаем свое первое ASP.NET Core приложение с использованием Docker

Создаем свое первое ASP.NET Core приложение с использованием Docker

Docker уже де-факто стал стандартом для приложений, пора разобрать то, как использовать свои ASP.NET Core приложения в докере.

lets start

Создаем проект с помощью CLI

Для начала создадим solution. Для этого как матерые ребята воспользуемся .net CLI.

Открываем папку, где хотим создать решение и выполняем следующую команду в cmd:

dotnet new sln

sln

После создадим пустой веб проект с помощью команды:

dotnet new web -n WebApi

new proj

Теперь добавим новый проект, который мы создали в наш sln

dotnet sln IpLookup.sln add WebApi/WebApi.csproj

add

Конфигурация приложения

Когда все готово, откроем наш проект с помощью VS Code. Создадим наш первый контроллер, для этого добавим папку:

folder

И добавим апи контроллер:

namespace WebApi.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class IpController : ControllerBase
    {
        [HttpGet("{ip}")]
        public ActionResult Get(string ip)
        {
            return NoContent();
        }
    }
}

Давайте теперь запустим код, с помощью .net cli. для этого нужно выполнить следующий код:

dotnet run --project webapi/WebApi.csproj

run

Как видим, с записей в консоли, проект успешно запущен на 5000 порту, давайте откроем его в браузере:

hello world

Браузер нам вывел Hello Worldна экран

Почему?

Если мы посмотрим в стандартный Startup класс, который сгенерировал CLI

public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }
    }

То увидим, что у нас есть стандартная обработка / роута.

Окей, теперь нам нужно оживить наш проект, давайте добавим использование AddMvcCore сервиса.

Остановим наш аппликейшин, для этого достаточно нажать ctrl + c в терминале VS Code

stop

Подключим нужные nuget пакеты, а именно Microsoft.AspNetCore.All, Microsoft.AspNetCore.Mvc.NewtonsoftJson

И добавим фильтр для автоматической проверки ModelState и возврата BadRequest, в случае если ModelState.IsValid = false.

public class ModelStateValidationActionFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            base.OnActionExecuting(context);
            var modelState = context.ModelState;
            if (!modelState.IsValid)
            {
                context.Result = new BadRequestObjectResult(modelState);
            }
        }
    }

Модифицируем Program класс

 public class Program
    {
        public static void Main(string[] args)
        {
            WebHost.CreateDefaultBuilder(args)
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>().Build().Run();
        }
    }

И Startup.cs, который будет выглядеть следующим образом:

public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddResponseCompression();
            services.Configure<GzipCompressionProviderOptions>(options =>
            {
                options.Level = CompressionLevel.Fastest;
            });
            services.AddMvcCore(options =>
            {
                options.Filters.Add(new ApiControllerAttribute());
                options.Filters.Add(new ModelStateValidationActionFilterAttribute());
                options.EnableEndpointRouting = false;
            })
                .AddFormatterMappings()
                .AddCors(options =>
                {
                    options.AddPolicy("AllowAll",
                        builder =>
                        {
                            builder
                                .AllowAnyMethod()
                                .AllowAnyHeader()
                                .AllowCredentials();
                        });
                }).AddApiExplorer()
                .AddNewtonsoftJson()
                .AddDataAnnotations()
                .AddAuthorization().SetCompatibilityVersion(CompatibilityVersion.Latest);
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", true, true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true);
            var configuration = builder.Build();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseResponseCompression();
            app.UseDefaultFiles();
            app.UseStaticFiles();
            app.UseCors("AllowAll");
            app.UseAuthentication();
            app.UseMvc();
        }
    }
}

Запускаем проект и тестируем наш API. Для этого откроем postman и сделаем запрос на наш Endpoint:

postman test

Отлично. как видите. мы получили ответ с нужным статус кодом.

Docker

Теперь давайте "обернем" наш проект в докер контейнер.

Для этого создадим DockerFile с следующим содержимым:

FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build
WORKDIR /app

# copy csproj and restore as distinct layers

COPY *.csproj ./
RUN dotnet restore

# copy everything else and build app
COPY /. ./
WORKDIR /app/
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 AS runtime
WORKDIR /app
COPY --from=build /app/out ./
ENTRYPOINT ["dotnet", "WebApi.dll"]

Так как мы будем запускать контейнеры в Linux, убедитесь, что вы перевели ваш docker в линукc режим

Теперь сбилдим наше локальное приложение с помощью команды

docker build -t iplookup .

(или docker build -t iplookup ./webapi если вы находитесь в корневой папке)

Обратите внимание, точка указывает на то, что Dockerfile находиться в той же директории, где вы запускаете команду. Когда я первый раз работал с докером, не мог понять, что же не так с командой, оказалось что я просто удалял эту точку, когда копировал команду, думая что она не нужна.

Теперь запустим наше приложение и выполним команду для просмотра активных контейнеров

docker run -d -p 8080:80 --name IpLookup iplookup
docker ps

После выполнения команд, должна появиться следующая информация в консоли:

docker ps

И если мы откроем Docker плагин в VS code, то увидим что должен появиться новый контейнер и image:

containers docker

Теперь протестируем тот же API, но через Docker контейнер, для этого нужно сделать на этот http://localhost:8080/api/ip/231321 эндпоинт

docker test in postman

Как видим, результат тот же, как и в случае с обычным дебагом через dotnet run

Проект, который использовался в статье можно скачать тут.

В следующей статье мы рассматриваем как подключить MongoDB к нашему проекту и разберемся что такое docker compose.

0 31 30.11.2019 16:37

Комментарии:

Пожалуйста авторизируйтесь, чтобы получить возможность оставлять комментарии