基于docker-compose,从镜像构建开始,本地一步一步手动在单机上搭建一个storm容器集群。

1 docker镜像制作

1.1 storm docker镜像制作预备

配置docker镜像下载加速

root@sure-PC:~/storm# cat /etc/docker/daemon.json 
{
  "registry-mirrors": [
        "https://hub-mirror.c.163.com",
        "https://1nj0zren.mirror.aliyuncs.com",
        "https://docker.mirrors.ustc.edu.cn",
        "http://f1361db2.m.daocloud.io",
        "https://registry.docker-cn.com"
	]
}

查看镜像信息:

查看docker日志:
centos: journalctl -u docker

dockerfile语法:
https://www.runoob.com/docker/docker-dockerfile.html     

https://linuxhandbook.com/create-custom-docker-image/

/root/storm:

apache-storm-1.0.8-SNAPSHOT
Dockerfile

Dockerfile内容:

FROM openjdk:16-slim-buster
COPY ./apache-storm-1.0.8-SNAPSHOT /opt/apache-storm-1.0.8

构建镜像:

cd /root/storm
docker build -t storm:1.0 .

基于镜像storm:1.0生成一个交互容器执行命令,执行完即删除:
docker run --rm -it storm:1.0 /bin/bash

这时如果通过命令docker run -it -d storm:1.0运行容器,容器立马就退出了。
如何保证容器启动后不退出?这要求容器启动后有一个前台常驻进程不退出。

root@sure-PC:~/storm# cat Dockerfile 
FROM openjdk:16-slim-buster
COPY ./apache-storm-1.0.8-SNAPSHOT /opt/apache-storm-1.0.8
CMD ["/bin/sh"] #保证容器不退出

后台运行容器:docker run --name storm -it -d storm:1.0.8

root@sure-PC:~/storm# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
f96cdff86ea9        storm:1.0         "/bin/sh"           About a minute ago   Up About a minute                       storm

容器不再退出。

如何查看docker hub上镜像的dockerfile?以zookeeper为例:

https://hub.docker.com/_/zookeeper?tab=description

docker 集群部署 consul 内存大 docker容器集群_apache

1.2 需要制作的镜像

  1. storm镜像
  2. zookeeper镜像

storm的镜像中需要包含jdk和storm包。我没有直接使用docker-hub上的jdk镜像,因为本文主要目的在于学习。
zookeeper镜像需要包含jdk和storm。
系统镜像我使用centos,没有用alpine,因为我本地的jdk文件无法在其中运行。
这里有人基于alpine制作jdk容器。

由于我只需java运行时,因此只用jdk包中的jre目录即可。

1.2.1 Storm镜像

root@sure-PC:~/storm# cat Dockerfile 
FROM centos:centos7
COPY ./apache-storm-1.0.8-SNAPSHOT /opt/apache-storm-1.0.8
COPY ./jre /opt/jre
WORKDIR /opt/apache-storm-1.0.8
ENV JAVA_HOME=/opt/jre \
	STORM_HOME=/opt/apache-storm-1.0.8
ENV PATH=$PATH:$JAVA_HOME/bin:$STORM_HOME/bin
#需要使用ip命令查看ip路由,vim编辑文件, lsof查看连接
RUN yum -y install iproute vim lsof
CMD ["/bin/sh"]

docker build -t storm:1.1 .

通过这个Dockfile能做出一个storm的镜像,但只是启动一个该镜像的容器,storm还没运行起来。

那如何启动storm对应的角色(nimbus、supervisor和ui)呢?可以定义一个ROLE环境变量的值来判断启动那个角色。

添加启动脚本start-storm.sh,根据角色执行不同启动命令:

root@sure-PC:~/storm# cat start-storm.sh 
#!/bin/sh

role=${ROLE}

cd /opt
case "$role" in
  "nimbus")
    exec nohup storm nimbus
    ;;
  "supervisor")
    exec nohup storm supervisor
    ;;
  "ui")
    exec nohup storm ui
    ;;
  *)
    echo "unrecognized role: $role" >> nohup.log   
esac

注意:命令得前台运行,要不然容器就会退出。

这时storm镜像的Dockerfile:

root@sure-PC:~/storm# cat Dockerfile 
FROM centos:centos7
COPY ./apache-storm-1.0.8-SNAPSHOT /opt/apache-storm-1.0.8
COPY ./jre /opt/jre
COPY ./start-storm.sh /opt/start-storm.sh
WORKDIR /opt/apache-storm-1.0.8
ENV JAVA_HOME=/opt/jre \
	STORM_HOME=/opt/apache-storm-1.0.8
