背景
内网环境部署一套微服务应用系统,采用docker方式部署。包括mysql、redis、nginx、nacos、gateway以及应用程序的jar包。下面记录部署的过程和遇到的问题。
一、内网dockcer部署mysql服务
内网生成mysql镜像
- 在一个可以连接外网的环境中,下载mysql镜像:
docker pull mysql:5.7
- 将镜像打包:
docker save -o mysql.tar mysql:5.7
- 将打好的mysql.tar包传到内网服务器中,解压:
docker load -i mysql.tar
此时,内网环境中就具备了mysql镜像。执行docker images命令可以查看是否有mysql镜像。
mysql容器启动
- 在内网宿主机上创建mysql容器的挂载目录,分别为:
创建数据目录:
mkdir /usr/local/mysql/data
创建配置文件目录:
mkdir /usr/local/mysql/conf
创建日志目录:
mkdir /usr/local/mysql/logs
创建配置文件:
cd /usr/local/mysql/conf
touch my.cnf
- 启动mysql容器:
docker run -p 3306:3306 --name mysql -v /usr/local/mysql/conf:/etc/mysql/conf.d -v /usr/local/mysql/logs:/logs -v /usr/local/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7.40
其中,通过-e 参数设置mysql的登录密码。
启动容器后,在/data目录下,就有了数据库的数据文件。
- 远程连接数据库,创建数据库。至此,mysql部署完成。
踩坑记录
如果启动docker容器时,查看容器的日志报错:(13: Permission denied)。
查阅资料给出的解决方案是docker启动容器命令增加 --privileged=true 参数,但是并没有效果。经过多次尝试,通过赋予宿主机mysql挂载文件权限接口:
chmod -R 777 /usr/local/mysql/
这样就解决了容器日志报权限不足的问题。在下面的redis容器,nginx容器部署时,也报这个错误,解决方案都是给挂载文件目录赋予权限解决。
二、内网dockcer部署redis服务
与mysql步骤类似,下面记录一下步骤过程:
- 外网环境拉取redis镜像:
docker pull redis
- 镜像文件打包:
docker save -o redis.tar redis
- 将redis.tar复制到内网环境,解压:
docker load -i redis.tar
- 内网宿主机创建挂载目录:
mkdir /usr/local/redis/conf
mkdir /usr/local/redis/data
touch /usr/local/redis/redis.log
chmod 777 redis.log
- 配置redis配置文件redis.conf
#bind 127.0.0.1 #注释掉这部分,使redis可以外部访问
requirepass 123456
logfile /data/redis.log
protected-mode no
# 设置 RDB 文件名和文件路径
dbfilename dump.rdb
dir /data
#----------------------------------------------------------------------(下面的不用修改)
# RDB 默认的设置 ,可以按照如下规则,根据自己的实际请求压力进行设置调整。
# 如果900秒内有1条Key信息发生变化,则进行快照;
save 900 1
#如果300秒内有10条Key信息发生变化,则进行快照;
save 300 10
#如果60秒内有10000条Key信息发生变化,则进行快照。
save 60 10000
# 启动备份文件压缩
rdbcompression yes
#redis 5之后,64位的CRC冗余校验码会放在RDB文件的末尾,以对文件完整性进行验证,但是在保存和加载RDB文件时,会损失10%左右的性能
rdbchecksum yes
# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes
#———————AOF配置文件—————————
# 开启AOF 备份
appendonly yes
# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的
dir /data
# AOF持久化的文件名,默认是appendonly.aof
appendfilename "appendonly.aof"
# 同步策略
# appendfsync always
appendfsync everysec
# appendfsync no
# aof重写期间是否同步
no-appendfsync-on-rewrite no
# 触发设置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 加载aof出错如何处理
aof-load-truncated yes
# 文件重写策略
aof-rewrite-incremental-fsync yes
- 将redis.conf传到宿主机/usr/local/redis/conf目录下
- 启动镜像:
docker run -d --name redis -p 6379:6379 --restart=always -v /usr/local/redis/conf:/usr/local/etc/redis -v /usr/local/redis/data:/data redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes
三、内网docker部署nginx服务
- 外网环境下载nginx镜像:
docker pull nginx
docker save -o nginx.tar nginx
- 将tar包放入内网环境,解压:
docker load -i nginx.tar
- 宿主机创建挂载目录:
mkdir /usr/local/nginx/web
- 第一次启动nginx容器,目的是复制容器内部nginx相关文件到宿主机:
docker run -d --name nginx -p 3100:80 -v /usr/local/nginx/web:/usr/share/nginx/html nginx
- 复制文件到宿主机:
docker cp nginx:/etc/nginx /usr/local/nginx
此时,在/usr/local/nginx/nginx下就有了nginx的相关文件,如下图:
6. 停止并删除刚刚启动的nginx容器:
docker stop nginx
docker rm nginx
- 修改上图中conf.d/default.conf文件,配置nginx转发信息
server {
listen 3100;
server_name localhost;
location / {
root /usr/share/nginx/html/xxx/portal; #/usr/share/nginx/html对应/usr/local/nginx/web路径,后面填项目路径
index index.html index.htm;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.html?s=$1 last;
break;
}
}
location ^~ /xxx-gateway/{
proxy_pass http://xxx.xxx.xxx.xxx:9999/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
- 将前端工程放入到web路径下。
- 启动nginx容器:
docker run -d --name nginx -p 3100:3100 -v /usr/local/nginx/nginx/:/etc/nginx -v /usr/local/nginx/web:/usr/share/nginx/html nginx
四、java服务jar包镜像制作
nacos、gateway和应用微服务都采用jar包形式部署,这里以nacos为例,记录部署过程,其他服务部署方式步骤一致。
- 外网环境下载jdk镜像,打包:
docker pull java:8
docker save -o java_8.tar java:8
- 将java_8.tar传入内网环境,解压:
docker load -i java_8.tar
- 制作Dockerfile文件
FROM java:8
MAINTAINER xiaoxiaosu
#VOLUME指定临时文件目录为tmp,在主机/var/lib/docker目录下创建一个临时文件并连接到容器的tmp
#VOLUME /tmp
ADD jeecg-cloud-nacos-3.5.0.jar jeecg-cloud-nacos-3.5.0.jar
#运行jar包
RUN bash -c 'touch jeecg-cloud-nacos-3.5.0.jar'
ENTRYPOINT ["java","-jar","jeecg-cloud-nacos-3.5.0.jar"]
EXPOSE 8848
- 将Dockerfile和nacos.jar传入内网服务器,且在一个目录下,生成镜像:
docker build -t nacos .
至此jar包镜像生成。
- 启动jar包镜像:
docker run -d --network host -p 8848:8848 --name nacos nacos
注意: --network host参数是为了让容器共用宿主机ip,这样就可以通过宿主机ip访问nacos了。否则无法通过宿主机ip访问nacos。其他jar包程序也是一样。
五、使用docker-compose编排微服务
上述用了mysql、nginx、redis、nacos、gateway和三个业务微服务,一个一个启动容器很费力,因此使用docker-compose编排启动微服务。
踩坑
起初,通过depends_on参数指定各个微服务的启动顺序。发现业务微服务无法注册到nacos上,报错为连接nacos失败,微服务也起不来。
网上搜索资料得知,depends_on是微服务启动成功后,依赖于它的其他微服务就立即启动。而nacos微服务启动成功后,还需等待一段时间,才能让其他微服务去注册。因此会出现注册连接失败的问题。
网上给出的方案是使用wait-for-it脚本进行解决。博主尝试了一下并没有成功,而是用另一种方式进行了解决。
解决方案
写了两个docker-compose.yml文件,一个文件里定义nginx、redis、mysql、nacos这些基础组件。另一个文件里定义gateway和三个业务微服务。先一键启动有nacos的编排,再启动业务微服务编排。
两个docker-compose.yml放在两个文件夹,启动即可。
version: "3"
services:
nacos:
image: xxx_nacos
ports:
- "8848:8848"
networks:
- bonc
depends_on:
- mysql
nginx:
image: nginx
ports:
- "3100:3100"
volumes:
- /usr/local/nginx/nginx/:/etc/nginx
- /usr/local/nginx/web:/usr/share/nginx/html
networks:
- bonc
mysql:
image: mysql:5.7.40
container_name: mysql
ports:
- "3306:3306"
volumes:
- /usr/local/mysql/conf:/etc/mysql/conf.d
- /usr/local/mysql/logs:/logs
- /usr/local/mysql/data:/var/lib/mysql
networks:
- bonc
environment:
MYSQL_ROOT_PASSWORD: 123456
redis:
image: redis
ports:
- "6379:6379"
volumes:
- /usr/local/redis/conf:/usr/local/etc/redis
- /usr/local/redis/data:/data
networks:
- bonc
command: redis-server /usr/local/etc/redis/redis.conf --appendonly yes
networks:
bonc:
external: true
version: "3"
services:
gateway:
image: xxx_gateway
ports:
- "9999:9999"
networks:
- bonc
xxxsystem:
image: xxx_xxxsystem
ports:
- "7001:7001"
networks:
- bonc
xxxsystem:
image: xxx_system
ports:
- "7019:7019"
networks:
- bonc
xxx:
image: xxx
ports:
- "7018:7018"
networks:
- bonc
networks:
bonc:
external: true
需要注意的是docker-compose需要定义自定义网络,然后在yml里配置networks项。
分别进入两个yml目录下,执行
docker-compose up -d
参考文章:
内网如何下载docker镜像
docker安装mysql5.7
Nginx 的 Docker 镜像使用教程
Docker安装Redis镜像