背景

内网环境部署一套微服务应用系统,采用docker方式部署。包括mysql、redis、nginx、nacos、gateway以及应用程序的jar包。下面记录部署的过程和遇到的问题。

一、内网dockcer部署mysql服务

内网生成mysql镜像

  1. 在一个可以连接外网的环境中,下载mysql镜像:
docker pull mysql:5.7
  1. 将镜像打包:
docker save -o mysql.tar mysql:5.7
  1. 将打好的mysql.tar包传到内网服务器中,解压:
docker load -i mysql.tar 

此时,内网环境中就具备了mysql镜像。执行docker images命令可以查看是否有mysql镜像。

mysql容器启动

  1. 在内网宿主机上创建mysql容器的挂载目录,分别为:

创建数据目录:

mkdir /usr/local/mysql/data

创建配置文件目录:

mkdir /usr/local/mysql/conf

创建日志目录:

mkdir /usr/local/mysql/logs

创建配置文件:

cd /usr/local/mysql/conf
touch my.cnf
  1. 启动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目录下,就有了数据库的数据文件。

  1. 远程连接数据库,创建数据库。至此,mysql部署完成。

踩坑记录

如果启动docker容器时,查看容器的日志报错:(13: Permission denied)。
查阅资料给出的解决方案是docker启动容器命令增加 --privileged=true 参数,但是并没有效果。经过多次尝试,通过赋予宿主机mysql挂载文件权限接口:

chmod -R 777 /usr/local/mysql/

这样就解决了容器日志报权限不足的问题。在下面的redis容器,nginx容器部署时,也报这个错误,解决方案都是给挂载文件目录赋予权限解决。

二、内网dockcer部署redis服务

与mysql步骤类似,下面记录一下步骤过程:

  1. 外网环境拉取redis镜像:
docker pull redis
  1. 镜像文件打包:
docker save -o redis.tar redis
  1. 将redis.tar复制到内网环境,解压:
docker load -i redis.tar 
  1. 内网宿主机创建挂载目录:
mkdir /usr/local/redis/conf
mkdir /usr/local/redis/data
touch /usr/local/redis/redis.log
chmod 777 redis.log
  1. 配置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

  1. 将redis.conf传到宿主机/usr/local/redis/conf目录下
  2. 启动镜像:
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服务

  1. 外网环境下载nginx镜像:
docker pull nginx
docker save -o nginx.tar nginx
  1. 将tar包放入内网环境,解压:
docker load -i nginx.tar
  1. 宿主机创建挂载目录:
mkdir /usr/local/nginx/web
  1. 第一次启动nginx容器,目的是复制容器内部nginx相关文件到宿主机:
docker run -d --name nginx -p 3100:80  -v /usr/local/nginx/web:/usr/share/nginx/html nginx
  1. 复制文件到宿主机:
docker cp nginx:/etc/nginx /usr/local/nginx

此时,在/usr/local/nginx/nginx下就有了nginx的相关文件,如下图:
在这里插入图片描述
6. 停止并删除刚刚启动的nginx容器:

docker stop  nginx
docker rm nginx
  1. 修改上图中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;

       }

}
  1. 将前端工程放入到web路径下。
  2. 启动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为例,记录部署过程,其他服务部署方式步骤一致。

  1. 外网环境下载jdk镜像,打包:
docker pull java:8
docker save -o  java_8.tar java:8
  1. 将java_8.tar传入内网环境,解压:
docker load -i java_8.tar
  1. 制作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
  1. 将Dockerfile和nacos.jar传入内网服务器,且在一个目录下,生成镜像:
docker build -t nacos .

至此jar包镜像生成。

  1. 启动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镜像

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