2019/10/24, docker 19.03.4, ASP.NET Core 3.0, CentOS 7.6

摘要:ASP.NET Core 3.0 网站项目容器化部署,使用docker-compose编排Nginx容器、MySQL容器、web容器

案例代码

依赖结构介绍

整个网站项目取名samplems,一共需要三个容器(按依赖顺序):

1.MySQL容器,取名为samplems.mysql,来自mysql(官方)镜像

2.web容器,取名为samplems.web,来自samplemsweb(自己build出来的)镜像

3.nginx容器,取名为samplems.nginx,来自nginx(官方)镜像

使用docker-compose编排三个容器,建立桥接网络(取名samplems-net)联系三者

目录结构

在CentOS7.6中/home/yzh(yzh是我登录账户的个人文件夹)下新建deploy部署文件夹,用于存放部署所需文件,deploy里文件结构如下(后文会逐步建立以下内容):

│  docker-compose.yml       //compose编排文件

├─web //web 目录
│ │ Dockerfile //web docker配置文件
│ │
│ └─publish //web 发布文件(发布生成的内容)
│ ...
│ appsettings.json //发布文件中包含appsettings.json,其中有数据库连接配置
│ ...

└─nginx //nginx目录

└─confs //nginx 配置文件目录
nginx.conf //nginx全局配置
default.conf //web项目对应的nginx配置文件

在vs中方案文件夹结构如下:



这样组织后,WebApi发布到deploy/web/publish中,整个deploy文件夹打包发送到服务器进行部署。

把部署分为两步:

1.构建所需镜像

2.使用docker-compose编排容器

构建所需镜像

MySQL镜像

本次项目用到的MySQL镜像直接使用官方镜像,不需要进一步包装修改,直接拉取(下载)官方镜像:

docker pull mysql

MySQL配置数据库密码、数据卷挂载都稍后在docker-compose.yml中配置。

web镜像

web项目准备

Visual Studio中,web项目的MySQL数据库连接字符串(appsettings.json中)改为:

server=samplems.mysql;database=samplems;user=root;password=mysql@samplems

注意点:

  • server=samplems.mysql,这个地址就是我们的MySQL容器名;
  • 此处的密码和后文中docker-compose.yml指定的MySQL密码要一致;
  • 连接字符串没有显式指定连接端口,所以是默认的3306端口

web项目发布时,目标运行时选择linux-x64可移植

将发布内容拷贝到目标系统上,把它放进/home/yzh/deploy/web/publish文件夹内,如下图:

我这里web项目名称为WebApi,所以其中的WebApi.dll就是后文Dockerfile中dotnet指令的对象。

Dockerfile编写

/home/yzh/deploy/web文件夹下新建Dockerfile文件:

touch Dockerfile

内容如下:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.0
WORKDIR /app
COPY ./publish/ /app
EXPOSE 80
ENTRYPOINT ["dotnet","WebApi.dll"]

上面五句话的意思分别是:

  • 基于mcr.microsoft.com/dotnet/core/aspnet:3.0镜像(因为是netcore3.0的web项目),会自动下载该镜像
  • 工作目录为容器内的/app
  • 将/web/publish文件夹里所有内容拷贝至/app
  • 容器开放80端口
  • 使用dotnet运行asp.net core web项目,这里是"WebApi.dll",因为WebApi.dll就在工作目录中,所以不需要任何路径

构建web镜像

在deploy/web文件夹下使用以下指令构建镜像:(注意samplemsweb与.之间有空格,samplemsweb就是我们命名的镜像名称)

docker build -t samplemsweb .

如下图所示:

Nginx镜像

本次项目用到的Nginx镜像直接使用官方镜像,不需要进一步包装修改,直接拉取(下载)官方镜像:

docker pull nginx

Nginx配置

/home/yzh/deploy/nginx/confs/下新建nginx.conf文件,此文件是Nginx的配置文件,内容如下:

