08月26, 2018

docker前后分离笔记

这个也是慕课的一个课程。我觉得作为前端,还是需要懂一些运维、分布式、集群这几块知识点。

linux之防火墙

之前有几篇文章一直用的是iptables,这次说说centos7自带的firewall

查看、启动、关闭、重启防火墙

firewall-cmd --state  # 查看状态
service firewall start # 启动
service firewall stop # 停止
service firewall restart # 重启

端口管理

firewall-cmd --permanent --add-port =8080-8085/tcp   # 添加8080-8085的端口区段,也可以是固定值,如3000
firewall-cmd --reload  
firewall-cmd --permanent --remove-port=8080-8085/tcp # 需要注意的是,如果是加的区段值,删的时候也必须为区段值

查看开启的端口和服务

firewall-cmd --permanent --list-ports # 查看开启的端口号
firewall-cmd --permanent --list-services

docker命令

之前写过docker简单篇和深入篇。

alt

这里还需要补充一些命令:

导入、导出镜像

当我们pull下来一个镜像之后,可以导出一个tar包,然后下次可以用这个tar包再次导入进来

docker save java > /home/java.tar.gz
docker load < /home/java.tar.gz

启动容器

docker run -it --name myjava java bash
docker run -it --name myjava -p 9000:8080 -p 9001:8085 java bash
docker run -it --name myjava -v /home/project:/soft --privileged java bash

停止、挂起、恢复容器

docker stop 容器ID
docker pause 容器ID
docker unpase 容器ID

查看容器信息

docker inspect 容器ID

数据卷管理

docker volume create 数据卷名称  #创建数据卷
docker volume rm 数据卷名称  #删除数据卷
docker volume inspect 数据卷名称  #查看数据卷

网络管理

docker network ls 查看网络信息
docker network create --subnet=网段 网络名称
docker network rm 网络名称

避免VM虚拟机挂起恢复之后,Docker虚拟机断网

vi /etc/sysctl.conf

文件中添加net.ipv4.ip_forward=1这个配置

随后重启网络服务:

systemctl  restart network

MySQL集群

常见MySQL集群方案

alt

PXC全称是Percona XtraDB Cluster

建议PXC使用PerconaServer(MySQL改进版,性能提升很大)

PXC方案与Replication方案的对比

alt

alt

PXC的数据强一致性

  • 同步复制,事务在所有集群节点要么同时提交,要么不提交

alt

  • Replication采用异步复制,无法保证数据的一致性

alt

MySQL相关命令:

STOP SLAVE
SHOW SLAVE STATUS

安装PXC集群

docker pull percona/percona-xtradb-cluster

为PXC镜像改名:

docker tag percona/percona-xtradb-cluster pxc

出于安全考虑,需要给PXC集群实例创建Docker内部网络

docker network create --subnet=172.18.0.0/16 net1

创建PXC容器

在创建容器之前,先要创建数据卷,假设我们要开5个PXC容器,就需要5个数据卷:

docker volume create --name v1
docker volume create --name v2
docker volume create --name v3
docker volume create --name v4
docker volume create --name v5
#创建第1个MySQL节点
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v1:/var/lib/mysql -v backup:/data --privileged --name=node1 --net=net1 --ip 172.18.0.2 pxc
#创建第2个MySQL节点
docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v2:/var/lib/mysql -v backup:/data --privileged --name=node2 --net=net1 --ip 172.18.0.3 pxc
#创建第3个MySQL节点
docker run -d -p 3308:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v3:/var/lib/mysql --privileged --name=node3 --net=net1 --ip 172.18.0.4 pxc
#创建第4个MySQL节点
docker run -d -p 3309:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v4:/var/lib/mysql --privileged --name=node4 --net=net1 --ip 172.18.0.5 pxc
#创建第5个MySQL节点
docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v5:/var/lib/mysql -v backup:/data --privileged --name=node5 --net=net1 --ip 172.18.0.6 pxc

注意,每个MySQL容器创建之后,因为要执行PXC的初始化和加入集群等工作,耐心等待1分钟左右再用客户端连接MySQL。另外,必须第1个MySQL节点启动成功,用MySQL客户端能连接上之后,再去创建其他MySQL节点。

数据库负载均衡的必要性

  • 虽然搭建了集群,但是不使用数据库负载均衡,单点节处理所有请求,负载高,性能差

alt

  • 使用Hapoxy做负载均衡,请求被均匀发给每个节点,单节点负载低,性能好

alt

负载均衡中间件对比

alt

Haproxy相关

