asp.net core docker实战

作者 : 慕源网 本文共10708个字,预计阅读时间需要27分钟 发布时间: 2022-01-26 共251人阅读

在本教程中,我将在使用 SQL Server 作为后端的 ASP.NET Core 应用程序中执行 CRUD 操作。我将为此使用 Docker Compose,因此将有 2 个容器,一个运行 ASP.NET Core 应用程序和其他 SQL Server 2019。

请注意,此设置对于不想在其 PC 上安装 SQL Server 并且可以节省许可证费用的人非常有用。SQL Server 2019 镜像将从 docker 容器运行,大小约为 350 mb。您甚至可以从 SQL Server Management Studio 连接到此 SQL Server 容器并执行任何类型的工作,例如创建数据库、创建表、运行查询等。

拉取并运行 SQL Server 2019 镜像

打开命令提示符并运行以下命令,该命令将从 Microsoft Container Registry(mcr) 中提取 SQL Server 2019 镜像。

docker pull mcr.microsoft.com/mssql/server:2019-latest

该命令将开始下载大小约为 350 mb 的 sql server 镜像。

本教程是Docker系列ASP.NET Core 应用程序的一部分。

asp.net core docker实战

接下来,使用 SQL Server 下载的镜像运行 Docker 容器。命令如下:

docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=vV5r9tn0M4@" -p 1440:1433 --name mysqlserver -h mysqlserver -d 
mcr.microsoft.com/mssql/server:2019-latest
asp.net core docker实战

上面的命令做了以下事情:

  • 1. 创建一个名为mysqlserver的容器,该容器将运行此 SQL Server 镜像。
  • 2. SQL Server 密码设置为vV5r9tn0M4@。请注意,您设置的密码应该是强密码并且长度至少为 8 个字符。它应该有字母、数字、大写字母和特殊字符的组合。
  • 3. 容器的端口暴露给宿主机。参见-p 1440:1433,这里容器的 1433 端口(第二个值)暴露给主机上的 1440(第一个值)端口。

现在检查您的 docker Desktop,它将显示该容器已启动并正在运行,请参见下图,其中包含我的 docker Desktop的屏幕截图。

asp.net core docker实战

或者,您也可以在命令提示符下运行docker ps以查看该容器处于运行模式。

使用 SSMS 连接到容器上的 SQL Server

现在您可以连接在 docker 容器中运行的 SQL Server。因此,在 SQL Server Management Studio (SSMS) 中,输入以下内容:

  • 1. localhost,1440为服务器名,记得 1440 是我们之前设置的端口。除了 localhost,您还可以编写您的机器 ip,您可以通过运行 ipconfig 命令获得。
  • 2. SA登录。
  • 3. vV5r9tn0M4@为密码。

单击“连接”按钮以连接在容器中运行的此 SQL Server。

asp.net core docker实战

连接后,您可以创建数据库、表、存储过程并执行您通常在数据库中执行的任何其他操作。

更改数据库密码

您还可以通过运行以下给定命令来更改 SQL Server 的密码:

docker exec -it mysqlserver /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "vV5r9tn0M4@" -Q "ALTER LOGIN SA WITH PASSWORD='abD5r9tn0M@4'"

因此,运行此命令后,新密码变为abD5r9tn0M@4

在 ASP.NET Core 应用程序中创建 CRUD 操作

现在让我们通过 ASP.NET Core 应用程序创建 CRUD 操作,该应用程序使用在docker 容器上运行的 SQL Server 。因此,在 Visual Studio 中创建一个新的ASP.NET Core Web 应用程序。

asp.net core docker实战

接下来,为您的应用程序命名,我将其命名为DockerCrud,并取消选中选项Place solution and project in the same directory

asp.net core docker实战

不要选择启用 Docker 支持

接下来,选择名为ASP.NET Core Web App (Model-View-Controller)的模板来创建一个基本的 ASP.NET Core MVC 应用程序。

asp.net core docker实战

Movie Database 和Entity Framework Core

