赞
踩
本章是《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文件夹,如下图红框所示:
接下来开始镜像制作吧;
先整理出我们需要一个什么样的镜像:
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是制作镜像时执行的脚本,内容如下:
- # Docker file for rabbitmq single or cluster from bolingcavalry
- # VERSION 0.0.3
- # Author: bolingcavalry
-
- #基础镜像
- FROM centos:7
-
- #作者
- MAINTAINER BolingCavalry <zq2599@gmail.com>
-
- #定义时区参数
- ENV TZ=Asia/Shanghai
-
- #设置时区
- RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone
-
- #设置编码为中文
- RUN yum -y install kde-l10n-Chinese glibc-common
-
- RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
-
- ENV LC_ALL zh_CN.utf8
-
- #安装wget工具
- RUN yum install -y wget unzip tar
-
- #安装erlang
- RUN 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
-
- RUN yum install -y erlang
-
- #安装rabbitmq
- RUN rpm --import http://www.rabbitmq.com/rabbitmq-signing-key-public.asc
-
- RUN 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
-
- RUN /usr/sbin/rabbitmq-plugins list <<<'y'
-
- #安装常用插件
- RUN /usr/sbin/rabbitmq-plugins enable --offline rabbitmq_mqtt rabbitmq_stomp rabbitmq_management rabbitmq_management_agent rabbitmq_federation rabbitmq_federation_management <<<'y'
-
- #添加配置文件
- ADD rabbitmq.config /etc/rabbitmq/
-
- #添加cookie,使集群环境中的机器保持互通
- ADD erlang.cookie /var/lib/rabbitmq/.erlang.cookie
-
- #添加启动容器时执行的脚本,主要根据启动时的入参做集群设置
- ADD startrabbit.sh /opt/rabbit/
-
- #给相关资源赋予权限
- RUN chmod u+rw /etc/rabbitmq/rabbitmq.config \
- && chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie \
- && chmod 400 /var/lib/rabbitmq/.erlang.cookie \
- && mkdir -p /opt/rabbit \
- && chmod a+x /opt/rabbit/startrabbit.sh
-
- #暴露常用端口
- EXPOSE 5672
- EXPOSE 15672
- EXPOSE 25672
- EXPOSE 4369
- EXPOSE 9100
- EXPOSE 9101
- EXPOSE 9102
- EXPOSE 9103
- EXPOSE 9104
- EXPOSE 9105
-
- #设置容器创建时执行的脚本
- CMD /opt/rabbit/startrabbit.sh
如上所示,每个功能都有对应的注释,就不再赘述了;
startrabbit.sh内容如下:
- #!/bin/bash
- change_default_user() {
-
- if [ -z $RABBITMQ_DEFAULT_USER ] && [ -z $RABBITMQ_DEFAULT_PASS ]; then
- echo "Maintaining default 'guest' user"
- else
- echo "Removing 'guest' user and adding ${RABBITMQ_DEFAULT_USER}"
- rabbitmqctl delete_user guest
- rabbitmqctl add_user $RABBITMQ_DEFAULT_USER $RABBITMQ_DEFAULT_PASS
- rabbitmqctl set_user_tags $RABBITMQ_DEFAULT_USER administrator
- rabbitmqctl set_permissions -p / $RABBITMQ_DEFAULT_USER ".*" ".*" ".*"
- fi
- }
-
- HOSTNAME=`env hostname`
-
- if [ -z "$CLUSTERED" ]; then
- # if not clustered then start it normally as if it is a single server
- /usr/sbin/rabbitmq-server &
- rabbitmqctl wait /var/lib/rabbitmq/mnesia/rabbit\@$HOSTNAME.pid
- change_default_user
- tail -f /var/log/rabbitmq/rabbit\@$HOSTNAME.log
- else
- if [ -z "$CLUSTER_WITH" ]; then
- # If clustered, but cluster with is not specified then again start normally, could be the first server in the
- # cluster
- /usr/sbin/rabbitmq-server&
- rabbitmqctl wait /var/lib/rabbitmq/mnesia/rabbit\@$HOSTNAME.pid
- tail -f /var/log/rabbitmq/rabbit\@$HOSTNAME.log
- else
- /usr/sbin/rabbitmq-server &
- rabbitmqctl wait /var/lib/rabbitmq/mnesia/rabbit\@$HOSTNAME.pid
- rabbitmqctl stop_app
- if [ -z "$RAM_NODE" ]; then
- rabbitmqctl join_cluster rabbit@$CLUSTER_WITH
- else
- rabbitmqctl join_cluster --ram rabbit@$CLUSTER_WITH
- fi
-
- rabbitmqctl start_app
-
- # If set ha flag, enable here
- if [ -z "$HA_ENABLE" ]; then
- echo "Running with normal cluster mode"
- else
- rabbitmqctl set_policy HA '^(?!amq\.).*' '{"ha-mode": "all"}'
- echo "Running wiht HA cluster mode"
- fi
-
- # Tail to keep the a foreground process active..
- tail -f /var/log/rabbitmq/rabbit\@$HOSTNAME.log
- fi
- fi
这个脚本有以下几点需要注意:
1. if [ -z “$CLUSTERED” ]表示如果环境变量中没有CLUSTERED这个参数;
2. 如果环境变量中没有CLUSTERED这个参数,当前容器的身份就是主,会调用change_default_user方法,这个方法中检查是否输入了用户名和密码,如果有就创建用户,并赋予管理员权限,再把原有的guest账号删除;
3. 如果环境变量中有CLUSTERED这个参数,当前容器身份就是从,会执行rabbitmqctl join_cluster命令加入到集群中去;
4. 如果环境变量中有RAM_NODE这个参数,会在rabbitmqctl join_cluster命令中带上ram参数,表示当前节点为内存节点;
5. 如果环境变量中有HA_ENABLE这个参数,就在启动RabbitMQ之后执行命令rabbitmqctl set_policy,将集群中的队列变为镜像队列,实现集群高可用;
以上就是制作镜像前的准备工作,完成之后在Dockerfile文件所在目录下执行命令docker build -t bolingcavalry/rabbitmq-server:0.0.3 .,即可构建镜像;
这个docker-compose.yml在上一章我们用过,内容如下:
- rabbitmq:
- image: bolingcavalry/rabbitmq-server:0.0.3
- hostname: rabbitmq
- ports:
- - "15672:15672"
- environment:
- - RABBITMQ_DEFAULT_USER=admin
- - RABBITMQ_DEFAULT_PASS=888888
- producer:
- image: bolingcavalry/rabbitmqproducer:0.0.2-SNAPSHOT
- hostname: producer
- links:
- - rabbitmq:rabbitmqhost
- ports:
- - "18080:8080"
- environment:
- - mq.rabbit.address=rabbitmqhost:5672
- - mq.rabbit.username=admin
- - mq.rabbit.password=888888
- consumer:
- image: bolingcavalry/rabbitmqconsumer:0.0.3-SNAPSHOT
- hostname: consumer
- links:
- - rabbitmq:rabbitmqhost
- environment:
- - mq.rabbit.address=rabbitmqhost:5672
- - mq.rabbit.username=admin
- - mq.rabbit.password=888888
- - mq.rabbit.queue.name=consumer.queue
producer和consumer的配置我们下一章再看,现在重点关注rabbitmq的配置:
1. 没有CLUSTERED参数,表示该容器以主的身份运行;
2. RABBITMQ_DEFAULT_USER、RABBITMQ_DEFAULT_PASS这两个参数设定了此RabbitMQ的管理员权限的账号和密码;
内容如下:
- version: '2'
- services:
- rabbit1:
- image: bolingcavalry/rabbitmq-server:0.0.3
- hostname: rabbit1
- ports:
- - "15672:15672"
- environment:
- - RABBITMQ_DEFAULT_USER=admin
- - RABBITMQ_DEFAULT_PASS=888888
- rabbit2:
- image: bolingcavalry/rabbitmq-server:0.0.3
- hostname: rabbit2
- depends_on:
- - rabbit1
- links:
- - rabbit1
- environment:
- - CLUSTERED=true
- - CLUSTER_WITH=rabbit1
- - RAM_NODE=true
- ports:
- - "15673:15672"
- rabbit3:
- image: bolingcavalry/rabbitmq-server:0.0.3
- hostname: rabbit3
- depends_on:
- - rabbit2
- links:
- - rabbit1
- - rabbit2
- environment:
- - CLUSTERED=true
- - CLUSTER_WITH=rabbit1
- ports:
- - "15675:15672"
- producer:
- image: bolingcavalry/rabbitmqproducer:0.0.2-SNAPSHOT
- hostname: producer
- depends_on:
- - rabbit3
- links:
- - rabbit1:rabbitmqhost
- ports:
- - "18080:8080"
- environment:
- - mq.rabbit.address=rabbitmqhost:5672
- - mq.rabbit.username=admin
- - mq.rabbit.password=888888
- consumer1:
- image: bolingcavalry/rabbitmqconsumer:0.0.3-SNAPSHOT
- hostname: consumer1
- depends_on:
- - producer
- links:
- - rabbit2:rabbitmqhost
- environment:
- - mq.rabbit.address=rabbitmqhost:5672
- - mq.rabbit.username=admin
- - mq.rabbit.password=888888
- - mq.rabbit.queue.name=consumer1.queue
- consumer2:
- image: bolingcavalry/rabbitmqconsumer:0.0.3-SNAPSHOT
- hostname: consumer2
- depends_on:
- - consumer1
- links:
- - rabbit3:rabbitmqhost
- environment:
- - mq.rabbit.address=rabbitmqhost:5672
- - mq.rabbit.username=admin
- - mq.rabbit.password=888888
- - mq.rabbit.queue.name=consumer2.queue
这个脚本有以下几点需要注意:
1. rabbit1是主节点;
2. rabbit2和rabbit3由于设置了CLUSTERED,身份成为从节点,在startrabbit.sh脚本中,会通过rabbitmqctl join_cluster命令加入到主节点的集群中去,加入时如何找到主节点呢?用的是CLUSTER_WITH参数,而CLUSTER_WITH参数的值,在docker-compose.yml中通过link参数设置为rabbit1;
3. rabbit2设置了RAM_NODE,所以是个内存节点;
至此,整个RabbitMQ镜像制作和使用的详细分析就结束了,您也可以自行实战,在Dockerfile和startrabbit.sh中增加一些命令来对RabbitMQ做更多个性化的设置,下一章,我们开发两个基于SpringBoot的工程,分别用来生产和消费消息;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。