安装镜像

docker pull haproxy

配置文件

可以在宿主机上新建haproxy.cfg,通过-v映射到容器内

# haproxy.cfg的配置
global
    #工作目录
    chroot /usr/local/etc/haproxy
    #日志文件,使用rsyslog服务中local5日志设备(/var/log/local5),等级info
    log 127.0.0.1 local5 info
    #守护进程运行
    daemon
​
defaults
    log global
    mode    http
    #日志格式
    option  httplog
    #日志中不记录负载均衡的心跳检测记录
    option  dontlognull
    #连接超时(毫秒)
    timeout connect 5000
    #客户端超时(毫秒)
    timeout client  50000
    #服务器超时(毫秒)
    timeout server  50000
​
#监控界面   
listen  admin_stats
    #监控界面的访问的IP和端口
    bind  0.0.0.0:8888
    #访问协议
    mode        http
    #URI相对地址
    stats uri   /dbs
    #统计报告格式
    stats realm     Global\ statistics
    #登陆帐户信息
    stats auth  admin:abc123456
#数据库负载均衡
listen  proxy-mysql
    #访问的IP和端口
    bind  0.0.0.0:3306  
    #网络协议
    mode  tcp
    #负载均衡算法(轮询算法)
    #轮询算法:roundrobin
    #权重算法:static-rr
    #最少连接算法:leastconn
    #请求源IP算法:source 
    balance  roundrobin
    #日志格式
    option  tcplog
    #在MySQL中创建一个没有权限的haproxy用户,密码为空。Haproxy使用这个账户对MySQL数据库心跳检测
    option  mysql-check user haproxy
    server  MySQL_1 172.18.0.2:3306 check weight 1 maxconn 2000  
    server  MySQL_2 172.18.0.3:3306 check weight 1 maxconn 2000  
    server  MySQL_3 172.18.0.4:3306 check weight 1 maxconn 2000 
    server  MySQL_4 172.18.0.5:3306 check weight 1 maxconn 2000
    server  MySQL_5 172.18.0.6:3306 check weight 1 maxconn 2000
    #使用keepalive检测死链
    option  tcpka
docker run -it -d 
-p 4001:8888 -p 4002:3306
- v /home/soft/haproxy:/usr/local/etc/haproxy
--name haproxy --privileged --net=net1
haproxy
# 进入上面的haproxy容器
docker exec -it haproxy bash
haproxy -f /usr/local/etc/haproxy/haproxy.cfg

它有一个可视化的界面,端口就是上面映射的4001:

alt

红色的就是表明该节点已经失效

为什么要采用双机热备?

单节点Haproxy不具备高可用,必须要有冗余设计

alt

虚拟IP

Haproxy双机热备的方案离不开一个关键性的技术:虚拟IP。

alt

alt

Haproxy的双机热备方案

alt

#创建第1个Haproxy负载均衡服务器
docker run -it -d -p 4001:8888 -p 4002:3306 -v /home/soft/haproxy:/usr/local/etc/haproxy --name h1 --privileged --net=net1 --ip 172.18.0.7 haproxy
#进入h1容器,启动Haproxy
docker exec -it h1 bash
haproxy -f /usr/local/etc/haproxy/haproxy.cfg
#创建第2个Haproxy负载均衡服务器
docker run -it -d -p 4003:8888 -p 4004:3306 -v /home/soft/haproxy:/usr/local/etc/haproxy --name h2 --privileged --net=net1 --ip 172.18.0.8 haproxy
#进入h2容器,启动Haproxy
docker exec -it h2 bash
haproxy -f /usr/local/etc/haproxy/haproxy.cfg

Haproxy容器内安装Keepalived,设置虚拟IP

#进入h1容器
docker exec -it h1 bash
#更新软件包
apt-get update
#安装VIM
apt-get install vim
#安装Keepalived
apt-get install keepalived
#编辑Keepalived配置文件(参考下方配置文件)
vim /etc/keepalived/keepalived.conf
#启动Keepalived
service keepalived start
#宿主机执行ping命令
ping 172.18.0.201
vrrp_instance  VI_1 {
    state  MASTER
    interface  eth0
    virtual_router_id  51
    priority  100
    advert_int  1
    authentication {
        auth_type  PASS
        auth_pass  123456
    }
    virtual_ipaddress {
        172.18.0.201
    }
}
#进入h2容器
docker exec -it h2 bash
#更新软件包
apt-get update
#安装VIM
apt-get install vim
#安装Keepalived
apt-get install keepalived
#编辑Keepalived配置文件
vim /etc/keepalived/keepalived.conf
#启动Keepalived
service keepalived start
#宿主机执行ping命令
ping 172.18.0.201
vrrp_instance  VI_1 {
    state  MASTER
    interface  eth0
    virtual_router_id  51
    priority  100
    advert_int  1
    authentication {
        auth_type  PASS
        auth_pass  123456
    }
    virtual_ipaddress {
        172.18.0.201
    }
}

