Docker下RabbitMQ四部曲之二:细说RabbitMQ镜像制作

释放双眼,带上耳机,听听看~!

本章是《Docker下RabbitMQ四部曲》系列的第二篇,将详细简述Docker下制作RabbitMQ镜像的技术细节,包括以下内容:

  1. 列举制作RabbitMQ镜像时用到的所有材料;
  2. 编写Dockerfile;
  3. 编写容器启动时执行的脚本startrabbit.sh;
  4. 单机版RabbtiMQ环境的docker-compose.yml说明;
  5. 集群版RabbitMQ环境的docker-compose.yml说明;

文件和源码下载

您可以在GitHub下载本文涉及到的文件和源码,地址和链接信息如下表所示:

项目主页
https://github.com/zq2599/blog_demos
该项目在GitHub上的主页
git仓库地址(https)
https://github.com/zq2599/blog_demos.git
该项目源码的仓库地址,https协议
git仓库地址(ssh)
git@github.com:zq2599/blog_demos.git
该项目源码的仓库地址,ssh协议

这个git项目中有多个文件夹,本章所需的内容在
rabbitmq_docker_files文件夹,如下图红框所示:

接下来开始镜像制作吧;

RabbitMQ镜像要做的事情

先整理出我们需要一个什么样的镜像:

  1. 基础镜像为centos:7;
  2. 时区:Asia/Shanghai;
  3. 编码:zh_CN.UTF-8;
  4. 装好了Erlang;
  5. 装好了RabbitMQ;
  6. 集群时候各个RabbitMQ机器之间的访问权限是通过erlang.cookie来控制的,所以在镜像中提前准备好erlang.cookie,这样使用该镜像的所有容器由于erlang.cookie相同,就有了相互访问的权限;
  7. 创建容器时,可以通过参数来控制容器身份,例如集群版的主或者从,如果是身份是从,还要让从知道主的地址;
  8. 创建容器时,可以通过参数设置RabbitMQ,例如用户名和密码、是否是内存节点、是否是高可用的镜像队列;

以上就是RabbitMQ镜像所具备的功能,其中1-6都可以在Dockerfile中实现,7和8是在容器启动后要做的事情,所以要做个shell脚本来完成,容器创建时自动执行这个脚本;

准备镜像制作材料

根据前面列出的功能点,我们需要准备下面以下材料来制作镜像:

  1. Dockerfile:制作Docker镜像必须的脚本文件
  2. erlang.cookie:允许多个RabbitMQ容器相互访问的权限文件
  3. rabbitmq.config:RabbitMQ配置文件
  4. startrabbit.sh:容器创建时执行的脚本

这些材料在github上都能获取到,地址:https://github.com/zq2599/blog_demos/tree/master/rabbitmq_docker_files/image

erlang.cookie和rabbitmq.config很简单不需多说,我们细看Dockerfile和startrabbit.sh;

Dockerfile

Dockerfile是制作镜像时执行的脚本,内容如下:


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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
1# Docker file for rabbitmq single or cluster from bolingcavalry
2# VERSION 0.0.3
3# Author: bolingcavalry
4
5#基础镜像
6FROM centos:7
7
8#作者
9MAINTAINER BolingCavalry <zq2599@gmail.com>
10
11#定义时区参数
12ENV TZ=Asia/Shanghai
13
14#设置时区
15RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone
16
17#设置编码为中文
18RUN yum -y install kde-l10n-Chinese glibc-common
19
20RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
21
22ENV LC_ALL zh_CN.utf8
23
24#安装wget工具
25RUN yum install -y wget unzip tar
26
27#安装erlang
28RUN rpm -Uvh https://github.com/rabbitmq/erlang-rpm/releases/download/v19.3.6.5/erlang-19.3.6.5-1.el7.centos.x86_64.rpm
29
30RUN yum install -y erlang
31
32#安装rabbitmq
33RUN rpm --import http://www.rabbitmq.com/rabbitmq-signing-key-public.asc
34
35RUN yum install -y https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.7.5-rc.1/rabbitmq-server-3.7.5.rc.1-1.el7.noarch.rpm
36
37RUN /usr/sbin/rabbitmq-plugins list <<<'y'
38
39#安装常用插件
40RUN /usr/sbin/rabbitmq-plugins enable --offline rabbitmq_mqtt rabbitmq_stomp rabbitmq_management  rabbitmq_management_agent rabbitmq_federation rabbitmq_federation_management <<<'y'
41
42#添加配置文件
43ADD rabbitmq.config /etc/rabbitmq/
44
45#添加cookie,使集群环境中的机器保持互通
46ADD erlang.cookie /var/lib/rabbitmq/.erlang.cookie
47
48#添加启动容器时执行的脚本,主要根据启动时的入参做集群设置
49ADD startrabbit.sh /opt/rabbit/
50
51#给相关资源赋予权限
52RUN chmod u+rw /etc/rabbitmq/rabbitmq.config \
53&& chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie \
54&& chmod 400 /var/lib/rabbitmq/.erlang.cookie \
55&& mkdir -p /opt/rabbit \
56&& chmod a+x /opt/rabbit/startrabbit.sh
57
58#暴露常用端口
59EXPOSE 5672
60EXPOSE 15672
61EXPOSE 25672
62EXPOSE 4369
63EXPOSE 9100
64EXPOSE 9101
65EXPOSE 9102
66EXPOSE 9103
67EXPOSE 9104
68EXPOSE 9105
69
70#设置容器创建时执行的脚本
71CMD /opt/rabbit/startrabbit.sh
72
73