我将在docker容器上运行的 SQL Server 中创建一个名为MovieDB的Movie数据库。将有一个名为Movie的表,在此表中创建、读取、更新和删除操作将从 ASP.NET Core MVC 应用程序执行。数据库创建和 CRUD 操作将由Entity Framework Core (EF Core)执行。

请注意,此处的 ASP.NET Core MVC 应用程序将访问容器上运行的 SQL Server。检查下面描述此架构的图像。

asp.net core docker实战

因此,首先在来自 NuGet 的 ASP.NET Core MVC 应用程序上添加必要的 EF Core 包。这些软件包是:

  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Design
  • Microsoft.EntityFrameworkCore.Tools

接下来,在Models文件夹中创建一个名为Movie.cs的新类。

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
 
namespace DockerCrud.Models
{
    public class Movie
    {
        [Required]
        public int Id { get; set; }
 
        [Required]
        public string Name { get; set; }
 
        [Required]
        public string Actors { get; set; }
    }
}

将另一个名为MovieContext.cs的类添加到Models文件夹。它将用作 EF Core 的数据库上下文。代码如下:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
 
namespace DockerCrud.Models
{
    public class MovieContext : DbContext
    {
        public MovieContext(DbContextOptions<MovieContext> options) : base(options)
        {
        }
 
        public DbSet<Movie> Movie { get; set; }
 
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
        }
 
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
        }
    }
}
控制器设置

现在更新Controllers文件夹中的 HomeController.cs 文件,以包含将执行 CRUD 操作的操作方法。

using DockerCrud.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
 
namespace DockerCrud.Controllers
{
    public class HomeController : Controller
    {
        private MovieContext context;
        public HomeController(MovieContext mc)
        {
            context = mc;
        }
 
        public IActionResult Create()
        {
            return View();
        }
 
        [HttpPost]
        public async Task<IActionResult> Create(Movie m)
        {
            if (ModelState.IsValid)
            {
                context.Add(m);
                await context.SaveChangesAsync();
 
                return RedirectToAction("Index");
            }
            else
                return View();
        }
 
        public IActionResult Index()
        {
            var m = context.Movie.ToList();
            return View(m);
        }
 
        public IActionResult Update(int id)
        {
            var pc = context.Movie.Where(a => a.Id == id).FirstOrDefault();
            return View(pc);
        }
 
        [HttpPost]
        public async Task<IActionResult> Update(Movie m)
        {
            if (ModelState.IsValid)
            {
                context.Update(m);
                await context.SaveChangesAsync();
 
                return RedirectToAction("Index");
            }
            else
                return View(m);
        }
 
        [HttpPost]
        public async Task<IActionResult> Delete(int id)
        {
            var pc = context.Movie.Where(a => a.Id == id).FirstOrDefault();
            context.Remove(pc);
            await context.SaveChangesAsync();
 
            return RedirectToAction("Index");
        }
    }
}
UI 视图

之后在Views >> Home控制器中创建 3 个视图(Index.cshtml、Create.cshtml、Update.cshtml) 。这些视图将构成 CRUD 操作的 UI。

1. Index.cshtml

@model List<Movie>
 
@{
    ViewData["Title"] = "Movies";
}
 
<h1 class="bg-info text-white">Movies</h1>
<a asp-action="Create" class="btn btn-secondary">Create a Movie</a>
 
<table class="table table-sm table-bordered">
    <tr>
        <th>Id</th>
        <th>Name</th>
        <th>Actors</th>
        <th></th>
        <th></th>
    </tr>
    @foreach (Movie m in Model)
    {
        <tr>
            <td>@m.Id</td>
            <td>@m.Name</td>
            <td>@m.Actors</td>
            <td>
                <a class="btn btn-sm btn-primary" asp-action="Update" asp-route-id="@m.Id">
                    Update
                </a>
            </td>
            <td>
                <form asp-action="Delete" asp-route-id="@m.Id" method="post">
                    <button type="submit" class="btn btn-sm btn-danger">
                        Delete
                    </button>
                </form>
            </td>
        </tr>
    }
</table>

2.Create.cshtml

@model Movie
 
@{
    ViewData["Title"] = "Create a Movie";
}
 
<h1 class="bg-info text-white">Create a Movie</h1>
<a asp-action="Index" class="btn btn-secondary">View all Movies</a>
 