宿主机安装Keepalived,实现双击热备

#宿主机执行安装Keepalived
yum -y install keepalived
#修改Keepalived配置文件
vi /etc/keepalived/keepalived.conf
#启动Keepalived
service keepalived start
vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.99.150
    }
}
​
virtual_server 192.168.99.150 8888 {
    delay_loop 3
    lb_algo rr 
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
​
    real_server 172.18.0.201 8888 {
        weight 1
    }
}
​
virtual_server 192.168.99.150 3306 {
    delay_loop 3
    lb_algo rr 
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
​
    real_server 172.18.0.201 3306 {
        weight 1
    }
}

冷备份

  • 冷备份是关闭数据库时候的备份方式,通常做法是拷贝数据文件
  • 冷备份是最简单最安全的一种备份方式
  • 大型网站无法做到关闭业务备份数据,所以冷备份不是最佳选择

alt

热备份

  • 热备份是在系统运行的状态下备份数据,也是难度最大的备份
  • MySQL常见的热备份有LVM和XtraBackUp两种方案
  • 建议使用XtraBackup热备MySQL

XtraBackup优势

  • XtraBackup备份过程不锁表、快速可靠
  • XtraBackup备份过程不会打断正在执行的事务
  • XtraBackup能够基于压缩等功能节约磁盘空间和流量

全量备份和增量备份

  • 全量备份是备份全部数据。备份时间长,占用空间大

alt

  • 增量备份是只备份变化的那部分数据。备份时间短,占用空间小

alt

步骤

#进入node1容器
docker exec -it node1 bash
#更新软件包
apt-get update
#安装热备工具
apt-get install percona-xtrabackup-24
#全量热备
innobackupex --user=root --password=abc123456 /data/backup/full

另外考虑到数据备份,所以我们还得再创建一个backup的数据卷,直接映射到容器中的/data目录。

PXC全量恢复步骤

  • 数据库可以热备份,但是不能热还原。为了避免恢复过程中的数据同步,我们采用空白的MySQL还原数据,然后再建立PXC集群
  • 还原数据前要将未提交的事务回滚,还原数据之后,重启MySQL

冷还原数据 停止其余4个节点,并删除节点

docker stop node2
docker stop node3
docker stop node4
docker stop node5
docker rm node2
docker rm node3
docker rm node4
docker rm node5

node1容器中删除MySQL的数据