如上所示,每个功能都有对应的注释,就不再赘述了;

容器启动后执行的脚本startrabbit.sh

startrabbit.sh内容如下:


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
1#!/bin/bash
2
3change_default_user() {
4
5        if [ -z $RABBITMQ_DEFAULT_USER ] && [ -z $RABBITMQ_DEFAULT_PASS ]; then
6                echo "Maintaining default 'guest' user"
7        else
8                echo "Removing 'guest' user and adding ${RABBITMQ_DEFAULT_USER}"
9                rabbitmqctl delete_user guest
10                rabbitmqctl add_user $RABBITMQ_DEFAULT_USER $RABBITMQ_DEFAULT_PASS
11                rabbitmqctl set_user_tags $RABBITMQ_DEFAULT_USER administrator
12                rabbitmqctl set_permissions -p / $RABBITMQ_DEFAULT_USER ".*" ".*" ".*"
13        fi
14}
15
16HOSTNAME=`env hostname`
17
18if [ -z "$CLUSTERED" ]; then
19        # if not clustered then start it normally as if it is a single server
20        /usr/sbin/rabbitmq-server &
21        rabbitmqctl wait /var/lib/rabbitmq/mnesia/rabbit\@$HOSTNAME.pid
22        change_default_user
23        tail -f /var/log/rabbitmq/rabbit\@$HOSTNAME.log
24else
25        if [ -z "$CLUSTER_WITH" ]; then
26                # If clustered, but cluster with is not specified then again start normally, could be the first server in the
27                # cluster
28                /usr/sbin/rabbitmq-server&
29                rabbitmqctl wait /var/lib/rabbitmq/mnesia/rabbit\@$HOSTNAME.pid
30                tail -f /var/log/rabbitmq/rabbit\@$HOSTNAME.log
31        else
32                /usr/sbin/rabbitmq-server &
33                rabbitmqctl wait /var/lib/rabbitmq/mnesia/rabbit\@$HOSTNAME.pid
34                rabbitmqctl stop_app
35                if [ -z "$RAM_NODE" ]; then
36                        rabbitmqctl join_cluster rabbit@$CLUSTER_WITH
37                else
38                        rabbitmqctl join_cluster --ram rabbit@$CLUSTER_WITH
39                fi
40
41                rabbitmqctl start_app
42
43                # If set ha flag, enable here
44                if [ -z "$HA_ENABLE" ]; then
45                        echo "Running with normal cluster mode"
46                else
47                        rabbitmqctl set_policy HA '^(?!amq\.).*' '{"ha-mode": "all"}'
48                        echo "Running wiht HA cluster mode"
49                fi
50                
51                # Tail to keep the a foreground process active..
52                tail -f /var/log/rabbitmq/rabbit\@$HOSTNAME.log
53        fi
54fi
55
56

这个脚本有以下几点需要注意:

  1. if [ -z “$CLUSTERED” ]表示如果环境变量中没有

CLUSTERED这个参数;

  1. 如果环境变量中没有

CLUSTERED这个参数,当前容器的身份就是主,会调用change_default_user方法,这个方法中检查是否输入了用户名和密码,如果有就创建用户,并赋予管理员权限,再把原有的guest账号删除;

  1. 如果环境变量中有

CLUSTERED这个参数,当前容器身份就是从,会执行
rabbitmqctl join_cluster命令加入到集群中去;

  1. 如果环境变量中有

RAM_NODE这个参数,会在rabbitmqctl join_cluster命令中带上ram参数,表示当前节点为内存节点;

  1. 如果环境变量中有

HA_ENABLE这个参数,就在启动RabbitMQ之后执行命令
rabbitmqctl set_policy,将集群中的队列变为镜像队列,实现集群高可用;

构建镜像

以上就是制作镜像前的准备工作,完成之后在Dockerfile文件所在目录下执行命令
docker build -t bolingcavalry/rabbitmq-server:0.0.3 .,即可构建镜像;

单机版的docker-compose.yml

