服务器迁移及docker部署

这段时间负责公司运维工作,多个私有云服务器快到期了,因此线上服务和数据需要迁移备份,但是如果在同一台机器上部署多个实例难免有端口冲突,为了做到相互隔离和维护方便,docker可能是最佳选择,于是开始了我的迁移之旅:

备份

服务器迁移过程中最重要的是数据,为了确保数据不丢失,最好是晚上停机备份

1
2
3
4
5
6
7
8
9
10
11
12
13
# redis:拷贝rdb文件和conf配置文件
# mysql全量备份
mysqldump --all-databases -uroot -p > mysql_backup.sql
# mysql容器备份,配置文件:/etc/mysql/mysql.conf.d/mysqld.cnf
docker exec -it id(container) mysqldump --all-databases -uroot -p > mysql_backup.sql
# 导出单个库(如果在db_name 前加--databases ,最终在xxx.sql里面会有create database db_name;和use db_name;语句)
docker exec -it id(container) mysqldump -uroot -p db_name > mysql_backup.sql
# mongo备份整库到指定文件
mongodump --authenticationDatabase=admin -u admin -p -d xc_log --archive=./xc_log.archive
# 数据量大时可使用gzip压缩
mongodump --authenticationDatabase=admin -u admin -p -d xc_log --port 27017 -o ./mongo_back/ --gzip
# mongodb容器导出数据
docker exec mongo -c 'exec mongodump -uadmin -p"123456" --authenticationDatabase=admin -d xc_log --archive' > ./xc_log.archive

mongodump命令详解

备份文件传输,可使用scp命令和xftp软件,推荐使用rsync同步整个项目目录

1
2
3
4
# 将backup文件夹传送到远程的目录,可列出多个,回车后需要输入密码 
scp -r backup root@ip:/workspace/shlg
# 传送文件
scp mysql_backup.sql mysqld.conf root@ip:/workspace/shlg

部署

服务器环境配置,如 git,nginx等,这里不多讲

docker安装

安装过程请自行搜索:Ubuntu安装docker

创建自定义网络(虚拟网桥),这样容器可以与同一网络中的其他容器通信,

1
2
3
4
5
6
# 默认为 bridge 模式
docker network create tongji_net
# 打印所有网络
docker network ls
# 查看网络信息
docker network inspect tongji_net

关于network的更多解释见 链接

数据库

redis

如有备份文件,请把rdb文件拷贝至data目录下

1
2
3
4
# 拉取合适的版本
docker pull redis:5.0-alpine
# 生成容器
docker run -itd --name shlg_redis -v /workspace/shlg/redis/data:/data -v /workspace/shlg/redis/redis.conf:/etc/redis/redis.conf --network tongji_net --ip 172.18.0.25 --restart=always redis:5.0-alpine

配置文件需改为如下设置

1
2
3
4
# 关闭守护进程,否则起不来
daemonize no
# 生产上可不用修改,默认为127.0.0.1,仅限本机访问
bind 0.0.0.0

mysql

如需设置时区请加上 -e TZ="Asia/Shanghai"

1
2
3
4
5
6
7
# --name 容器名称
# -p 端口映射
# -v 目录挂载
# -e 设置root密码等
# --network 绑定网络
# --ip 绑定ip
docker run -d --name shlg_mysql -p 3406:3306 -v /workspace/shlg/mysql/data:/var/lib/mysql -v /workspace/shlg/mysql/my.cnf:/etc/my.cnf -e MYSQL_ROOT_PASSWORD='123456' --network tongji_net --ip 172.18.0.24 mysql:5.7.31

数据恢复

1
docker exec -it id(container) mysql -uroot -p"123456" < ./mysql_backup.sql

用户角色配置

1
2
3
4
5
6
7
8
9
10
11
12
13
# 5.7之前的版本
grant all privileges on *.* to 'test'@'172.18.0.%' identified by 'password' with grant option;
# 如果想配置某个数据库的权限,改成
grant all privileges on database_name.* to 'test'@'172.18.0.%' identified by 'password' with grant option;
flush privileges;
show grants for 'test'@'127.0.0.1';

# 8.0之后的版本
CREATE USER 'test'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'test'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
# 撤销权限
revoke shutdown on *.* from 'user'@'%';

