docker部署Asp.Net Core、Nginx、MySQL
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的更多相关文章
- Visual Studio Code和Docker开发asp.net core和mysql应用
Visual Studio Code和Docker开发asp.net core和mysql应用 .net猿遇到了小鲸鱼,觉得越来越兴奋.本来.net猿只是在透过家里那田子窗看外面的世界,但是看着海峡对 ...
- docker部署asp.net core
上一篇文章我们成功的在win10上边安装了docker,这篇文章,我们将在docker中部署asp.net core程序, 先来一张运行成功的hello world镇楼 现在开始,首先创建一个asp. ...
- 部署Asp.net core & Nginx,通过nginx转发
部署Asp.net core & Nginx,通过nginx转发 CentOS 7 x64 1.vs2017 建立Asp.net core项目,并发布到目录 2.通过FTP工具,将程序copy ...
- 从零实操基于WSL2 Docker部署Asp.Net Core项目
前言 平日在公司里都是基于阿里Teambition中的飞流进行Docker部署Api项目或服务,已经习惯了那一套成熟的操作流程,开发和部署确实快捷方便,但是还没在自己的电脑上进行操作过,特别是Wind ...
- Centos下使用Docker部署asp.net core项目
本文讲述 CentOS 系统 Docker 中部署 asp.net core开源项目 abp 的过程 步骤 1. 拉取 asp.net core 基础镜像 docker pull microsoft/ ...
- Centos8 Docker+Nginx部署Asp.Net Core Nginx正向代理与反向代理 负载均衡实现无状态更新
首先了解Nginx 相关介绍(正向代理和反向代理区别) 所谓代理就是一个代表.一个渠道: 此时就涉及到两个角色,一个是被代理角色,一个是目标角色,被代理角色通过这个代理访问目标角色完成一些任务的过程称 ...
- docker4dotnet #3 在macOS上使用Visual Studio Code和Docker开发asp.net core和mysql应用
.net猿遇到了小鲸鱼,觉得越来越兴奋.本来.net猿只是在透过家里那田子窗看外面的世界,但是看着海峡对岸的苹果园越来越茂盛,实在不想再去做一只宅猿了.于是,.net猿决定搭上小鲸鱼的渡轮到苹果园去看 ...
- 使用Docker部署ASP.NET Core应用程序实践
前言 最近把很火的Docker给看了,于是就磨拳擦掌要去实践一下.于是就拿之前一个aps.net core的项目(已被停止)去练手.该项目之前在ubuntu14.04上确保可以正常运行,所以docke ...
- docker部署Asp.net core应用
1 容器概念 使用Docker前我们首先要简单了解一下容器的概念.MSDN上有一张虚拟机和容器的对比图,很好的展示了虚拟机和容器的区别,如下所示,虚拟机包括应用程序.必需的库或二进制文件以及完整的来宾 ...
随机推荐
- 小程序支持原生async方法
下载最新版本的微信开发工具,社区链接https://developers.weixin.qq.com/community/develop/doc/00066877c54eb0ff5488b54885b ...
- [技术博客] 自制 apt deb Repository
[技术博客] 自制 apt deb Repository (termux) 在修改整合遵循GPLv3的Android terminal app and Linux environment:termux ...
- abp 中log4net 集成Kafka
1.安装包 Install-Package log4net.Kafka.Core 2.修改log4net.config 配置文件 <?xml version="1.0" en ...
- Element + Vue I18n动态import加载国际化语言包翻译文件
需求 项目为多页应用,包含产品a.b.c.d.e,每个产品都有自己的翻译文件.一次加载所有翻译文件是极度不合理的.于是考虑动态加载. 实现 参考官方文档:延迟加载翻译 项目结构 │ ├── dist ...
- mvn命令修改pom打包的版本号
在java项目中打包经常需要修改镜像的版本号.可以使用如下命令 mvn versions: // 如果要打包使用人如下命令,打印详细信息使用 -X mvn clean deploy -e -Dskip ...
- 二分查找时间复杂度、partition时间复杂度
二分查找时间复杂度 partition时间复杂度 O(n) = O(n) + O(n/2) + O(n/4)+.... 然后用等比求和公式得出是O(2n),即O(n)
- MQTT研究之EMQ:【EMQX使用中的一些问题记录(3)】
EMQX功能强大,但是帮助信息或者可用资料的确有限,遇到个问题,比较难找到处理的头绪,今天,我要记录的是,使用中出现EMQX宕机,但是呢,启动也启动不了. 今天记录的内容,就以操作EMQX 3.2.3 ...
- MSSQL Server 及 MSSQL Express版本 自动备份
一.SQL Server Management Studio(SMSS) 维护计划 [参考]SQL SERVER如何定期自动备份数据库 二.Windows 级 任务计划程序( MSSQL Expres ...
- 基于term vector深入探查数据
1.term vector介绍 获取document中的某个field内的各个term的统计信息 term information: term frequency in the field, term ...
- allure与junit结合生成漂亮的demo
1.allure安装 环境配置可参考https://blog.csdn.net/huggh/article/details/90905845,且博客中也分享了官网的案例https://github.c ...