user  nginx;
worker_processes 1; error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid; events {
worker_connections 1024;
} http {
include /etc/nginx/mime.types;
default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; #允许客户端请求的最大字节
client_max_body_size 256m;
#缓冲区最大字节
client_body_buffer_size 256k; #代理服务器链接后端服务器的超时时间
proxy_connect_timeout 30;
#代理服务器等待后端服务器响应的超时时间
proxy_read_timeout 60;
#后端服务器返回数据给代理服务器的最大传输时间
proxy_send_timeout 30;
#代理服务器缓冲区大小,客户端的头信息会保存在这里
proxy_buffer_size 64k;
#代理服务器有几个缓冲区,最大是多大
proxy_buffers 4 64k;
#代理服务器繁忙可以申请更大的缓冲区,Nginx官方推荐为*2即可
proxy_busy_buffers_size 128k;
#代理服务器临时文件大小
proxy_temp_file_write_size 256k; #websocket 启用
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
} sendfile on;
#tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf;
}

简单解读:

  • client_max_body_size 256m;是限制web上传文件的大小限制
  • proxy开头的配置是为了解决an upstream response is buffered to a temporary file报错(请求文件大于缓冲区大小,导致写入成临时文件影响性能)
  • include /etc/nginx/conf.d/*.conf;是包含/etc/nginx/conf.d/下所有的配置文件,默认会有一个default.conf,下文会新建一个default.conf覆盖默认的
  • 定义了nginx错误日志和访问日志的路径

/home/yzh/deploy/nginx/confs/下新建default.conf文件,内容如下:

#设定负载均衡后台服务器列表
upstream composeserver {
#指定支持的调度算法
ip_hash;
server samplems.web:80;
} #虚拟主机的配置
server {
listen 80;
location / {
proxy_pass http://composeserver; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 以下三句话是websocket启用
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}

注意点:

  • default.conf是nginx
  • 其中samplems.web就是我们web容器的名称,后面的80即容器端口
  • listen 80 监听80端口,也就是后文为什么要开放nginx容器的80端口

至此所有的镜像已准备好

编写docker-compose.yml

在deploy文件夹下新建docker-compose.yml文件,内容如下:

version: '3.4'

services:
samplems.mysql:
image: mysql
container_name: samplems.mysql
ports:
- "3306:3306"
restart: always
environment:
- MYSQL_ROOT_PASSWORD=mysql@samplems
- TZ=Asia/Shanghai
volumes:
- /app/data/mysql:/var/lib/mysql
networks:
- samplems-net samplems.web:
image: samplemsweb
container_name: samplems.web
restart: always
depends_on:
- samplems.mysql
environment:
- TZ=Asia/Shanghai
networks:
- samplems-net samplems.nginx:
image: nginx
container_name: samplems.nginx
restart: always
ports:
- "80:80"
- "443:443"
environment:
- TZ=Asia/Shanghai
volumes:
- /app/data/nginx/default.conf:/etc/nginx/conf.d/default.conf
- /app/data/nginx/nginx.conf:/etc/nginx/nginx.conf
- /app/logs/nginxlogs:/var/log/nginx
depends_on:
- samplems.web
networks:
- samplems-net networks:
samplems-net:
driver: bridge

如上代码所示,整个yml文件结构大致分为version、services、networks三块,其中services内又有samplems.mysql、samplems.web、samplems.nginx三块

samplems.mysql:

  • image 表示引用的镜像,这里是官方的mysql
  • container_name:容器名称(其他两个容器这个字段的定义类似)
  • ports 映射的端口号,宿主机的3306映射到容器的3306端口(其他两个容器这个字段的定义类似)
  • restart: always 指定容器退出后的重启策略为始终重启(其他两个容器这个字段的定义相同)
  • environment 中定义了MySQL root账号的密码为mysql@samplems,这里需要和web项目中密码保持一致
  • environment 中定义了容器时区为亚洲上海,防止容器时区和宿主机时区不一致导致获取到的时间有偏差(其他两个容器这个字段的定义相同)
  • volumes 挂载数据卷,将容器中所有要写入/var/lib/mysql中的数据库文件,写入到宿主机/app/data/mysql中(这样即使mysql容器被删除,数据依然存在)
  • networks 使用自定义的samplems-net桥接网络(其他两个容器这个字段的定义相同)

samplems.web:

  • image 这里引用的是我们自己build的web镜像
  • depends_on 表明容器要先启动samplems.mysql,再启动samplems.web

samplems.nginx:

  • ports 80端口是默认的http端口,443是默认的https端口
  • volumes 挂载数据卷,将default.conf和nginx.conf两个配置文件映射到容器中,这样如果配置文件变动不需要重新构建nginx镜像(可以看到两个文件都在/app/data/nginx/下,所有容器编排启动前,需要将配置文件拷贝到/app/data/nginx/下)
  • volumes 挂载数据卷,将容器中所有要写入/var/log/nginx中的文件,写入到宿主机/app/logs/nginxlogs中,这里主要是nginx的日志文件
  • depends_on 表明容器要先启动samplems.web,再启动samplems.nginx,如此一来,启动的先后顺序为 mysql->web->nginx

启动容器

启动容器前,需要将nginx的配置文件拷贝至/app/data/nginx/下

#创建目录
sudo mkdir -p /app/data
#复制文件{/home/yzh}请对应修改
sudo cp -rf /home/yzh/deploy/nginx/confs /app/data/nginx

至此所有的准备工作都已完成,在deploy文件夹下执行以下命令启动容器:

docker-compose up -d

如下图,三个绿色的done表示三个容器启动成功:



使用docker ps查看容器的运行状态,是正常运行:

开放宿主机防火墙80端口:

sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
sudo systemctl restart firewalld

浏览器访问CentOS的IP地址,即可查看网页:

注意点:

1.Linux下使用到的脚本、配置文件,在visual studio中建议使用高级保存选项:utf-8编码、Unix换行格式进行保存(如果这样还报错,可以直接在Linux下新建文件,再把内容复制进去)



2.网站Program.cs中,建议把CreateHostBuilder(args).Build().Run()包裹在try catch中,这样网站出错后容器会自动重启

整个访问流程

流程:

1.浏览器访问CentOS的IP地址(默认80端口)时,访问到宿主机的80端口

2.由于docker-compose.yml中定义了nginx的端口80:80,所有宿主机的80端口映射到nginx容器的80端口

3.由于nginx容器的配置文件default.conf定义了监听80端口,所以能响应到浏览器的请求

4.由于nginx容器的配置文件default.conf定义了反向代理,将请求转发给了samplems.web容器(因为共用了samplems-net网络,所以能找到对方),端口也是80

5.samplems.web在Dockerfile中暴露了80端口,所以响应nginx的转发,web服务做出对应response返回数据内容

6.因为共用了samplems-net网络,所以web服务在连接数据库中,能找到samplems.mysql,应用了数据库操作

docker部署Asp.Net Core、Nginx、MySQL的更多相关文章

  1. Visual Studio Code和Docker开发asp.net core和mysql应用

    Visual Studio Code和Docker开发asp.net core和mysql应用 .net猿遇到了小鲸鱼,觉得越来越兴奋.本来.net猿只是在透过家里那田子窗看外面的世界,但是看着海峡对 ...

  2. docker部署asp.net core

    上一篇文章我们成功的在win10上边安装了docker,这篇文章,我们将在docker中部署asp.net core程序, 先来一张运行成功的hello world镇楼 现在开始,首先创建一个asp. ...

  3. 部署Asp.net core & Nginx,通过nginx转发

    部署Asp.net core & Nginx,通过nginx转发 CentOS 7 x64 1.vs2017 建立Asp.net core项目,并发布到目录 2.通过FTP工具,将程序copy ...

  4. 从零实操基于WSL2 Docker部署Asp.Net Core项目

    前言 平日在公司里都是基于阿里Teambition中的飞流进行Docker部署Api项目或服务,已经习惯了那一套成熟的操作流程,开发和部署确实快捷方便,但是还没在自己的电脑上进行操作过,特别是Wind ...

  5. Centos下使用Docker部署asp.net core项目

    本文讲述 CentOS 系统 Docker 中部署 asp.net core开源项目 abp 的过程 步骤 1. 拉取 asp.net core 基础镜像 docker pull microsoft/ ...

  6. Centos8 Docker+Nginx部署Asp.Net Core Nginx正向代理与反向代理 负载均衡实现无状态更新

    首先了解Nginx 相关介绍(正向代理和反向代理区别) 所谓代理就是一个代表.一个渠道: 此时就涉及到两个角色,一个是被代理角色,一个是目标角色,被代理角色通过这个代理访问目标角色完成一些任务的过程称 ...

  7. docker4dotnet #3 在macOS上使用Visual Studio Code和Docker开发asp.net core和mysql应用

    .net猿遇到了小鲸鱼,觉得越来越兴奋.本来.net猿只是在透过家里那田子窗看外面的世界,但是看着海峡对岸的苹果园越来越茂盛,实在不想再去做一只宅猿了.于是,.net猿决定搭上小鲸鱼的渡轮到苹果园去看 ...

  8. 使用Docker部署ASP.NET Core应用程序实践

    前言 最近把很火的Docker给看了,于是就磨拳擦掌要去实践一下.于是就拿之前一个aps.net core的项目(已被停止)去练手.该项目之前在ubuntu14.04上确保可以正常运行,所以docke ...

  9. docker部署Asp.net core应用

    1 容器概念 使用Docker前我们首先要简单了解一下容器的概念.MSDN上有一张虚拟机和容器的对比图,很好的展示了虚拟机和容器的区别,如下所示,虚拟机包括应用程序.必需的库或二进制文件以及完整的来宾 ...

随机推荐

  1. 小程序组件--> 组件传参

    小程序组件,在components文件夹右击-->创建文件夹-->右击-->新建component即可 创建一个组件 如果多个地方需要使用到,可以在app.json中加入一下代码,相 ...

  2. Spark2.x(六十一):在Spark2.4 Structured Streaming中Dataset是如何执行加载数据源的?

    本章主要讨论,在Spark2.4 Structured Streaming读取kafka数据源时,kafka的topic数据是如何被执行的过程进行分析. 以下边例子展开分析: SparkSession ...

  3. Server Tomcat v8.5 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.

    Server Tomcat v9.0 Server at localhost was unable to start within 45 seconds. If the server requires ...

  4. MySQL索引原理(一)

    MySQL索引原理 索引目的 索引的目的在于提高查询效率,可以类比字典,如果要查“mysql”这个单词,我们肯定需要定位到m字母,然后从下往下找到y字母,再找到剩下的sql.如果没有索引,那么你可能需 ...

  5. mysqldump 备份数据库脚本

    创建备份数据库脚本mysql_backup.sh,内容如下: #!/bin/bash export PATH=/bin:/usr/bin:/usr/local/bin TODAY=`date +&qu ...

  6. springMVC 数据模型相关注解 可注释类型 ModelAttribute SessionAttributes InitBinder

    ModelAttribute 参数/方法SessionAttributes 类InitBinder 方法

  7. python开发笔记-连接rabbitmq异常问题unacked处理

    待补充 思路:捕获程序处理异常,异常情况下,也给队列生产者返回“确认”消息

  8. QT5.12 qtcreate 在Ubuntu14.04

    Ubuntu14.04 下出现了 symbol dbus_message_get_allow_interactive_authorization, version LIBDBUS_1_3 not de ...

  9. Vue基础知识学习笔记

    一.环境搭建1.安装nodejs ((https://nodejs.org/en/)2.安装脚手架 npm install --global vue-cli /cnmp install --globa ...

  10. a simple machine learning system demo, for ML study.

    Machine Learning System introduction This project is a full stack Django/React/Redux app that uses t ...