<div asp-validation-summary="All" class="text-danger"></div>
 
<form method="post" enctype="multipart/form-data">
    <div class="form-group">
        <label asp-for="Name"></label>
        <input type="text" asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Actors"></label>
        <input type="text" asp-for="Actors" class="form-control" />
        <span asp-validation-for="Actors" class="text-danger"></span>
    </div>
    <button type="submit" class="btn btn-primary">Create</button>
</form>

3.Update.cshtml

@model Movie
 
@{
    ViewData["Title"] = "Update a Movie";
}
 
<h1 class="bg-info text-white">Update a Movie</h1>
<a asp-action="Index" class="btn btn-secondary">View all Movies</a>
 
<div asp-validation-summary="All" class="text-danger"></div>
 
<form method="post" enctype="multipart/form-data">
    <div class="form-group">
        <label asp-for="Id"></label>
        <input type="text" asp-for="Id" readonly class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Name"></label>
        <input type="text" asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Actors"></label>
        <input type="text" asp-for="Actors" class="form-control" />
        <span asp-validation-for="Actors" class="text-danger"></span>
    </div>
    <button type="submit" class="btn btn-primary">Update</button>
</form>

Entity Framework Core Migration

打开appsettings.json文件并创建到 SQL Server 数据库的连接字符串。数据源应该是localhost、1440和 Initial Catalog 是数据库的名称。您可以为数据库命名任何您喜欢的名称。

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=localhost,1440;Initial Catalog=MovieDB;Persist Security Info=True;User ID=SA;Password=vV5r9tn0M4@"
  }
}

而不是 localhost 你可以写你的电脑的IP地址。通过在命令提示符下运行ipconfig命令可以查看 IP 地址。我的电脑的 IP 地址是192.168.1.100。所以,我可以在我的连接字符串上使用它,如下所示。

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=192.168.1.100,1440;Initial Catalog=MovieDB;Persist Security Info=True;User ID=SA;Password=vV5r9tn0M4@"
  }
}

接下来,转到Startup.cs文件并将数据库上下文添加为服务。检查下面突出显示的代码。

using DockerCrud.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
 
namespace DockerCrud
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
 
        public IConfiguration Configuration { get; }
 
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<MovieContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            services.AddControllersWithViews();
        }
 
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            …
        }
    }
}

最后,您需要运行 EF Core Migration命令。因此,在 VS 中打开 Package Manager Console 窗口并转到Startup.cs类的目录,然后运行以下 2 个命令。

dotnet ef migrations add Migration1
dotnet ef database update

这将在容器中运行的 SQL Server 上创建名为MovieDB的数据库,现在您可以使用 ASP.NET Core MVC 应用程序执行 CRUD 操作。

测试 CRUD 操作

现在是时候测试 CRUD 操作是否正常工作了。在 vs 中运行 ASP.NET Core MVC 应用程序并转到创建电影部分,输入电影名称及其演员(用逗号分隔),然后单击创建按钮。电影记录将被插入到数据库中。请参阅下图,我在其中展示了这个东西。

asp.net core docker实战

接下来,单击更新链接并在文本框中输入新值。然后点击更新按钮更新记录。检查下面的屏幕截图,我在其中显示了更新过程。

asp.net core docker实战

接下来单击记录上的删除按钮以将其删除。检查以下屏幕截图:

asp.net core docker实战

我们已经成功测试了运行良好的 CRUD 操作。

适用于 ASP.NET Core 应用程序和 SQL Server 2019 的 Docker Compose

现在,我将使用 Docker Compose 在多容器中运行我们刚刚构建的 ASP.NET Core MVC 应用程序和 SQL Server 2019。

右键单击解决方案资源管理器中的项目名称,然后选择容器编排器支持。

asp.net core docker实战

接下来,在打开的新窗口中选择“Docker Compose”。

asp.net core docker实战

接下来,选择目标操作系统为 Linux,然后单击确定按钮。

asp.net core docker实战

这将在解决方案资源管理器上添加一个名为 docker-compose 的新项目。

打开您将在 docker-compose 项目中找到的 docker-compose.yml文件并添加新服务并将其命名为sqldata