mongodb

1
docker run -itd --name shlg_mongodb -v /workspace/shlg/mongodb/data:/data/db --network tongji_net --ip 172.18.0.26 mongo:4.0 

数据恢复

1
2
3
4
# 此命令暂未生效
docker exec -i shlg_mongodb mongorestore -u admin -p "123" --authenticationDatabase admin -d xc_log --gzip < /workspace/shlg/mongodb/xc_log
# 有效
docker exec -i shlg_mongodb sh -c 'exec mongorestore -u "admin" -p "123" --authenticationDatabase admin --archive' < /workspace/shlg/xc_log.archive

可以直接进入容器内部,无需密码,设置用户角色

1
2
3
4
5
docker exec -it shlg_mongodb mongo
use admin
db.createUser({ user:'admin',pwd:'mongo@123',roles:[ { role:'root', db: 'admin'} ]})
use xc_log
db.createUser({ user:'shlg',pwd:'123456',roles:[ { role:'dbOwner', db: 'xc_log'} ]})

然后在/etc/mongod.conf文件的 security 下加上下面的代码,重启服务即可生效

1
2
security:
authorization: enabled

mongorestore命令

node服务

这里有多个node服务:exports、log、join、xiaochuang,shared是公共字典,将它们部署到一个容器内,需要打包成镜像,再根据镜像生成容器,在项目同级目录下新建Dockerfile文件,内容如下:

1
2
3
4
5
6
7
8
9
10
FROM node:10.24-alpine
ENV TZ=Asia/Shanghai
RUN apk update && apk add tzdata && echo "${TZ}" > /etc/timezone && ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && rm /var/cache/apk/*
COPY exports /workspace/exports
COPY log /workspace/log
COPY join /workspace/join
COPY xiaochuang /workspace/xiaochuang
COPY shared /workspace/shared
COPY script.sh /workspace/script.sh
ENTRYPOINT ["./workspace/script.sh"]

注意:如果系统的文件存储在项目所在目录下且存的是绝对地址的话,容器内的项目根目录必须保持和原系统一致,否则会找不到文件。

配置容器内项目启动脚本,当前目录新建script.sh,内容如下:

1
2
3
4
5
#!/bin/sh
cd /workspace/log && npm run start-prod
cd /workspace/exports && npm run start-prod
cd /workspace/join && npm run start-prod
cd /workspace/xiaochuang && npm run start-prod

给当前文件新增可执行权限

1
chmod 755 script.sh

在项目上一级目录新建init.sh,名字自定义,内容如下:

1
2
3
4
5
6
7
8
9
10
11
# 删除旧镜像
docker rmi shlg_node:old
# 标记新镜像为旧镜像
docker tag shlg_node:latest shlg_node:old
docker rmi shlg_node:latest
# 根据该目录下的Dockerfile打包镜像,如果打包过程报错提示包无法下载请加上 --network=host
docker build -t shlg_node:latest /workspace/shlg/workspace/ --network=host
# 生成新的容器
docker rm -f shlg_node && docker run -d --name shlg_node -v /workspace/shlg/workspace/xiaochuang:/workspace/xiaochuang -v /workspace/shlg/workspace/exports:/workspace/exports -v /workspace/shlg/workspace/log:/workspace/log -v /workspace/shlg/workspace/join:/workspace/join -v /workspace/shlg/workspace/shared:/workspace/shared -v /workspace/shlg/workspace/logs:/root/logs --network tongji_net --ip 172.18.0.52 shlg_node:latest
# 查看最新20条并跟踪启动日志
docker logs --tail=20 -f shlg_node

如果遇到容器无法启动的情况,可能是因为docker容器运行必须有一个前台进程,如果没有前台进程执行,容器认为空闲,就会自行退出。xiaochuang是项目主体,所以得去掉package.json 中启动命令start-prod里的 --daemon选项。

如果后端项目要连接宿主机的数据库,请把连接信息中的host改为该容器的网关ip,可使用docker inspect container查看
Gateway设置,即为虚拟网卡ip。

确保路径映射和ip无误后最后运行脚本:sh init.sh,稍等几分钟,中途没有报错的话,容器自动运行,最后大功告成 ~_~