ENV PATH=$PATH:$JAVA_HOME/bin:$STORM_HOME/bin
RUN yum -y install iproute net-tools vim
ENTRYPOINT ["/opt/start-storm.sh"]

1.2.2 zookeeper镜像

参考了这个github小项目的方法:
https://github.com/cheyang/zookeeper_cluster_deployment/blob/master/docker_compose.md

2 多个容器的编排 - docker-compose

2.1 通过docker-compose为各服务容器指定ip

参数说明:
https://docs.docker.com/compose/https://docs.docker.com/compose/compose-file/

2.2 一个demo

root@sure-PC:~/storm# cat docker-compose.yml 
version: '2'
services:
   storm:
      image: storm:1.1
      container_name: storm
      restart: always #前台进程退出后就会重启容器
      tty: true
      networks:
         extnetwork: #使用指定的网络
            ipv4_address: 172.19.0.2 #指定ip
 
networks:
   extnetwork: #自定义网络
      ipam:
         config:
         - subnet: 172.19.0.0/16
           gateway: 172.19.0.1

启动定义的容器服务storm:
docker-compose up -d storm

启动整个服务:docker-compose up
若是要后台运行: docker-compose up -d
若不使用默认的docker-compose.yml 文件名:docker-compose -f server.yml up -d


2.3 storm配置

问题:storm和zookeeper的文件中需要配置ip,如何让这些容器获取彼此的ip信息呢?

在docker-compose中指定的container_name可以作为这个容器的域名。因此可以通过容器名来引用其他容器ip。

http://storm.apache.org/releases/current/Setting-up-a-Storm-cluster.html

storm.yml:

########### These MUST be filled in for a storm configuration
storm.zookeeper.servers:
  - "zk1" #zk容器域名
  - "zk2"
  - "zk3"
storm.local.dir: "/opt/data"

nimbus.host: "storm-nimbus" #storm-nimbus为nimbus容器域名
supervisor.slots.ports:
  - 6700
  - 6701
  - 6702
  - 6703

2.4 zookeeper配置

root@21afafecd75c:/opt# cat zookeeper/conf/zoo.cfg 
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper

镜像中有一个服务启动脚本run.sh。在docker-compose中定义了一些环境变量,容器运行时执行这个脚本会读取这些变量的值写入到zoo.cfg中。

root@21afafecd75c:/opt# cat run.sh 
#!/bin/sh

ZOO_CFG="/opt/zookeeper/conf/zoo.cfg"

# Output server ID
echo "server id (myid): ${SERVER_ID}"
echo "${SERVER_ID}" > /tmp/zookeeper/myid

# Add additional ZooKeeper servers into the zoo.cfg file
echo "${ADDITIONAL_ZOOKEEPER_1}" >> ${ZOO_CFG}
echo "${ADDITIONAL_ZOOKEEPER_2}" >> ${ZOO_CFG}
echo "${ADDITIONAL_ZOOKEEPER_3}" >> ${ZOO_CFG}
echo "${ADDITIONAL_ZOOKEEPER_4}" >> ${ZOO_CFG}
echo "${ADDITIONAL_ZOOKEEPER_5}" >> ${ZOO_CFG}
echo "${ADDITIONAL_ZOOKEEPER_6}" >> ${ZOO_CFG}
echo "${ADDITIONAL_ZOOKEEPER_7}" >> ${ZOO_CFG}
echo "${ADDITIONAL_ZOOKEEPER_8}" >> ${ZOO_CFG}
echo "${ADDITIONAL_ZOOKEEPER_9}" >> ${ZOO_CFG}
echo "${ADDITIONAL_ZOOKEEPER_10}" >> ${ZOO_CFG}

# Start Zookeeper
/opt/zookeeper/bin/zkServer.sh start-foreground

运行时配置为:

root@21afafecd75c:/opt# cat zookeeper/conf/zoo.cfg 
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper
server.1=zk1:2888:3889 #zk1为容器域名
server.2=zk2:2888:3889
server.3=zk3:2888:3889
clientPort=2181

3.5 最终的docker-compose.yml

