使用 Docker 和 Kubernetes 将 React JS 和 .NET Core 应用容器化
一. 简介
本文将创建一个使用 .NET Core Web API 和 React JS 网页表单的示例产品应用程序后端。我们还将借助 Docker 和 Kubernetes 对其进行容器化。
二. 议程
-
示例产品应用程序后端(.NET Core Web API) -
示例产品应用程序前端(React JS) -
应用程序的 Docker 文件 -
容器化应用程序
三. 先决条件
-
Visual Studio -
Docker Desktop(包含 Kubernetes) -
NPM -
.NET Core SDK -
React JS
四. 示例产品应用程序:后端(.NET Core Web API)
步骤 1:创建新的产品管理 .NET Core Web API
在 Visual Studio 中,创建一个新的 ASP.NET Core Web API 项目。
步骤 2:安装 NuGet 包
安装以下 NuGet 包以支持内存数据库:
步骤 3:添加产品类
在 Entities
文件夹中添加 Product
类。
namespace ProductManagementAPI.Entities
{
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
}
步骤 4:创建 AppDbContext 类
在 Data
文件夹中创建 AppDbContext
类,并使用内存连接和 DB 集合属性。
using Microsoft.EntityFrameworkCore;
using ProductManagementAPI.Entities;
namespace ProductManagementAPI.Data
{
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseInMemoryDatabase("InMemoryDb");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 可选择在此配置实体映射
}
}
}
步骤 5:添加产品仓库
在 Repositories
文件夹中添加 IProductRepository
接口和 ProductRepository
实现。
IProductRepository
using ProductManagementAPI.Entities;
namespace ProductManagementAPI.Repositories
{
public interface IProductRepository
{
Task<List<Product>> GetAllProductsAsync();
Task<Product> GetProductByIdAsync(int id);
Task AddProductAsync(Product product);
Task UpdateProductAsync(Product product);
Task DeleteProductAsync(int id);
}
}
ProductRepository
using Microsoft.EntityFrameworkCore;
using ProductManagementAPI.Data;
using ProductManagementAPI.Entities;
namespace ProductManagementAPI.Repositories
{
public class ProductRepository : IProductRepository
{
private readonly AppDbContext _context;
public ProductRepository(AppDbContext context)
{
_context = context;
}
public async Task<List<Product>> GetAllProductsAsync()
{
return await _context.Products.ToListAsync();
}
public async Task<Product> GetProductByIdAsync(int id)
{
return await _context.Products
.AsNoTracking()
.FirstOrDefaultAsync(p => p.Id == id);
}
public async Task AddProductAsync(Product product)
{
if (product == null)
{
throw new ArgumentNullException(nameof(product));
}
_context.Products.Add(product);
await _context.SaveChangesAsync();
}
public async Task UpdateProductAsync(Product product)
{
if (product == null)
{
throw new ArgumentNullException(nameof(product));
}
_context.Entry(product).State = EntityState.Modified;
await _context.SaveChangesAsync();
}
public async Task DeleteProductAsync(int id)
{
var product = await _context.Products.FindAsync(id);
if (product == null)
{
throw new KeyNotFoundException("Product not found.");
}
_context.Products.Remove(product);
await _context.SaveChangesAsync();
}
}
}
步骤 6:创建产品控制器
创建一个新的产品控制器,定义不同的操作方法。
using Microsoft.AspNetCore.Mvc;
using ProductManagementAPI.Entities;
using ProductManagementAPI.Repositories;
namespace ProductManagementAPI.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductRepository _repository;
public ProductsController(IProductRepository repository)
{
_repository = repository;
}
[HttpGet]
public async Task<IActionResult> GetAllProducts()
{
var products = await _repository.GetAllProductsAsync();
return Ok(products);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetProductById(int id)
{
var product = await _repository.GetProductByIdAsync(id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
[HttpPost]
public async Task<IActionResult> AddProduct([FromBody] Product product)
{
if (product == null)
{
return BadRequest();
}
await _repository.AddProductAsync(product);
return CreatedAtAction(nameof(GetProductById), new { id = product.Id }, product);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateProduct(int id, [FromBody] Product product)
{
if (product == null || id != product.Id)
{
return BadRequest();
}
await _repository.UpdateProductAsync(product);
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteProduct(int id)
{
await _repository.DeleteProductAsync(id);
return NoContent();
}
}
}
步骤 7:注册服务并配置中间件
在 Program.cs
中注册服务并配置中间件。
using Microsoft.EntityFrameworkCore;
using ProductManagementAPI.Data;
using ProductManagementAPI.Repositories;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IProductRepository, ProductRepository>();
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("InMemoryDb"));
builder.Services.AddCors(options =>
{
options.AddPolicy("CORSPolicy", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
});
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseCors("CORSPolicy");
app.UseSwagger();
app.UseSwaggerUI();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
步骤 8:运行应用程序
最后,运行应用程序并使用 Swagger UI 执行不同的 API 端点。
五. 示例产品应用程序:前端(React JS)
让我们创建一个客户端应用程序,使用 React JS 并消费上述 API 端点。
步骤 1:创建新的 React JS 应用程序
使用以下命令创建新的 React 应用程序。
npx create-react-app react-netcore-crud-app
步骤 2:导航到项目目录
cd react-netcore-crud-app
步骤 3:安装 Axios 和 Bootstrap
安装 Axios 以消费后端 API,安装 Bootstrap 用于设计。
npm install axios
npm install bootstrap
步骤 4:添加组件和服务
产品列表组件
// src/components/ProductList/ProductList.js
import React, { useState, useEffect } from 'react';
import ProductListItem from './ProductListItem';
import productService from '../../services/productService';
const ProductList = () => {
const [products, setProducts] = useState([]);
useEffect(() => {
fetchProducts();
}, []);
const fetchProducts = async () => {
try {
const productsData = await productService.getAllProducts();
setProducts(productsData);
} catch (error) {
console.error('Error fetching products:', error);
}
};
const handleDelete = async (id) => {
try {
await productService.deleteProduct(id);
fetchProducts(); // 刷新产品列表
} catch (error) {
console.error('Error deleting product:', error);
}
};
const handleEdit = () => {
fetchProducts(); // 刷新产品列表以反映编辑
};
return (
<div className="container">
<h2 className="my-4">Product List</h2>
<ul className="list-group">
{Array.isArray(products) && products.length > 0 ? (
products.map(product => (
<ProductListItem key={product.id} product={product} onDelete={() => handleDelete(product.id)} onEdit={handleEdit} />
))
) : (
<p>No products available</p>
)}
</ul>
</div>
);
};
export default ProductList;
产品列表项组件
// src/components/ProductList/Product
ListItem.js
import React from 'react';
const ProductListItem = ({ product, onDelete, onEdit }) => {
return (
<li className="list-group-item d-flex justify-content-between align-items-center">
<div>
<strong>{product.name}</strong> - ${product.price.toFixed(2)}
</div>
<div>
<button className="btn btn-danger btn-sm" onClick={onDelete}>Delete</button>
<button className="btn btn-warning btn-sm ms-2" onClick={onEdit}>Edit</button>
</div>
</li>
);
};
export default ProductListItem;
步骤 5:创建服务以消费 API
在 src/services
目录中创建 productService.js
文件。
// src/services/productService.js
import axios from 'axios';
const apiUrl = 'https://localhost:5001/api/products'; // 替换为您的后端 API URL
const getAllProducts = async () => {
const response = await axios.get(apiUrl);
return response.data;
};
const addProduct = async (product) => {
await axios.post(apiUrl, product);
};
const deleteProduct = async (id) => {
await axios.delete(`${apiUrl}/${id}`);
};
const productService = {
getAllProducts,
addProduct,
deleteProduct
};
export default productService;
步骤 6:更新主组件
在 src/App.js
中导入和使用 ProductList
组件。
import React from 'react';
import ProductList from './components/ProductList/ProductList';
const App = () => {
return (
<div className="App">
<header className="App-header">
<h1>Product Management</h1>
</header>
<ProductList />
</div>
);
};
export default App;
步骤 7:启动 React 应用
使用以下命令启动 React 应用。
npm start
六. 应用程序的 Docker 文件
为 .NET Core Web API 和 React JS 创建 Docker 文件。
.NET Core Dockerfile
# 使用 .NET SDK 镜像构建应用程序
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /app
COPY *.sln .
COPY *.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o out
# 使用 ASP.NET Core 运行时镜像部署应用程序
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build /app/out .
ENTRYPOINT ["dotnet", "ProductManagementAPI.dll"]
React Dockerfile
# 使用 Node.js 镜像构建 React 应用程序
FROM node:16 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 使用 Nginx 运行 React 应用程序
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
七. 容器化应用程序
使用 Docker Compose 管理应用程序的容器。
docker-compose.yml
version: '3.4'
services:
webapi:
image: productmanagementapi
build:
context: .
dockerfile: ProductManagementAPI/Dockerfile
ports:
- "5000:80"
reactapp:
image: reactproductapp
build:
context: .
dockerfile: react-netcore-crud-app/Dockerfile
ports:
- "3000:80"
步骤 1:构建和运行 Docker 容器
在项目根目录下运行以下命令。
docker-compose up --build
步骤 2:访问应用程序
-
.NET Core Web API:访问 http://localhost:5000/api/products
-
React 应用:访问 http://localhost:3000
八. 使用 Kubernetes 部署
为应用程序创建 Kubernetes 部署和服务。
k8s-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: product-management
spec:
replicas: 1
selector:
matchLabels:
app: product-management
template:
metadata:
labels:
app: product-management
spec:
containers:
- name: webapi
image: productmanagementapi
ports:
- containerPort: 80
- name: reactapp
image: reactproductapp
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: product-management-service
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
selector:
app: product-management
步骤 1:应用 Kubernetes 配置
在 Kubernetes 集群中应用配置。
kubectl apply -f k8s-deployment.yaml
步骤 2:访问 Kubernetes 服务
使用以下命令获取服务的外部 IP 和端口。
kubectl get svc
九. 结论
通过本教程,我们创建了一个使用 .NET Core Web API 和 React JS 的简单产品管理应用程序,并使用 Docker 和 Kubernetes 进行了容器化和部署。这为构建可扩展和高效的 Web 应用程序奠定了基础。
您可以根据需要添加更多功能,如身份验证、授权等,以增强应用程序的安全性和功能性。
希望这个完整的示例能帮助您在项目中应用 .NET Core Web API 和 React JS 的知识,并有效利用 Docker 和 Kubernetes。