asp.net core docker实战

指定镜像为sql server 2019,密码和端口。请参阅下面给出的突出显示的代码。

version: '3.4'
 
services:
  dockercrud:
    image: ${DOCKER_REGISTRY-}dockercrud
    build:
      context: .
      dockerfile: DockerCrud/Dockerfile
   
  sqldata:
    image: mcr.microsoft.com/mssql/server:2019-latest
    environment:
      - SA_PASSWORD=vV5r9tn0M4@
      - ACCEPT_EULA=Y
    ports:
      - "1450:1433"

注意端口“1450:1433”,第一个端口是主机的端口,第二个是运行sql server的容器的端口。我使用了不同的端口 1450 而不是以前的 1440 端口,它已经运行了 sql 服务器。更清楚地说,这里使用的 SQL Server 与上一个不同。因此,我们必须从 Entity Framework Core Migration 命令创建数据库。我马上就做。

保存 yml 文件后,docker 将创建 2 个容器——一个将运行 ASP.NET Core MVC 应用程序,另一个将运行 SQL Server。下图解释了这件事。

asp.net core docker实战

您可以在 docker Desktop上看到这些多容器启动并运行。

asp.net core docker实战

接下来,通过将端口更改为 1450,将此appsettings.json文件中的连接字符串更改为这个新的 SQL Server。

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=sqldata;Initial Catalog=MovieDB;Persist Security Info=True;User ID=SA;Password=vV5r9tn0M4@"
  }
}

请注意,这里我提供了Data Source=sqldata,它是 docker-compose.yml 文件中 SQL Server 的服务名称。这样做是因为 docker compose 中的容器可以通过名称相互通信。

这是一个很大的解脱,因为我们现在不必输入 IP 地址。

运行EF Core Migrations

EF Core migrations 将在 SQL Server 上创建数据库。执行migrations 时有一个问题,您必须更改数据库字符串以使用localhost、1450而不是 sqldata,因为 EF Core应该知道需要执行migrations 到哪个数据库。因此更新的连接字符串应该是:

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=localhost,1450;Initial Catalog=MovieDB;Persist Security Info=True;User ID=SA;Password=vV5r9tn0M4@"
  }
}

现在在包管理器控制台窗口中,从Startup.cs文件的目录中运行以下 2 个命令。

dotnet ef migrations add Migration2
dotnet ef database update

迁移完成后,将连接字符串恢复为:

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=sqldata;Initial Catalog=MovieDB;Persist Security Info=True;User ID=SA;Password=vV5r9tn0M4@"
  }
}
还要注意的一件事是数据库容器应该处于运行模式,否则迁移将不会运行。如果它们没有运行,则按 F6 构建应用程序,这将运行数据库容器,然后您的迁移将成功运行。

运行APP

现在您可以在 Visual Studio 中运行您的应用程序并开始执行 CRUD 操作。

我制作了一个 15 秒的小视频来展示它的工作原理。

如果您想直接在浏览器上运行应用程序而不借助 Visual Studio,那么您需要公开端口并生成 HTTPS 开发证书。然后需要使用 Docker Volume 将此证书映射到容器。我在之前的 Docker 教程中已经完成了这些事情。如果您想了解这些步骤,请遵循为 HTTPS 公开端口和配置环境变量

下载源代码:

下载

结论

在本教程中,您学习了如何使用 SQL Server 2019 镜像创建 docker 容器。如果您不想在系统上安装 sql server,此过程会很有帮助。您还学习了如何使用 SQL Server 2019 容器运行数据库驱动的 ASP.NET Core MVC 应用程序。为此,我们使用了 Docker Compose。

如果您喜欢阅读本教程,请务必通过在您的微博、微信分享来做一些宣传。

 


慕源网 » asp.net core docker实战

常见问题FAQ

程序仅供学习研究,请勿用于非法用途,不得违反国家法律,否则后果自负,一切法律责任与本站无关。
请仔细阅读以上条款再购买,拍下即代表同意条款并遵守约定,谢谢大家支持理解!

发表评论

开通VIP 享更多特权,建议使用QQ登录