root@sure-PC:~/storm# cat docker-compose.yml 
version: '3.6'
services:
  zk1:
    image: garland/zookeeper
    container_name: zk1
    volumes:
      - ./data/zk1:/tmp/zookeeper
    environment:
      - SERVER_ID=1
      - ADDITIONAL_ZOOKEEPER_4=clientPort=2181
      - ADDITIONAL_ZOOKEEPER_1=server.1=zk1:2888:3889
      - ADDITIONAL_ZOOKEEPER_2=server.2=zk2:2888:3889
      - ADDITIONAL_ZOOKEEPER_3=server.3=zk3:2888:3889
    networks:
      - extnetwork
  zk2:
    image: garland/zookeeper
    container_name: zk2
    volumes:
      - ./data/zk2:/tmp/zookeeper
    environment:
      - SERVER_ID=2
      - ADDITIONAL_ZOOKEEPER_4=clientPort=2181
      - ADDITIONAL_ZOOKEEPER_1=server.1=zk1:2888:3889
      - ADDITIONAL_ZOOKEEPER_2=server.2=zk2:2888:3889
      - ADDITIONAL_ZOOKEEPER_3=server.3=zk3:2888:3889
    networks:
      - extnetwork
  zk3:
    image: garland/zookeeper
    container_name: zk3
    volumes:
      - ./data/zk3:/tmp/zookeeper
    environment:
      - SERVER_ID=3
      - ADDITIONAL_ZOOKEEPER_4=clientPort=2181
      - ADDITIONAL_ZOOKEEPER_1=server.1=zk1:2888:3889
      - ADDITIONAL_ZOOKEEPER_2=server.2=zk2:2888:3889
      - ADDITIONAL_ZOOKEEPER_3=server.3=zk3:2888:3889
    networks:
      - extnetwork
  storm-nimbus:
    image: storm:1.1
    container_name: storm-nimbus
    restart: always
    environment:
      - ROLE=nimbus
    volumes:
      - ./data/nimbus:/opt/apache-storm-1.0.8/logs
    networks:
      - extnetwork
  storm-supervisor-1:
    image: storm:1.1
    container_name: storm-worker-1
    restart: always
    environment:
      - ROLE=supervisor
    volumes:
      - ./data/supervisor-1:/opt/apache-storm-1.0.8/logs
    networks:
      - extnetwork
  storm-supervisor-2:
    image: storm:1.1
    container_name: storm-worker-2
    restart: always
    environment:
      - ROLE=supervisor
    volumes:
      - ./data/supervisor-2:/opt/apache-storm-1.0.8/logs
    networks:
      - extnetwork
  storm-ui:
    image: storm:1.1
    container_name: storm-ui
    restart: always
    environment:
      - ROLE=ui 
    volumes:
      - ./data/ui:/opt/apache-storm-1.0.8/logs
    networks:
      - extnetwork

networks:
  extnetwork:
    ipam:
      config:
        - subnet: 172.19.0.0/16
          gateway: 172.19.0.1

最终的目录结构为:

root@sure-PC:~/storm# ll
drwxr-xr-x 12 root root 4.0K 11月 21 19:42 apache-storm-1.0.8-SNAPSHOT
drwxr-xr-x  9 root root 4.0K 11月 22 21:38 data //运行时生存,映射的storm和zk的日志目录
-rw-r--r--  1 root root 2.2K 11月 22 21:04 docker-compose.yml
-rw-r--r--  1 root root  349 11月 22 21:55 Dockerfile
drwxr-xr-x  5 root root 4.0K 11月 21 22:52 jre
-rwxr-xr-x  1 root root  253 11月 22 21:56 start-storm.sh

这个的docker-compose.yml定义了一个storm集群:
其中zk集群由3个容器节点组成,nimbus一个节点,用于处理任务的supervisor节点两个,ui节点一个。

在storm目录下,先执行docker build -t storm:1.1 .生成storm镜像,
然后执行命令docker-compose up即可运行这个storm集群。

docker 集群部署 consul 内存大 docker容器集群_docker_02

nimbus容器:

docker 集群部署 consul 内存大 docker容器集群_docker_03

supervisor容器:

docker 集群部署 consul 内存大 docker容器集群_docker_04

获取ui容器ip:

docker inspect storm-ui |grep Add

docker 集群部署 consul 内存大 docker容器集群_docker_05

浏览器访问:172.19.0.6:8080

docker 集群部署 consul 内存大 docker容器集群_zookeeper_06

至此,咱们通过docker-compose在单机上搭建storm集群完成。这个集群离生产还差得太多,
只作为学习容器的一个demo。这样,我们便能在本地对storm集群的行为进行更直接的分析和开发。