zoukankan      html  css  js  c++  java
  • 【ASP.NET Core分布式项目实战】(五)Docker制作dotnet core控制台程序镜像

    Docker制作dotnet core控制台程序镜像

    基于dotnet SDK

    1. 新建控制台程序
      mkdir /home/console
      cd /home/console
      dotnet new console
      dotnet restore
    2. 创建 Dockerfile 文件,参考https://github.com/dotnet/dotnet-docker/blob/master/samples/aspnetapp/Dockerfile
      vim /home/console/Dockerfile
      
      # ------
      
      FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
      WORKDIR /app
      
      COPY . /app
      
      RUN dotnet run
    3. 构建镜像

      docker build -t wyt/console:dev .
    4. 运行容器
      dotnet run --name console-dev wyt/console

    基于dotnet Runtime

    1. 新建控制台程序
      mkdir /home/console
      cd /home/console
      dotnet new console
      dotnet restore
      using System;
      using System.Threading;
      
      namespace console
      {
          class Program
          {
              static void Main(string[] args)
              {
                  Console.WriteLine("Hello World from docker!");
      
                  Thread.Sleep(Timeout.Infinite);
              }
          }
      }
      View Code
    2. 创建 Dockerfile 文件
      FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
      WORKDIR /code
      
      COPY *.csproj /code
      RUN dotnet restore
      
      COPY . /code
      RUN dotnet publish -c Release -o out
      
      FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
      WORKDIR /app
      COPY --from=build /code/out /app
      ENTRYPOINT ["dotnet", "console.dll"]
    3. 构建镜像
      docker build -t wyt/console:prod .
    4. 运行容器
      docker run --name=console-prod wyt/console:prod

    镜像大小对比

    docker images
    REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
    wyt/console                            prod                d2c683338197        3 minutes ago       260MB
    wyt/console                            dev                 93b346366bc5        20 minutes ago      1.74GB
    mcr.microsoft.com/dotnet/core/sdk      2.2                 155911c343f3        11 days ago         1.74GB
    mcr.microsoft.com/dotnet/core/aspnet   2.2                 c56aab97bc42        11 days ago         260MB

    Mysql EF Core 快速构建 web api

    1. 新建文件夹beta,创建WebAPI项目User.API,添加EFCore引用
      Install-Package MySql.Data.EntityFrameworkCore
    2. 新建文件夹Data、Models 
      新建 AppUser.cs 
      namespace User.API.Models
      {
          public class AppUser
          {
              public int Id { get; set; }
              public string Name { get; set; }
              public string Company { get; set; }
              public string Title { get; set; }
          }
      }
      View Code

      新建 UserContext.cs 

      namespace User.API.Data
      {
          public class UserContext:DbContext
          {
              public UserContext(DbContextOptions<UserContext> options) : base(options)
              { }
              
              public DbSet<AppUser> Users { get; set; }
      
              protected override void OnModelCreating(ModelBuilder modelBuilder)
              {
                  modelBuilder.Entity<AppUser>().ToTable(nameof(Users)).HasKey(t => t.Id);
      
                  base.OnModelCreating(modelBuilder);
              }
          }
      }
      View Code
    3. 修改 Startup.cs 
      namespace User.API
      {
          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<UserContext>(options =>
                  {
                      options.UseMySQL(Configuration.GetConnectionString("MysqlUser"));
                  });
      
      
                  services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
              }
      
              // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
              public void Configure(IApplicationBuilder app, IHostingEnvironment env)
              {
                  if (env.IsDevelopment())
                  {
                      app.UseDeveloperExceptionPage();
                  }
      
                  app.UseMvc();
      
                  InitDatabase(app);
              }
      
              public void InitDatabase(IApplicationBuilder app)
              {
                  using (var scope=app.ApplicationServices.CreateScope())
                  {
                      var userContext = scope.ServiceProvider.GetRequiredService<UserContext>();
                      //userContext.Database.Migrate();
                      if (userContext.Users.Count()==0)
                      {
                          userContext.Users.Add(new AppUser()
                          {
                              Name = "wyt"
                          });
                          userContext.SaveChanges();
                      }
                  }
              }
          }
      }
      View Code
    4. 修改 appsettings.json 添加数据库配置
      "ConnectionStrings": {
        "MysqlUser": "Server=192.168.103.240;Port=3306;Database=beta_user;Uid=root;Pwd=pwd123456"
      }
    5. 生成数据库

      Add-Migration init
      Update-Database
    6. 修改 ValuesController.cs 加入依赖注入
      namespace User.API.Controllers
      {
          [Route("api/[controller]")]
          [ApiController]
          public class ValuesController : Controller
          {
              private UserContext _userContext;
      
              public ValuesController(UserContext userContext)
              {
                  _userContext = userContext;
              }
      
              // GET api/values
              [HttpGet]
              public async  Task<IActionResult> Get()
              {
                  return Json(await _userContext.Users.FirstOrDefaultAsync(u => u.Name == "wyt"));
              }
          }
      }
      View Code
    7. 访问api

    ASPNETCORE WEB API与MYSQL互联

    • 修改 appsettings.json 与 appsettings.Development.json ,采用不同配置
      //appsettings.json
      
      {
        "Logging": {
          "LogLevel": {
            "Default": "Warning"
          }
        },
        "AllowedHosts": "*",
        "ConnectionStrings": {
          "MysqlUser": "Server=db;Port=3306;Database=beta_user;Uid=root;Pwd=pwd123456"
        }
      }
      
      //appsettings.Development.json
      
      {
        "Logging": {
          "LogLevel": {
            "Default": "Debug",
            "System": "Information",
            "Microsoft": "Information"
          }
        },
        "ConnectionStrings": {
          "MysqlUser": "Server=47.111.84.191;Port=3306;Database=beta_user;Uid=root;Pwd=pwd123456"
        }
      }
    • 修改 Program.cs 设置80端口

      public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
          WebHost.CreateDefaultBuilder(args)
              .UseUrls("http://*:80")
              .UseStartup<Startup>();
    • 创建 Dockerfile 

      FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
      WORKDIR /code
      COPY *.csproj ./
      RUN dotnet restore
      
      COPY . ./
      RUN dotnet publish -c Release -o out
      
      FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
      WORKDIR /app
      COPY --from=build /code/out ./
      
      EXPOSE 80
      
      ENTRYPOINT ["dotnet", "User.API.dll"]
    • 拷贝到Linux服务器上,并执行下方命令创建镜像

      docker build -t wyt/aspnetcore:pred .
      [root@localhost User.API]# docker build -t wyt/aspnetcore:pred .
      Sending build context to Docker daemon  1.265MB
      Step 1/11 : FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
       ---> 155911c343f3
      Step 2/11 : WORKDIR /code
       ---> Using cache
       ---> 3e2cb7223b3b
      Step 3/11 : COPY *.csproj ./
       ---> 6f6d88b83c75
      Step 4/11 : RUN dotnet restore
       ---> Running in c538c0a59636
        Restore completed in 3.85 sec for /code/User.API.csproj.
      Removing intermediate container c538c0a59636
       ---> 6e45bd786a9c
      Step 5/11 : COPY . ./
       ---> 50ac66ac3f97
      Step 6/11 : RUN dotnet publish -c Release -o out
       ---> Running in 9febf9972a3d
      Microsoft (R) Build Engine version 16.1.76+g14b0a930a7 for .NET Core
      Copyright (C) Microsoft Corporation. All rights reserved.
      
        Restore completed in 667.65 ms for /code/User.API.csproj.
        User.API -> /code/bin/Release/netcoreapp2.2/User.API.dll
        User.API -> /code/out/
      Removing intermediate container 9febf9972a3d
       ---> a7c92c3fd98b
      Step 7/11 : FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
       ---> c56aab97bc42
      Step 8/11 : WORKDIR /app
       ---> Using cache
       ---> 12d1df98dc50
      Step 9/11 : COPY --from=build /code/out ./
       ---> Using cache
       ---> b901e53b64f8
      Step 10/11 : EXPOSE 80
       ---> Using cache
       ---> c61ad551fa76
      Step 11/11 : ENTRYPOINT ["dotnet", "User.API.dll"]
       ---> Running in 36c66859c548
      Removing intermediate container 36c66859c548
       ---> 063fc4fe64ed
      Successfully built 063fc4fe64ed
      Successfully tagged wyt/aspnetcore:pred
      View Code
    • 运行容器,进行端口映射和容器关联

      docker run -d -p 8002:80 --name aspnetcore --link mysql01:db wyt/aspnetcore:pred
    • 成功访问
       

    Docker Network

    1. 创建新的桥接网段
      # 创建mybridge桥接网段
      docker network create -d bridge mybridge
      # 显示网络信息
      docker network ls
    2. 通过桥接网络创建新的 aspnetcore 容器
      # 删除之前创建的容器
      docker rm aspnetcore -f
      # 使用mybridge桥接网段创建新的容器
      docker run -d -p 8002:80 --net mybridge --name aspnetcore wyt/aspnetcore:pred
      我们可以通过命令查看容器 aspnetcore 的ip信息,为172.17.0.4
      docker inspect aspnetcore
    3. 将 mybridge 桥接网段与 mysql01 进行桥接
      # 将mybridge网段与mysql01所在网段进行桥接
      docker network connect mybridge mysql01

      这时可以查看 mysql01 的ip,然后进入 aspnetcore 容器内尝试是否可以ping通

      docker exec -it aspnetcore bash
      apt-get update -y
      apt-get install iputils-ping -y
      apt-get install net-tools -y
      ping 172.18.0.3
    4. 由于我们没有进行数据卷映射,所以配置文件无法更改,备注: appsettings.json 中使用的数据库为db,所以我们只能将 mysql01 改为 db 

      # 容器重命名
      docker rename mysql01 db

       方法二

      # 进入容器
      docker exec -it aspnetcore bash
      ls
      apt-get install vim -y
      # 修改配置
      vim appsettings.json
      exit
      # 重启容器
      docker restart aspnetcore
    5. 完成
      curl http://47.111.84.191:8002/api/values

      或者访问

    制作 docker compose

    1. 修改User.API项目
      # Startup.cs
      public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
      {
          if (env.IsDevelopment())
          {
              app.UseDeveloperExceptionPage();
          }
          app.UseMvc();
      
          UserContextSeed.SeedAsync(app,loggerFactory);
      }
      
      
      # /Data/UserContextSeed.cs
      public class UserContextSeed
      {
      
          private ILogger<UserContextSeed> _logger;
          public UserContextSeed(ILogger<UserContextSeed> logger)
          {
              _logger = logger;
          }
      
          public static async Task SeedAsync(IApplicationBuilder app, ILoggerFactory loggerFactory)
          {
              using (var scope = app.ApplicationServices.CreateScope())
              {
                  var userContext = scope.ServiceProvider.GetRequiredService<UserContext>();
                  var logger = (ILogger<UserContextSeed>)scope.ServiceProvider.GetService(typeof(ILogger<UserContextSeed>));
                  logger.LogDebug("Begin UserContextSeed SeedAsync");
      
                  userContext.Database.Migrate();
      
                  if (userContext.Users.Count() == 0)
                  {
                      userContext.Users.Add(new AppUser()
                      {
                          Name = "wyt"
                      });
                      userContext.SaveChanges();
                  }
              }
          }
      }
      View Code
    2. 安装docker-compose
      # 下载Docker Compose的当前稳定版本
      sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
      # https://github.com/docker/compose/releases/download/1.24.1/docker-compose-Linux-x86_64
      # 建议迅雷下载后进行重命名,这样速度快
      # 对二进制文件应用可执行权限
      sudo chmod +x /usr/local/bin/docker-compose
      # 测试安装
      docker-compose --version
    3. 新建文件 docker-compose.yml 
      version: '3'
      
      services: 
        db: 
          image: mysql/mysql-server
          container_name: db
          command: mysqld --character-set-server=utf8 --collation-server=utf8_general_ci
          restart: always
          ports:
            - '3306:3306'  #host物理直接映射端口为3306
          environment:
            MYSQL_ROOT_PASSWORD: pwd123456 #root管理员用户密码
            MYSQL_USER: jeese   #创建jeese用户
            MYSQL_PASSWORD: pwd123456  #设置jeese用户的密码
            MYSQL_ROOT_HOST: '%'
          volumes:
            - "/home/wyt/beta/mysql-init:/docker-entrypoint-initdb.d"  #设置数据库自动执行脚本目录,目录要存在
      
        web: 
          build: .
          container_name: aspnetcore
          ports:
            - '8003:80'  #host物理直接映射端口为3306
          depends_on: 
            - db
      # 初始化脚本mysql-init/init.sql
      use mysql;
      ALTER USER 'jeese'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd123456';
      ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd123456';
      FLUSH PRIVILEGES;
    4. docker-compose构建

      docker-compose build
      [root@localhost User.API]# docker-compose build
      db uses an image, skipping
      Building web
      Step 1/11 : FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
       ---> 155911c343f3
      Step 2/11 : WORKDIR /code
       ---> Using cache
       ---> 7525de38c042
      Step 3/11 : COPY *.csproj ./
       ---> Using cache
       ---> 397affedf1a6
      Step 4/11 : RUN dotnet restore
       ---> Using cache
       ---> 964ce7a0de36
      Step 5/11 : COPY . ./
       ---> Using cache
       ---> 5d18774ff1df
      Step 6/11 : RUN dotnet publish -c Release -o out
       ---> Using cache
       ---> 3353849a8dd8
      Step 7/11 : FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
       ---> c56aab97bc42
      Step 8/11 : WORKDIR /app
       ---> Using cache
       ---> 12d1df98dc50
      Step 9/11 : COPY --from=build /code/out ./
       ---> Using cache
       ---> 4e6819b010fe
      Step 10/11 : EXPOSE 80
       ---> Using cache
       ---> 2ee374887860
      Step 11/11 : ENTRYPOINT ["dotnet", "User.API.dll"]
       ---> Using cache
       ---> 2b06acc1b707
      Successfully built 2b06acc1b707
      Successfully tagged userapi_web:latest
      View Code
      docker-compose up
      [root@localhost User.API]# docker-compose up
      Creating network "userapi_default" with the default driver
      Creating db ... done
      Creating aspnetcore ... done
      Attaching to db, aspnetcore
      db     | [Entrypoint] MySQL Docker Image 8.0.16-1.1.11
      db     | [Entrypoint] Initializing database
      aspnetcore | warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      aspnetcore |       No XML encryptor configured. Key {67f35cc4-a4c3-4224-ba07-7a0753ed0d09} may be persisted to storage in unencrypted form.
      aspnetcore | Hosting environment: Production
      aspnetcore | Content root path: /app
      aspnetcore | Now listening on: http://[::]:80
      aspnetcore | Application started. Press Ctrl+C to shut down.
      db     | 2019-07-05T09:27:43.358708Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.16) initializing of server in progress as process 20
      db     | 2019-07-05T09:27:43.360043Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.
      db     | 2019-07-05T09:27:43.360052Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead.
      db     | 2019-07-05T09:27:46.943704Z 5 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
      db     | 2019-07-05T09:27:48.131450Z 0 [System] [MY-013170] [Server] /usr/sbin/mysqld (mysqld 8.0.16) initializing of server has completed
      db     | [Entrypoint] Database initialized
      db     | 2019-07-05T09:27:49.902213Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.16) starting as process 66
      db     | 2019-07-05T09:27:49.903376Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.
      db     | 2019-07-05T09:27:49.903389Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead.
      db     | 2019-07-05T09:27:50.456492Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
      db     | 2019-07-05T09:27:50.477501Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.16'  socket: '/var/lib/mysql/mysql.sock'  port: 0  MySQL Community Server - GPL.
      db     | 2019-07-05T09:27:50.558190Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: '/var/run/mysqld/mysqlx.sock'
      db     | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
      db     | Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it.
      db     | Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it.
      db     | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
      db     | Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
      db     | 
      db     | [Entrypoint] running /docker-entrypoint-initdb.d/init.sql
      db     | 
      db     | 
      db     | 2019-07-05T09:27:52.092496Z 12 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.0.16).
      db     | 2019-07-05T09:27:54.191280Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.16)  MySQL Community Server - GPL.
      db     | [Entrypoint] Server shut down
      db     | 
      db     | [Entrypoint] MySQL init process done. Ready for start up.
      db     | 
      db     | [Entrypoint] Starting MySQL 8.0.16-1.1.11
      db     | 2019-07-05T09:27:55.417600Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.16) starting as process 1
      db     | 2019-07-05T09:27:55.419490Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.
      db     | 2019-07-05T09:27:55.419504Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead.
      db     | 2019-07-05T09:27:55.858661Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
      db     | 2019-07-05T09:27:55.880107Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.16'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MySQL Community Server - GPL.
      db     | 2019-07-05T09:27:56.066024Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: '/var/run/mysqld/mysqlx.sock' bind-address: '::' port: 33060
      aspnetcore | Application is shutting down...
      aspnetcore exited with code 0
      aspnetcore | Hosting environment: Production
      aspnetcore | Content root path: /app
      aspnetcore | Now listening on: http://[::]:80
      aspnetcore | Application started. Press Ctrl+C to shut down.
      View Code
      # 停止docker-compose
      # docker-compose down

    启动问题解决方式:由于docker-compose.yml文件中存在db依赖,所以要修改/Data/UserContextSeed.cs进行延迟数据库自动初始化

    public static async Task SeedAsync(IApplicationBuilder app, ILoggerFactory loggerFactory,int? retry=0)
    {
        var retryForAvaiability = retry.Value;
        try
        {
            using (var scope = app.ApplicationServices.CreateScope())
            {
                var userContext = scope.ServiceProvider.GetRequiredService<UserContext>();
                var logger = (ILogger<UserContextSeed>)scope.ServiceProvider.GetService(typeof(ILogger<UserContextSeed>));
                logger.LogDebug("Begin UserContextSeed SeedAsync");
    
                userContext.Database.Migrate();
    
                if (userContext.Users.Count() == 0)
                {
                    userContext.Users.Add(new AppUser()
                    {
                        Name = "wyt"
                    });
                    userContext.SaveChanges();
                }
            }
        }
        catch (Exception ex)
        {
            if (retryForAvaiability<10)
            {
                retryForAvaiability++;
                var logger = loggerFactory.CreateLogger(typeof(UserContextSeed));
                logger.LogError(ex.ToString());
                await Task.Delay(TimeSpan.FromSeconds(2));
                await SeedAsync(app, loggerFactory, retryForAvaiability);
            }
        }
    }
    View Code
  • 相关阅读:
    Spring-IOC容器
    VUE 过滤器
    axios.post参数问题
    Stylus| vue项目中stylus和stylus-loader版本兼容问题
    SPA
    Options API 和 Composition API 的对比
    【ES6学习笔记之】Object.assign()
    vue element-ui 常用组件
    Vue调试工具
    组件
  • 原文地址:https://www.cnblogs.com/wyt007/p/11116498.html
Copyright © 2011-2022 走看看