这个docker-compose.yml在上一章我们用过,内容如下:


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
1rabbitmq:
2  image: bolingcavalry/rabbitmq-server:0.0.3
3  hostname: rabbitmq
4  ports:
5    - "15672:15672"
6  environment:
7    - RABBITMQ_DEFAULT_USER=admin
8    - RABBITMQ_DEFAULT_PASS=888888
9producer:
10  image: bolingcavalry/rabbitmqproducer:0.0.2-SNAPSHOT
11  hostname: producer
12  links:
13    - rabbitmq:rabbitmqhost
14  ports:
15      - "18080:8080"
16  environment:
17   - mq.rabbit.address=rabbitmqhost:5672
18   - mq.rabbit.username=admin
19   - mq.rabbit.password=888888
20consumer:
21  image: bolingcavalry/rabbitmqconsumer:0.0.3-SNAPSHOT
22  hostname: consumer
23  links:
24    - rabbitmq:rabbitmqhost
25  environment:
26   - mq.rabbit.address=rabbitmqhost:5672
27   - mq.rabbit.username=admin
28   - mq.rabbit.password=888888
29   - mq.rabbit.queue.name=consumer.queue
30
31

producer和consumer的配置我们下一章再看,现在重点关注rabbitmq的配置:

  1. 没有

CLUSTERED参数,表示该容器以主的身份运行;

  1. RABBITMQ_DEFAULT_USER、RABBITMQ_DEFAULT_PASS这两个参数设定了此RabbitMQ的管理员权限的账号和密码;

集群版的docker-compose.yml

内容如下:


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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
1version: '2'
2services:
3  rabbit1:
4    image: bolingcavalry/rabbitmq-server:0.0.3
5    hostname: rabbit1
6    ports:
7      - "15672:15672"
8    environment:
9      - RABBITMQ_DEFAULT_USER=admin
10      - RABBITMQ_DEFAULT_PASS=888888
11  rabbit2:
12    image: bolingcavalry/rabbitmq-server:0.0.3
13    hostname: rabbit2
14    depends_on:
15      - rabbit1
16    links:
17      - rabbit1
18    environment:
19     - CLUSTERED=true
20     - CLUSTER_WITH=rabbit1
21     - RAM_NODE=true
22    ports:
23      - "15673:15672"
24  rabbit3:
25    image: bolingcavalry/rabbitmq-server:0.0.3
26    hostname: rabbit3
27    depends_on:
28      - rabbit2
29    links:
30      - rabbit1
31      - rabbit2
32    environment:
33      - CLUSTERED=true
34      - CLUSTER_WITH=rabbit1
35    ports:
36      - "15675:15672"
37  producer:
38    image: bolingcavalry/rabbitmqproducer:0.0.2-SNAPSHOT
39    hostname: producer
40    depends_on:
41      - rabbit3
42    links:
43      - rabbit1:rabbitmqhost
44    ports:
45      - "18080:8080"
46    environment:
47      - mq.rabbit.address=rabbitmqhost:5672
48      - mq.rabbit.username=admin
49      - mq.rabbit.password=888888
50  consumer1:
51    image: bolingcavalry/rabbitmqconsumer:0.0.3-SNAPSHOT
52    hostname: consumer1
53    depends_on:
54      - producer
55    links:
56      - rabbit2:rabbitmqhost
57    environment:
58     - mq.rabbit.address=rabbitmqhost:5672
59     - mq.rabbit.username=admin
60     - mq.rabbit.password=888888
61     - mq.rabbit.queue.name=consumer1.queue
62  consumer2:
63    image: bolingcavalry/rabbitmqconsumer:0.0.3-SNAPSHOT
64    hostname: consumer2
65    depends_on:
66      - consumer1
67    links:
68      - rabbit3:rabbitmqhost
69    environment:
70      - mq.rabbit.address=rabbitmqhost:5672
71      - mq.rabbit.username=admin
72      - mq.rabbit.password=888888
73      - mq.rabbit.queue.name=consumer2.queue
74
75

这个脚本有以下几点需要注意:

  1. rabbit1是主节点;
  2. rabbit2和rabbit3由于设置了

CLUSTERED,身份成为从节点,在startrabbit.sh脚本中,会通过
rabbitmqctl join_cluster命令加入到主节点的集群中去,加入时如何找到主节点呢?用的是CLUSTER_WITH参数,而CLUSTER_WITH参数的值,在docker-compose.yml中通过link参数设置为rabbit1;

  1. rabbit2设置了RAM_NODE,所以是个内存节点;

至此,整个RabbitMQ镜像制作和使用的详细分析就结束了,您也可以自行实战,在Dockerfile和startrabbit.sh中增加一些命令来对RabbitMQ做更多个性化的设置,下一章,我们开发两个基于SpringBoot的工程,分别用来生产和消费消息;

参考并致敬:https://github.com/bijukunjummen/docker-rabbitmq-cluster

给TA打赏
共{{data.count}}人
人已打赏
安全网络

CDN安全市场到2022年价值76.3亿美元

2018-2-1 18:02:50

安全技术

Java电商秒杀系统性能优化(二)——云端部署,性能压测【从本地调试到云端上线的必经之路】

2022-1-11 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索