把AspDotNetCoreMvc程序运行在Docker上-part3:使用独立的存储容器
接上一篇博文《把AspDotNetCoreMvc程序运行在Docker上-part2:修改容器以及发布镜像》,这次我们看看如何使用docker存储数据。
背景
之前的示例都只有一个网站应用,其显示的数据是放在内存中,可以查看DummyRepository的实现方式。这样的数据除了用于演示没有什么用处。这一部分,将扩展数据存储功能,用比较实际的存储方式,把数据保存到MySql数据库中。
那么MySql数据库放在哪里呢?用传统部署站点的方式,数据库应该部署在独立的服务器上,那么用于docker也应该有数据库专用的容器。可能有的人会说,数据库放在跟应用站点容器中,不是更方便的吗?对于示例我想可以这么做,但是用于实战的话,会导致耦合,不易于对单独或者单独的数据库进行横向的扩容。所以这部分的示例将会把MySql数据库部署到独立的容器中。
了解volume
在演示之前,需要了解docker中的volume
volume从字面意思理解就是表示容量、体积,它的功能将数据存储独立于容器之外,可以这么理解:删除容器之后,数据还会保留。这么看来不就是类似于数据库的功能吗?
volume示例
对于volume的使用我们可以举个例子来说比较形象
在Docker服务器上创建如下文件Dockerfile.volumes,内容如下
FROM alpine:3.4
WORKDIR /data
ENTRYPOINT (test -e message.txt && echo "File exists" || (echo "Creating File..." && echo Hello, Docker $(date + '+%X') > message.txt)) && cat message.txt
这个文件包含了创建容器的命令
1.拉取镜像alpine:3.4(这是一个很小的Linux发行版)
2.设置WORKDIR
3.设置启动命令,一看就懂,就是看message.txt是否存在,不存在则创建并写入创建时间,否则直接显示内容
然后创建镜像
docker build . -t shenba/vtest -f Dockerfile.volumes
创建并运行一个容器
docker run --name vtest shenba/vtest
然后在输出中能看到如下信息
Creating File...
Hello, Docker 07:10:05
说明是新建的
由于这个容器其他啥也没干,所有运行完毕之后就直接关闭了,我们调用启动命令
docker start -a vtest
这时候的输出是
File exists
Hello, Docker 07:10:05
没问题,说明文件是保存在容器中了
那么我们把容器删掉再创建看看什么效果
docker rm -f vtest
docker run --name vtest shenba/vtest
输出如下
Creating File...
Hello, Docker 07:13:56
创建了新文件,并且输出的时间也变了,说明之前的文件已经不存在了
接下来我们使用volume来解决删除容器后数据丢失的问题
首先修改Dockerfile.volumes文件,在第一个命令之后插入如下命令
VOLUME /data
接着执行build命令更新镜像
docker build . -t shenba/vtest -f Dockerfile.volumes
创建volume,在创建容器的时候会被用到
docker volume create -name testdata
删除之前的容器
docker rm -f vtest
再次创建容器,这里指定了/data的数据是保存在testdata这个volume中
docker run --name vtest -v testdata:/data shenba/vtest
同样能看到输出
Creating File...
Hello, Docker 07:25:27
那么我们先删除这个容器,然后再次创建一个容器
docker rm -f vtest
docker run --name vtest -v testdata:/data shenba/vtest
这时候的输出内容是
File exists
Hello, Docker 07:25:27
说明message.txt这个文件是被保存在外部的volume中,不受容器删除的影响。
使用volume存储MySql数据
好了有了这么一个例子之后,我们接下来将我们的AspDotNetCoreMvc程序的数据保存到MySql数据库中。(为什么用Mysql,而不是微软当家SqlServer,那是应为这里用的是Linux docker平台,SqlServer运行在Linux还太新了,还不了解,避免踩到坑)
既然要用MySql,那首先有个MySql的镜像。跟传统方式不同吧,不用自己安装MySql,直接拉个镜像下来(这个命令需要些时间执行,可考虑配置国内镜像)
docker pull mysql:8.0.0
然后创建一个volume
docker volume create --name productdata
然后创建mysql的容器
docker run -p 3306:3306 -d --name mysql -v productdata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password -e bind-address=0.0.0.0 mysql:8.0.0
这里几个参数说明一下
-p 3304:3304 设置宿主机的3304端口映射到容器的3304端口,这样可以在宿主机访问到容器里的mysql
-d 后台运行容器
-e 是设置环境变量,这里设置了两个变量,一个是密码,一个是地址绑定
-v 指定使用的volume,后面的/var/lib/mysql是根据mysql镜像里设置的路径配置的,要查看这个路径可以使用如下命令 docker insepect mysql:8.0.0,在输出的内容中可以看到如下信息
"Volumes": {
"/var/lib/mysql": {}
}
因为设置的是后台运行,所以看不到详细的日志,不过可以通过以下命令查看
docker log -f mysql
从日志中我们可以看到如下字样
MySql is ready….
表明mysql服务已经成功运行了,整个过程比自己手动安装mysql简单多了(前提是docker环境已经搭好)
准备好MySql的docker容器之后,接着更新我们的AspDotNetCoreMvc程序,让数据存储指向MySql,改动过程不详细描述,这里有修改好的代码分支
https://github.com/shenba2014/AspDotNetCoreMvcDocker/tree/mysql
代码拉取下来后执行如下修改
修改appsettings.json中DBHOST的IP地址,指向MySql容器所在宿主机器的IP,如果docker就安装在开发机,那么可设置为localhost
然后执行如下命令(确保mysql的容器已正常运行)
dotnet restore
dotnet ef migrations add Initial
dotnet ef database update
执行完上述命令之后,就会在MySql创建books数据库,并且创建了数据表Book.
我们可以通过以下方式在docker容器上执行mysql命令来查看我们新建的数据库和表
docker exec -it mysql /bin/bash
然后进入到mysql容器下的bash命令,继续执行如下命令
mysql -uroot -p
输入密码(这里的密码在之前创建镜像的时候设置的)之后就会进行mysql的命令行
show databases;
use books;
show tables;
可以看到只有一个表Book
接下来更新我们的shenba/aspdotnetcoremvc镜像
首先还是执行以下publish命令
dotnet publish --framework netcoreapp2.0 --configuration Release --output dist
将dist文件夹拷贝docker所在服务器(如果开发机就是docker服务器可忽略这步)
确保dist文件夹同级别的目录下有Dockerfile文件,这个文件具体内容在项目代码根目录下有
然后执行如下命令更新镜像
docker build . -t shenba/aspdotnetcoremve -f Dockerfile
执行完毕之后,还不能立即创建这个镜像的容器,因为我们的容器是依赖于MySql数据库容器,我们的应用程序镜像是通过docker内部的网络来访问MySql数据库容器。这个网络,不是我们配置的localhost,其具体的访问地址是由docker设置好的
我们可以通过以下命令查看看docker的默认虚拟network的IP地址信息
docker network inspect bridge
在输出结果中我们可以看到类似如下的输出
"Containers": {
"d4e5cf975ad5e3ff11620c02f9b626fa4d0042faab83fa9d0ea86801d2cce452": {
"Name": "mysql",
"EndpointID": "39818b04606078f600a3ab55ef76949807d6528b978ec24d0f91cd5f4217b610",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
这是我们的mysql容器使用的网络配置信息,IPv4Address就是给其他容器访问的IP地址。
查看项目的Startup.cs的代码,我们的DBHOST是通过参数读取的。在运行ef migrations命令时,我们是通过appsettings.json中的DBHOST来设置具体的MySql所在服务器地址,实际上就是docker宿主机器的IP地址,因为我们做了映射,所以实际访问的是MySql容器。
然后在运行阶段,我们可以通过指明环境变量的方式来设置这个值
docker run -d --name bookApp -p 3000:80 -e DBHOST=172.17.0.2 shenba/aspdotnetcoremvc
执行完成这个命令之后,就会在mysql容器中插入一些种子数据。并且从输出信息中能看到执行了创建种子数据的过程
Applying Migrations...
Creating Seed Data...
然后通过浏览器访问
http://{ip}:3000就能看到数据是从mysql里读取的
并且重新通过docker exec -it mysql /bin/bash进入mysql可再次确认里面的数据
mysql -uroot -p
use books;
select * from Books;
好了到这里已经完成了,目前实现了两个容器之间的通讯,一个是包含web应用的容器,一个包含数据的mysql容器,说的比较啰嗦,实际上他们的结构图如下,没有想象的那么复杂。
把AspDotNetCoreMvc程序运行在Docker上-part3:使用独立的存储容器的更多相关文章
- 把AspDotNetCoreMvc程序运行在Docker上-part5:使用docker-compose
在上一part<把AspDotNetCoreMvc程序运行在Docker上-part4:实现负载均衡>中,我们通过几个比较复杂的步骤在docker平台上实现了对网站程序的负载均衡,配置步骤 ...
- 把AspDotNetCoreMvc程序运行在Docker上-part4:实现负载均衡
在上一part<把AspDotNetCoreMvc程序运行在Docker上-part3:使用独立的存储容器>,我们利用MySql容器和Volume实现了真正意义上的数据存储.整个结构非常简 ...
- 把AspDotNetCoreMvc程序运行在Docker上-part2:修改容器以及发布镜像
在上一个part<把AspDotNetCoreMvc程序运行在Docker上-part1>,已经将成功将aspdotnetcore程序运行在两个不同的容器中,目前两个容器的内容完全相同,只 ...
- 把AspDotNetCoreMvc程序运行在Docker上-part1
接<基于ASP.Net Core学习Docker技术第一步:在CentOS7安装Docker平台>这个博文,在搭建完成Docker平台之后,可以开始让aspdotnetcore程序运行在d ...
- 六、.net core (.NET 6)程序部署到Docker上
使用Docker部署应用程序 首先确保已经安装Docker 桌面软件,如下图: 然后,把需要部署到Docker上面的项目,咱们先添加Docker的支持,启动项目右键 -> 添加 -> Do ...
- 将Spring Boot项目运行在Docker上
将Spring Boot项目运行在Docker上 一.使用Dockerfile构建Docker镜像 1.1Dockerfile常用指令 1.1.1ADD复制文件 1.1.2ARG设置构建参数 1.1. ...
- ASP.NET CORE做的网站运行在docker上(不用dockerfile文件部署)
按网上的做法用dockerfile文件是可以弄得出来的,http://www.docker.org.cn/article/119.html, 不过我想把网站文件放在外面硬盘目录,再映射进去,这样只要在 ...
- Java程序运行在Docker等容器环境有哪些新问题
基本回答 一. 对于Java来说,Docker毕竟是一个较新的环境,其内存.CPU等资源限制是通过ControlGroup实现的.早期的JDK版本并不能识别这些限制,进而会导致一些基础问题. 1.如 ...
- 将微服务运行在docker上遇到的问题一
按照类似这样的流程: 但是去访问本机的 localhost:92 localhost:80 都没有任何的内容..... 这是什么原因? 重新再来一次 新写了一个微服务demo jar包: 相应的Doc ...
随机推荐
- Python 数据结构与算法——桶排序
#简单的桶排序 def bucksort(A): bucks = dict() # 定义一个桶变量,类型为字典 for i in A: bucks.setdefault(i,[]) # 每个桶默认为空 ...
- VS版本与系统不兼容问题
1.VS2012在win7 64位系统安装快结束时报出一个不兼容的错误. 2.这种情况官方给出解决方法: http://www.microsoft.com/en-us/download/details ...
- 《ASP.NET MVC 5 破境之道》:第一境 ASP.Net MVC5项目初探 — 第二节:MVC5项目结构
第一境 ASP.Net MVC5项目初探 — 第二节:MVC5项目结构 接下来,我们来看看,VS为我们自动创建的项目,是什么样子的? 可以通过菜单中[View]->[Solution Explo ...
- log Log4NET配置
Log4Net是用来记录日志的,可以将程序运行过程中的信息输出到一些地方(文件.数据库.EventLog等),日志就是程序的黑匣子,可以通过 日志查看系统的运行过程,从而发现系统的问题.日志的作用:将 ...
- 使用xargs与awk联合使用批量杀进程,很方便
ps -ef | grep java | grep alarm | awk '{print $2}' | xargs kill -9 注*A. $2表示第2列,即进程号PID; awk很强大,这里不 ...
- 文本比较算法Ⅱ——Needleman/Wunsch算法的C++实现【求最长公共子串(不需要连续)】
算法见:http://www.cnblogs.com/grenet/archive/2010/06/03/1750454.html 求最长公共子串(不需要连续) #include <stdio. ...
- Spring 开发第一步(二)
今天继续学习<Spring in action 3rd>并运行书中的例子,到了第4章aop,是加入一个作为切面的Audience类,将Performer的perform()方法作为切点来进 ...
- 为什么选择AJPFX
外汇贵金属交易市场是全球最大的金融产品市场,日均交易量达到5万亿美元,相当于美国证券市场的40倍,中国股票市场日均交易量的700倍,它的主要优势在于其透明度较高,由于交易量巨大,主力资金(如政府外汇储 ...
- PhoneGap - 解决用nmp无法安装PhoneGap问题!
PhoneGap从2.9.0开始,只采用node安装方式,安装命令如下: npm install -g phonegap 今天我使用此命令安装PhoneGap时候,始终无法安装,在网上搜索一下,最终解 ...
- 80端口被系统进程PID-4占用解决办法
今天因为工程需要就把tomcat服务器的端口改成了80了,可是一启动就出现问题了 发现报错信息是端口占用了,于是我马上就在了命令行敲入了netstat -ano查看端口占用情况 终于发现是PID为4的 ...