#删除数据
rm -rf /var/lib/mysql/*
#清空事务
innobackupex --user=root --password=abc123456 --apply-back /data/backup/full/2018-04-15_05-09-07/
#还原数据
innobackupex --user=root --password=abc123456 --copy-back  /data/backup/full/2018-04-15_05-09-07/

Redis集群

高速缓存介绍

  • 高速缓存利用内存保存数据,读写速度远超硬盘
  • 高速缓存可以减少I/O操作,降低I/O压力

Redis介绍

  • Redis是Wmware开发的开源免费的KV型NoSQL缓存产品
  • Redis具有很好的性能,最多可以提供10万次/秒的读写
  • 目前新浪微博团队组建了世界上最大规模的Redis集群

Redis集群介绍

Redis目前的集群方案分为以下几种:

  • RedisCluster:官方推荐,没有中心节点
  • Codis: 中间件产品,存在中心节点
  • Twemproxy:中间件产品,存在中心节点

RedisCluster

  • 无中心节点,客户端与redis节点直连,不需要中间代理层
  • 数据可以被分片存储
  • 管理方便,后续可自行增加或摘除节点

alt

主从同步

  • Redis集群中的数据库复制是通过主从同步来实现的
  • 主节点(Master)把数据分发给从节点(Slave)
  • 主从同步的好处在于高可用,Redis节点有冗余设计

alt

Redis集群高可用

  • Redis集群中应该包含奇数个Master,至少应该有3个Master
  • Redis集群中每个Master都应该有Slave

alt

Redis集群步骤

安装Redis

docker pull yyyyttttwwww/redis

创建net2网络

docker network create --subnet=172.19.0.0/16 net2

注意,检查一下docker网络中是否有docker_gwbridge,有的话,删除

配置Redis节点

alt

创建6节点Redis容器

docker run -it -d --name r1 -p 5001:6379 --net=net2 --ip 172.19.0.2 redis bash
docker run -it -d --name r2 -p 5002:6379 --net=net2 --ip 172.19.0.3 redis bash
docker run -it -d --name r3 -p 5003:6379 --net=net2 --ip 172.19.0.4 redis bash
docker run -it -d --name r4 -p 5004:6379 --net=net2 --ip 172.19.0.5 redis bash
docker run -it -d --name r5 -p 5005:6379 --net=net2 --ip 172.19.0.6 redis bash

启动6节点服务器

#进入r1节点
docker exec -it r1 bash
cp /home/redis/redis.conf /usr/redis/redis.conf
cd /usr/redis/src
./redis-server ../redis.conf
#进入r2节点
docker exec -it r2 bash
cp /home/redis/redis.conf /usr/redis/redis.conf
cd /usr/redis/src
./redis-server ../redis.conf
#进入r3节点
docker exec -it r3 bash
cp /home/redis/redis.conf /usr/redis/redis.conf
cd /usr/redis/src
./redis-server ../redis.conf
#进入r4节点
docker exec -it r4 bash
cp /home/redis/redis.conf /usr/redis/redis.conf
cd /usr/redis/src
./redis-server ../redis.conf
#进入r5节点
docker exec -it r5 bash
cp /home/redis/redis.conf /usr/redis/redis.conf
cd /usr/redis/src
./redis-server ../redis.conf
#进入r6节点
docker exec -it r6 bash
cp /home/redis/redis.conf /usr/redis/redis.conf
cd /usr/redis/src
./redis-server ../redis.conf

创建Cluster集群

#在r1节点上执行下面的指令
cd /usr/redis/src
mkdir -p ../cluster
cp redis-trib.rb ../cluster/
cd ../cluster
#创建Cluster集群
./redis-trib.rb create --replicas 1 172.19.0.2:6379 172.19.0.3:6379 172.19.0.4:6379 172.19.0.5:6379 172.19.0.6:6379 172.19.0.7:6379

--replicas 1参数表示为每个主节点创建一个从节点

打包部署后端项目

Maven打包

到项目目录,执行mvn命令

mvn clean install -Dmaven.test.skip=true

alt

安装Java镜像

docker pull java

创建3节点Java容器

#创建数据卷,上传JAR文件
docker volume create j1
#启动容器
docker run -it -d --name j1 -v j1:/home/soft --net=host java
#进入j1容器
docker exec -it j1 bash
#启动Java项目
nohup java -jar /home/soft/renren-fast.jar
​
#创建数据卷,上传JAR文件
docker volume create j2
#启动容器
docker run -it -d --name j2 -v j2:/home/soft --net=host java
#进入j1容器
docker exec -it j2 bash
#启动Java项目
nohup java -jar /home/soft/renren-fast.jar
​
#创建数据卷,上传JAR文件
docker volume create j3
#启动容器
docker run -it -d --name j3 -v j3:/home/soft --net=host java
#进入j1容器
docker exec -it j3 bash
#启动Java项目
nohup java -jar /home/soft/renren-fast.jar

后台程序负载均衡

Nginx是性能非常出色的反向代理服务器,最大可以支持8万/秒的并发访问

alt

docker pull nginx

宿主机上/home/n1/nginx.conf配置文件内容如下:

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
​
events {
    worker_connections  1024;
}
​
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
​
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
​
    access_log  /var/log/nginx/access.log  main;
​
    sendfile        on;
    #tcp_nopush     on;
​
    keepalive_timeout  65;
​
    #gzip  on;

    proxy_redirect          off;
    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size    10m;
    client_body_buffer_size   128k;
    proxy_connect_timeout   5s;
    proxy_send_timeout      5s;
    proxy_read_timeout      5s;
    proxy_buffer_size        4k;
    proxy_buffers           4 32k;
    proxy_busy_buffers_size  64k;
    proxy_temp_file_write_size 64k;

    upstream tomcat {
        server 192.168.99.104:6001;
        server 192.168.99.104:6002;
        server 192.168.99.104:6003;
    }
    server {
        listen       6101;
        server_name  192.168.99.104; 
        location / {  
            proxy_pass   http://tomcat;
            index  index.html index.htm;  
        }  
    }
}

创建第1个Nginx节点:

docker run -it -d --name n1 -v /home/n1/nginx.conf:/etc/nginx/nginx.conf --net=host --privileged nginx

宿主机上/home/n2/nginx.conf配置文件内容如下:

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
​
events {
    worker_connections  1024;
}
​
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
​
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
​
    access_log  /var/log/nginx/access.log  main;
​
    sendfile        on;
    #tcp_nopush     on;
​
    keepalive_timeout  65;
​
    #gzip  on;

    proxy_redirect          off;
    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size    10m;
    client_body_buffer_size   128k;
    proxy_connect_timeout   5s;
    proxy_send_timeout      5s;
    proxy_read_timeout      5s;
    proxy_buffer_size        4k;
    proxy_buffers           4 32k;
    proxy_busy_buffers_size  64k;
    proxy_temp_file_write_size 64k;

    upstream tomcat {
        server 192.168.99.104:6001;
        server 192.168.99.104:6002;
        server 192.168.99.104:6003;
    }
    server {
        listen       6102;
        server_name  192.168.99.104; 
        location / {  
            proxy_pass   http://tomcat;
            index  index.html index.htm;  
        }  
    }
}

创建第2个Nginx节点:

docker run -it -d --name n2 -v /home/n2/nginx.conf:/etc/nginx/nginx.conf --net=host --privileged nginx

在Nginx容器安装Keepalived

alt

#进入n1节点
docker exec -it n1 bash
#更新软件包
apt-get update
#安装VIM
apt-get install vim
#安装Keepalived
apt-get install keepalived
#编辑Keepalived配置文件(如下)
vim /etc/keepalived/keepalived.conf
#启动Keepalived
service keepalived start
vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        192.168.99.151
    }
}
virtual_server 192.168.99.151 6201 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
    real_server 192.168.99.104 6101 {
        weight 1
    }
}
#进入n2节点
docker exec -it n2 bash
#更新软件包
apt-get update
#安装VIM
apt-get install vim
#安装Keepalived
apt-get install keepalived
#编辑Keepalived配置文件(如下)
vim /etc/keepalived/keepalived.conf
#启动Keepalived
service keepalived start
vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        192.168.99.151
    }
}
virtual_server 192.168.99.151 6201 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
    real_server 192.168.99.104 6102 {
        weight 1
    }
}

前端程序负载均衡

基本上方案同后端的。。

npm run build

运行出最终的文件包(如dist),然后放到多个容器中。

alt

和后端的差别在于6501 6502 6503这些都是通过nginx服务启动起来的,而后端是通过tomcat启动起来的。

多主机集群

上述说的都是单主机集群,但如果这台主机挂了,那就杯具了,因此需要考虑多主机集群。

docker的多主机集群方案有两种:

  • swarm
  • k8s

alt

alt

Docker Swarm

alt

alt

去中心化的设计

alt

创建Swarm集群

docker swarm init

alt

加入Swarm集群

docker swarm join-token manage
docker swarm join-token worker

添加manager或者worker节点到集 群,只要执行对应的命令即可

查看Swarm集群节点

docker node ls

只可以在Manage节点执行该命令

查看Swarm集群网络

alt

创建共享网络

docker network create -d overlay --attachable swarm_test

ingress网络用于管理Swarm集群,所以我们需要创建新的共享网络

创建容器

docker run -it --net=swarm_test ...

alt

容器集群

alt

容器集群适用场合

容器集群不适合有状态程序,例如数据库、缓存等等。

alt

退出Swarm集群

docker swarm leave --force

Manage退出集群必须要使用--force参数

alt

使用Portainer管理Docker

Portainer是Docker的可视化界面,不过有些命令可能还是需要在命令行执行。

alt

要让Portainer真正接管docker的管理,我们必须要修改一下Docker网络管理端口,开放出来2375端口。

vi /etc/sysconfig/docker

在配置文件结尾添加开放Docker开发2375端口的参数:

OPTIONS='-Htcp://0.0.0.0:2375 -H unix:///var/run/docker.sock'

启动Portainer容器

docker run -d -p 9000:9000
portainer/portainer -H tcp://192.168.99.196:2375

192.168.99.196为宿主机的IP,不是容器IP

总结

前端部署方案

alt

后端部署方案

alt

数据库集成部署方案

alt

Redis集成部署方案

alt

结语

这个课程学了之后,对于单主机的集成部署方案掌握了80-90%,然而对于多主机的集成部署掌握似乎只有一半左右。。

一方面可能对于docker有些命令还是欠熟练,另外对于运维这一块还是有待提高吧。

继续加油!!

本文链接:www.my-fe.pub/post/docker-front-and-backend-separation.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。