应用场景
写完了项目的代码,怎么将整个项目容器化?怎么让运行前端、后端、数据库等服务作为一个整体,通过页面轻轻松松地部署?
实现效果:
在Rancher页面上自己定义的应用商店里找到自己的应用图标,点击进入启动页面,配置一下信息,然后点击启动就可以把整个项目部署完,包括前端、后端、数据库等。
用Rancher的好处还有很多,比如可以页面上对容器进行重启、升级、删除等,还可以查看容器的日志。
下面是一些Rancher自带的应用,这些应用都是可以页面部署到机器上的。
大体步骤:制作镜像,往镜像库harbor(Rancher能访问到的)上传相关的镜像;
在GitLab上传一个文件夹,文件夹包括docker-compose.yml文件、rancher-compose文件、一张svg图片,一个config.yml文件;
在Rancher上部署该应用。
具体过程:
一、制作镜像,上传镜像到镜像库
1. 生成jar包
(1) 首先在将工程配置文件中mysql的具体IP改成变量,为了动态地获取mysql的IP地址。
(2) 然后在工程目录下执行(这里用maven编译):
1mvn -DskipTests install
(3)生成的jar包在该工程的target目录下。
2. 写dockerfile
执行命令生成镜像(jar包和dockerfile放在同一个文件夹下;下面命令最后的点表示Dockerfile所在目录;双引号里为自定义的镜像名和镜像版本号):
1sudo docker build -t="ip:port/fileName/imageName:tag" .
解释:
为什么给镜像加上ip/fileName前缀,是为了更方便传到harbor,镜像名前半部分的ip是为了识别上传的时候传到哪里,fileName是为了识别传到Harbor上Project下的哪个文件夹。
3. 上传到harbor
(1) 登录harbor
先在宿主机配置daemon.json文件
1sudo vim /etc/docker/daemon.json
然后加上(自己把Harbor的IP、端口号添上,多个harbor中间用逗号隔开):
1{
2 "insecure-registries": ["harobrIp1:port1","harborIp2:port2"],
3 "registry-mirrors": ["https://registry.docker-cn.com"]
4}
保存,退出。然后:
1sudo systemctl daemon-reload
2sudo systemctl restart docker.service
通过命令行登录harbor
1sudo docker login harborIp:port
然后输入用户名和密码。
(2) push到harbor(以springappserver镜像为例,其它类似)
1sudo docker push harborIp:port/lamppole/springappserver:2018-06-05
1. 写docker-compose.yml和 rancher-compose.yml等文件
(1) docker-compose.yml文件:
1version: '2'
2services:
3 mysql:
4 image: harborIp:port/lamppole/mysql:5.7
5 restart: always
6 ports:
7 - "3306:3306"
8 environment:
9 - MYSQL_ROOT_PASSWORD=rootPassword
10 - MYSQL_USER=userName
11 - MYSQL_PASSWORD=password
12 - MYSQL_DATABASE=databaseName
13 springappserver:
14 image: harbor:port/lamppole/springappserver:2018-06-05
15 restart: always
16 links:
17 - mysql:lamppole-mysql
18 ports:
19 - "8090:8090"
20 ngnix:
21 image: nginx
22 restart: always
23 ports:
24 - "8080:80"
解释:
environment下: 设置了mysql的root用户的密码,并创建了一个新的用户,设置了新用户的密码,同时创建了一个数据库;
link: 这里的springserver链接到mysql;
restart: 设置为alway时,如果容器退出,会自动重启;
(2) rancher-compose.yml文件:
1version: '2'
2.catalog:
3 name: "xxx"
4 version: "v1.0"
5 description: ""
6 questions:
7 - variable: "server_port1"
8 description: "server_port1"
9 label: "后端服务端口"
10 type: "int"
11 defualt: 8090
12 required: true
13 services:
14 mysql:
15 scale: 1
16 start_on_create: true
17 server:
18 scale: 1
19 start_on_create: true
20 nginx:
21 scale: 1
22 start_on_create: true
(3) config.yml文件
1name: "lamppole"
2description: "xxx项目平台"
3version: "v0.1"
4category: Experiment
5maintainer: 李想妮
6labels:
7 io.rancher.certified: Allblue
解释:config文件里设置的信息到时会在应用商店的图标上显示:
1为配置文件里的name
2为description
3为io.rancher.certified的值
4为svg图片
(4) 准备一张后缀为svg的图片,作为该应用在Rancher应用商店上的图标。
(5) 把上面的文件按照一定的规则放在文件夹里。
说明:
lamppole为上传到GitLab上的文件夹,上传后放在某个catalog的templates文件夹下;
把docker-compose.yml文件和rancher-compose.yml文件放在项目文件夹lamppole下以正整数命名的文件夹下。数字文件夹按照不同的版本,从0开始,如果想放新的应用版本,下一次就加上一个以“1”命令的文件夹,放上同样的文件。
config.yml文件和svg图片放在数字文件夹外面,项目lamppole文件夹下。
2. 上传到GitLab
(1) 在本地新建一个空的文件夹,然后
1git init
2git remote add origin http://gitLabIp:port/xxx/xxx-catalog.git
3git pull origin master
(2) 然后把本地的lamppole文件夹放到pull下来的templates文件夹下,然后
1git add templates/lamppole/
2git commit -m "添加xxx的template"
3git push origin master
三、在Rancher上部署
1. 登录Rancher
登录Rancher,输入用户名和密码。
2. 添加主机,如果已经添加可以不用
基础架构-->主机-->添加主机
填上宿主机IP后,点复制按钮将命令行copy到该IP的机器上执行。
注:实际上就是在机器上运行一个rancher-agent容器,如果没有这个agent, Rancher和运行该应用的机器之间无法通信。
3. 添加(或更新)自己的应用商店
在某个测试环境下,选择系统管理-->添加应用商店-->填入信息-->保存
4. 在上一步自定义的应用商店下找到lamppole应用
选择版本-->填写端口-->点击启动按钮启动:
这时应用就部署好了,在Rancher的应用里可以找到部署好的服务。
在该宿主机上也能看到启动的容器了。
P.S. 到这里,虽然我还没把前端的代码部署上去(因为文章写到这的时候我还没拿到前端的代码或者dist文件夹),但是已经体现了完整的上线流程了。
补充:
1. 想升级服务怎么办?
重新制作一个镜像,给镜像不同的版本号,然后上传到镜像库,接着在Rancher页面上针对需要升级的服务进行点击升级,修改镜像名即可。(这种方法是升级多少个服务就得做多少遍这个步骤)
2. 如果想提供多个应用版本给用户部署的时候选择怎么办?
(1) 准备好相应的镜像
(2) 往GitLab的templates的该项目文件夹下添加数字文件夹,数字文件夹的命名按正整数递增;
(3) 把数据文件夹里docker-compose.yml文件夹下的镜像改成不同版本的,把rancher-compose.yml的应用版本号也改了。
注:如果在GitLab上添加了新的版本文件夹及文件,Rancher还会自动提示“有可用更新”,告诉你有新的版本了。(这种做法是整个应用升级,包括这个应用里所有在docker-compose.yml文件里修改了镜像的服务)
3. 怎么部署前端
这里用到nginx,把前端打包好的dist静态资源文件放在nginx的一个目录下,然后在nginx的配置文件nginx.conf或者default.conf里配置dist文件的地址和一些端口之类的信息。
步骤
(1) 将前端工程打包出一个存放着静态文件的dist的文件夹(Java工程用jar包做镜像,前端用的是dist文件夹);
(2) 将dist拷贝到nginx容器的某个目录下,然后在nginx.conf配置;
(3) 通过配置好的nginx容器制作镜像。
具体做法:
1.生成dist文件夹
dist其实是distribution的意思,文件夹里是用于发行的文件。
(1) 安装node环境(MacOS系统)
1brew install node
(2) 安装webpack
1// 4以上的版本可能会遇到各种问题,我这里用的是3.5.1版本的
2npm install webpack@3.5.1 -g
(3) 生成依赖
1npm install
执行完这条命令后,工程目录下会多一个node_modules的文件夹,里面是各种依赖。
(4) 打开生成dist文件夹
1webpack
成功执行完后,工程目录下就会多了一个dist文件夹。
2.将dist文件夹拷到容器里
1sudo docker cp 主机目录 容器ID:容器里的某个目录
3.修改nginx.conf文件
nginx.conf文件在容器里的/etc/nginx目录下。
下面的配置信息只是默认配置里的一部分。因为主要是配置server里的内容,其它的按默认的就行。
1#user nobody;
2worker_processes 1;
3#error_log logs/error.log;
4#error_log logs/error.log notice;
5#error_log logs/error.log info;
6#pid logs/nginx.pid;
7events {
8 worker_connections 1024;
9}
10http {
11 include mime.types;
12 default_type application/octet-stream;
13 sendfile on;
14 server {
15 # 设置端口
16 listen 80;
17 # 设置域名
18 server_name localhost;
19 #charset koi8-r;
20 #access_log logs/host.access.log main;
21 location / {
22 # root后面是容器里dist文件夹的绝对路径
23 root /var/tmp/lamppole/dist;
24 index /page/index.html;;
25 }
26 error_page 500 502 503 504 /50x.html;
27 location = /50x.html {
28 root html;
29 }
30 }
31}
也可以在/etc/nginx/conf.d下的default.conf文件中配置,因为nginx.conf文件include了default.conf文件的内容,因为defualt.conf里只写server的内容,这些内容会成为nginx.conf的一部分。
4.重载nginx配置文件
1// 在容器里执行
2nginx -s reload
这时用浏览器打开就可以看到前端的页面了,不需要退出容器(当然退出也没问题),也不需要重启容器。
5.通过这个容器制作新的镜像
1sudo docker commit 容器ID 镜像名:版本号
接下来用这个镜像就可以启动前端的服务了,无需再重复上面的步骤。
附加:
关于数据库的一些问题:
要给数据库增加新的表,我需要给MySQL制作新的镜像吗?
答:不用。通过Docker启动的数据库仍然可以像非容器启动的一样通过Navicat等工具去操作数据库,只要连接上了。
现在只是在启动MySQL容器的时候通过启动命令创建了数据库和用户,但是为什么MySQL能自动创建表?
答:因为后端关联了MySQL,运行后端代码后会自动建表,但自动建表功能一般是开发的时候用,真正部署的时候,代码自动建表会关掉。到时通过Docker启动命令创建的数据库就是一个没有表的数据库!但是我们仍然有方法可以把原来的数据给拿过来使用。
步骤:
(1) 先通过Navicat或者其它方式导入原数据库的“表结构+数据”,以sql为后缀命名该文件;
(2)然后拷贝到容器里
格式:
sudo docker cp host_path containerID:container_path
例如:
1sudo docker cp /xxx/xxx/xxx.sql a41ba44af0bd:/opt
(3) 进入容器里,登录MySQL(MYSQL_USER、MYSQL_DATABASE和MYSQL_PASSWORD是在docker-compose.yml文件里设置的用户名、密码和创建的数据库名称)
1sudo docker exec -it 容器ID /bin/bash
2mysql -u MYSQL_USER -p
3// 输入在启动命令里设置的密码MYSQL_PASSWORD
4use MYSQL_DATABASE
5source /opt/xxx.sql
这是数据已经放到容器里了。其实也可以通过把这个放了数据的容器反制作成镜像,这样今后用这个镜像启动的容器就直接带有这个sql文件了。
容器制作成镜像也很简单:
1$ sudo yum update -y && apt-get install -y luajit luarocks
1$ sudo docker commit 容器ID lamppole_mysql:5.7
原来用的是非容器启动的数据库,上面已经有数据了,而且该数据库部署在别的机器上,现在通过容器启动的是一个新的数据库,它没有数据,但是我还想用回原来的数据库和数据怎么办?
答:可以不使用通过Docker启动MySQL,直接用原来的数据库,其它的服务仍使用Docker启动。只是后端代码配置数据库的时候要用过原来的MySQL的IP,而且启动后端容器的时候也不需要用--link参数去关联MySQL了。