Docker 实战(六):使用 Docker Compose 搭建 Web 集群

实战(四) 中,使用 HAProxy 和 Tomcat 搭建了一个简单的 Tomcat 集群。
这节会去掉 Tomcat,使用 Spring Boot 和 MySQL 组成一个比较典型的负载均衡集群。

目录

1
2
3
4
5
6
compose-haproxy-web
- docker-compose.yml
+ haproxy
- haproxy.cfg
+ web
- paper-0.0.1-SNAPSHOT.jar

docker-compose.yml

MySQL 配置

1
2
3
4
5
6
7
image: batizhao/mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: paper
MYSQL_ROOT_HOST: "%"
expose:
- "3306"

MYSQL_DATABASE 需要在启动时创建 paper 数据库。
MYSQL_ROOT_HOST 在 mysql user 中增加客户端远程访问的权限。

在 batizhao/mysql 这个镜像中,有一个自定义的 my.cnf 文件,主要是定义了 bind-address ,否则会遇到 CommunicationsException: Communications link failure 的错误,还有一些服务端、客户端 UTF-8 编码的定义。

Web 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
image: batizhao/java:8
command: java -jar opt/paper.jar
volumes:
- ./web/paper-0.0.1-SNAPSHOT.jar:/opt/paper.jar
depends_on:
- "mysql"
links:
- "mysql:database"
expose:
- "8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://database:3306/paper?useUnicode=true&useSSL=false
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=password
- SPRING_DATASOURCE_SQL-SCRIPT-ENCODING=UTF-8

volumes 这个 Spring Boot 应用在 Github,可以自己打包放到 web 目录。
SPRING_DATASOURCE_SQL-SCRIPT-ENCODING 这个配置必须要有,否则初始化脚本会插入乱码到数据库。已经确定和 MySQL 无关,因为在宿主机启动 App 直接连接 MySQL 容器,并且在启动后插入中文数据都没有问题。只是在容器中启动 App 初始化时才会乱码,后来改 Web 容器编码也不起作用,加上这个配置就好了。

全部的 compose 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
version: '2'
services:
mysql:
image: batizhao/mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: paper
MYSQL_ROOT_HOST: "%"
expose:
- "3306"

weba:
image: batizhao/java:8
command: java -jar opt/paper.jar
volumes:
- ./web/paper-0.0.1-SNAPSHOT.jar:/opt/paper.jar
depends_on:
- "mysql"
links:
- "mysql:database"
expose:
- "8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://database:3306/paper?useUnicode=true&useSSL=false
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=password
- SPRING_DATASOURCE_SQL-SCRIPT-ENCODING=UTF-8

webb:
image: batizhao/java:8
command: java -jar opt/paper.jar
volumes:
- ./web/paper-0.0.1-SNAPSHOT.jar:/opt/paper.jar
depends_on:
- "mysql"
links:
- "mysql:database"
expose:
- "8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://database:3306/paper?useUnicode=true&useSSL=false
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=password
- SPRING_DATASOURCE_SQL-SCRIPT-ENCODING=UTF-8

haproxy:
image: haproxy
volumes:
- ./haproxy:/haproxy-override
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
links:
- weba
- webb
ports:
- "80:80"
- "70:70"
expose:
- "80"
- "70"

haproxy.cfg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
daemon

defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 2000
timeout connect 5000
timeout client 50000
timeout server 50000

frontend balancer
bind 0.0.0.0:80
mode http
default_backend servers

backend servers
option httpchk OPTIONS /
option forwardfor
cookie JSESSIONID prefix
server tomcat1 weba:8080 cookie JSESSIONID_SERVER_1 check inter 5000
server tomcat2 webb:8080 cookie JSESSIONID_SERVER_2 check inter 5000

listen status
mode http
default_backend servers
bind 0.0.0.0:70
stats enable
stats hide-version
stats uri /stats
stats auth admin:password
stats admin if TRUE

启动容器

1
2
3
4
5
6
7
8
9
10
11
$ docker-compose up
Creating network "composehaproxyweb_default" with the default driver
Creating composehaproxyweb_mysql_1
Creating composehaproxyweb_webb_1
Creating composehaproxyweb_weba_1
Creating composehaproxyweb_haproxy_1
Attaching to composehaproxyweb_mysql_1, composehaproxyweb_webb_1, composehaproxyweb_weba_1, composehaproxyweb_haproxy_1
mysql_1 | Initializing database
haproxy_1 | <7>haproxy-systemd-wrapper: executing /usr/local/sbin/haproxy -p /run/haproxy.pid -f /usr/local/etc/haproxy/haproxy.cfg -Ds
mysql_1 | Database initialized
mysql_1 | MySQL init process in progress...

访问 http://localhost
使用 admin/123456 可以登录系统。

访问 http://localhost:70/stats
使用 admin/password 可以看到集群状态。