说在前面
相信大家在入职新公司或者自己换新电脑的时候都会遇到重新搭建开发环境这种情况,搭建的过程可以说是非常的坎坷,但是自从有了docker之后就变得非常的方便快捷了。此处分享一下docker搭建基础java开发环境的步骤以及方法。
此处使用的系统是CentOs7,不同的系统安装某些依赖的命令会有所不同。
安装
docker
- 安装必要的依赖项
yum install -y yum-utils device-mapper-persistent-data lvm2
- 添加Docker存储库
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
- 更新yum软件包索引
yum makecache fast
- 安装最新版本的Docker CE(社区版)
yum install docker-ce
- 启动Docker服务并将其设置为在系统启动时自动启动
systemctl start docker
systemctl enable docker
- 验证Docker是否正确安装
docker version
portainer
portainer是一个docker可视化工具,可以方便的管理容器和镜像,告别枯燥的命令行界面
- 拉取 Portainer 镜像
docker pull portainer/portainer
- 创建数据卷
docker volume create portainer_data
- 运行
docker run -d -p 9000:9000
--name portainer
--restart=always
-v /var/run/docker.sock:/var/run/docker.sock
-v portainer_data:/data portainer/portainer
参数说明:
- -d 参数表示在后台运行容器
- -p 9000:9000 参数表示将主机的 9000 端口映射到容器的 9000 端口
- --name portainer 参数表示将容器命名为 portainer
- --restart=always 参数表示在容器异常退出后,Docker 引擎会自动重启该容器
- -v /var/run/docker.sock:/var/run/docker.sock 参数表示将主机的 Docker 引擎 Unix 套接字文件映射到容器内,使得 Portainer 可以通过该套接字与 Docker 引擎进行通信
- -v portainer_data:/data 参数表示将名为 portainer_data 的数据卷挂载到容器的 /data 目录,以便将 Portainer 的数据持久化到该数据卷上
- portainer/portainer 参数表示使用 Portainer 镜像来启动容器。
启动成功后访问 你的IP:9000,创建用户后登陆便可看到以下界面
MySQL
- 拉取镜像
docker pull mysql:latest
- 创建挂载卷
mkdir -p /opt/mysql/data
- 运行
docker run -d --name mysql-server
--restart=always
-e MYSQL_ROOT_PASSWORD=123456
-e MYSQL_USER=user007
-e MYSQL_PASSWORD=123456
-v /opt/mysql/data:/var/lib/mysql
-p 3306:3306
-d mysql:latest
-e 配置mysql的环境信息,此处配置了root的密码以及创建了一个用户并且指定此用户的登陆密码
完成后可以在Portainer看到MySQL正在运行
redis
- 拉取镜像
docker pull redis
- 运行容器
docker run -d --name redis
--restart=always
-p 6379:6379
-v redis_data:/data redis
--appendonly yes
完成后可以在Portainer看redis正在运行
rabbitMq
- 拉取镜像
docker pull rabbitmq:management
- 运行容器
docker run -d --name rabbitmq
--restart=always
-p 5672:5672
-p 15672:15672
-v rabbitmq_data:/var/lib/rabbitmq
--hostname rabbitmq
-e RABBITMQ_DEFAULT_USER=admin
-e RABBITMQ_DEFAULT_PASS=123456
rabbitmq:management
完成后可以在Portainer看到rabbitMq正在运行
访问 你的ip:15672 登陆
使用以上的密码登陆
elasticsearch
- 拉取镜像
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.13.3
- 运行容器
docker run -d --name elasticsearch
--restart=always
-p 9200:9200
-p 9300:9300
-e "discovery.type=single-node"
-v es_data:/usr/share/elasticsearch/data
docker.elastic.co/elasticsearch/elasticsearch:7.13.3
-e 以单体模式启动
访问 你的ip:9200看到以下json串表示已经成功启动es
zipkin
mkdir zipkin-data
docker run -d -p 9411:9411
-v ./zipkin-data:/zipkin
--name zipkin openzipkin/zipkin
访问你的ip:9411,看到以下页面则表示安装成功
docker-dompose
sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
还有一种用pip安装的方法,但是比较麻烦会有python版本问题,感兴趣的可以自行去了解。
Kafka
version: "3"
services:
kafka1:
image: 'bitnami/kafka:3.3.1'
network_mode: mynetwork
container_name: kafka1
user: root
ports:
- 9192:9092
- 9193:9093
environment:
### 通用配置
- KAFKA_CFG_MAX_PARTITION_FETCH_BYTES=1495725856
- KAFKA_CFG_MAX_REQUEST_SIZE=1495725856
- KAFKA_CFG_SOCKET_REQUEST_MAX_BYTES=1495725856
# 允许使用kraft,即Kafka替代Zookeeper
- KAFKA_ENABLE_KRAFT=yes
# kafka角色,做broker,也要做controller
- KAFKA_CFG_PROCESS_ROLES=broker,controller
# 指定供外部使用的控制类请求信息
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
# 定义kafka服务端socket监听端口
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
# 定义安全协议
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
# 集群地址
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
# 允许使用PLAINTEXT监听器,默认false,不建议在生产环境使用
- ALLOW_PLAINTEXT_LISTENER=yes
# 设置broker最大内存,和初始内存
- KAFKA_HEAP_OPTS=-Xmx512M -Xms256M
# 不允许自动创建主题
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=false
# 使用Kafka时的集群id,集群内的Kafka都要用这个id做初始化,生成一个UUID即可
- KAFKA_KRAFT_CLUSTER_ID=LelM2dIFQkiUFvXCEcqRWA
### broker配置
# 定义外网访问地址(宿主机ip地址和端口)
# - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.0.109:9192
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://10.31.98.18:9192
# - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://chera.top:17005
# broker.id,必须唯一
- KAFKA_BROKER_ID=1
volumes:
- /home/mycontainers/kafka1/kafka/kraft:/bitnami/kafka
# extra_hosts:
# - "kafka1:192.168.0.109"
# - "kafka2:192.168.0.109"
# - "kafka3:192.168.0.109"
kafka2:
image: 'bitnami/kafka:3.3.1'
network_mode: mynetwork
container_name: kafka2
user: root
ports:
- 9292:9092
- 9293:9093
environment:
- KAFKA_CFG_MAX_PARTITION_FETCH_BYTES=1495725856
- KAFKA_CFG_MAX_REQUEST_SIZE=1495725856
- KAFKA_CFG_SOCKET_REQUEST_MAX_BYTES=1495725856
### 通用配置
# 允许使用kraft,即Kafka替代Zookeeper
- KAFKA_ENABLE_KRAFT=yes
# kafka角色,做broker,也要做controller
- KAFKA_CFG_PROCESS_ROLES=broker,controller
# 指定供外部使用的控制类请求信息
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
# 定义kafka服务端socket监听端口
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
# 定义安全协议
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
# 集群地址
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
# 允许使用PLAINTEXT监听器,默认false,不建议在生产环境使用
- ALLOW_PLAINTEXT_LISTENER=yes
# 设置broker最大内存,和初始内存
- KAFKA_HEAP_OPTS=-Xmx512M -Xms256M
# 不允许自动创建主题
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=false
# 使用Kafka时的集群id,集群内的Kafka都要用这个id做初始化,生成一个UUID即可
- KAFKA_KRAFT_CLUSTER_ID=LelM2dIFQkiUFvXCEcqRWA
### broker配置
# 定义外网访问地址(宿主机ip地址和端口)
# - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.0.109:9292
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://10.31.98.18:9292
# - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://chera.top:17005
# broker.id,必须唯一
- KAFKA_BROKER_ID=2
volumes:
- /home/mycontainers/kafka2/kafka/kraft:/bitnami/kafka
# extra_hosts:
# - "kafka1:192.168.0.109"
# - "kafka2:192.168.0.109"
# - "kafka3:192.168.0.109"
kafka3:
image: 'bitnami/kafka:3.3.1'
network_mode: mynetwork
container_name: kafka3
user: root
ports:
- 9392:9092
- 9393:9093
environment:
- KAFKA_CFG_MAX_PARTITION_FETCH_BYTES=1495725856
- KAFKA_CFG_MAX_REQUEST_SIZE=1495725856
- KAFKA_CFG_SOCKET_REQUEST_MAX_BYTES=1495725856
### 通用配置
# 允许使用kraft,即Kafka替代Zookeeper
- KAFKA_ENABLE_KRAFT=yes
# kafka角色,做broker,也要做controller
- KAFKA_CFG_PROCESS_ROLES=broker,controller
# 指定供外部使用的控制类请求信息
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
# 定义kafka服务端socket监听端口
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
# 定义安全协议
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
# 集群地址
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
# 允许使用PLAINTEXT监听器,默认false,不建议在生产环境使用
- ALLOW_PLAINTEXT_LISTENER=yes
# 设置broker最大内存,和初始内存
- KAFKA_HEAP_OPTS=-Xmx512M -Xms256M
# 不允许自动创建主题
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=false
# 使用Kafka时的集群id,集群内的Kafka都要用这个id做初始化,生成一个UUID即可
- KAFKA_KRAFT_CLUSTER_ID=LelM2dIFQkiUFvXCEcqRWA
### broker配置
# 定义外网访问地址(宿主机ip地址和端口)
# - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.0.109:9392
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://10.31.98.18:9392
# - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://chera.top:17005
# broker.id,必须唯一
- KAFKA_BROKER_ID=3
volumes:
- /home/mycontainers/kafka3/kafka/kraft:/bitnami/kafka
# extra_hosts:
# - "kafka1:192.168.0.109"
# - "kafka2:192.168.0.109"
# - "kafka3:192.168.0.109"
配置注释都写在上面的yml,一目了然。
然后在服务器运行
docker-compose -f 你的yml名字.yml up
看到started Kafka相关字段即表示成功启动。
portainer控制面板如下
Kafka-ui
version: "3"
services:
kafkaui:
image: provectuslabs/kafka-ui:latest
network_mode: mynetwork
container_name: kafkaui
restart: always
ports:
- 7777:8080
volumes:
- /etc/localtime:/etc/localtime
environment:
- KAFKA_CLUSTERS_0_NAME=chera
- KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka1:9092,kafka2:9092,kafka3:9092
这里映射了7777宿主机端口到docker的8080端口 访问7777端口如下图
我们到portainer看看
sentinel
version: '3'
services:
sentinel:
image: bladex/sentinel-dashboard
container_name: sentinel
network_mode: mynetwork
ports:
- 18858:8858
restart: always
environment:
- DSENTINEL_NACOS_SERVER_ADDR=nacos
- DSENTINEL_NACOS_NAMESPACE=4ca9d0cb-a399-4009-ad4b-c00c5f381fe2
- DSENTINEL_NACOS_USERNAME=nacos
- DSENTINEL_NACOS_PASSWORD=nacos
可视化页面
访问一下组件页面
url根据你的配置文件来进行修改
默认密码是sentinel/sentinel,由于是内网,所以无所谓,请在公网上部署的时候一定要修改账号密码!!
访问url http://虚拟机ip:9411
nacos
version: "3"
services:
nacos:
image: nacos/nacos-server:v2.2.0
network_mode: mynetwork
container_name: nacos
restart: always
ports:
- 8848:8848
volumes:
- /etc/localtime:/etc/localtime
- /home/mycontainers/nacos/data:/data
environment:
- SPRING_DATASOURCE_PLATFORM=mysql
#此处配置工具你当前容器所处的网络进行如其名查找,位于同一网络的话会去查找mysql这个容器进行链接
- MYSQL_SERVICE_HOST=mysql
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_DB_NAME=nacos_config
- MYSQL_SERVICE_USER=你的mysql用户名
- MYSQL_SERVICE_PASSWORD=你的密码
- NACOS_DEBUG=n
访问url http://虚拟机ip:8848/nacos/
默认账号密码都是nacos,进入系统即可
kibana
version: '3'
services:
elasticsearch:
image: elasticsearch:7.14.2 #镜像
container_name: elasticsearch #定义容器名称
restart: always #开机启动,失败也会一直重启
environment:
- "cluster.name=elasticsearch" #设置集群名称为elasticsearch
- "discovery.type=single-node" #以单一节点模式启动
- "ES_JAVA_OPTS=-Xms512m -Xmx1024m" #设置使用jvm内存大小
volumes:
- ./plugins:/usr/share/elasticsearch/plugins #插件文件挂载
- es_data:/usr/share/elasticsearch/data #数据文件挂载
- docker.elastic.co/elasticsearch/elasticsearch:7.14.2 #数据文件挂载
ports:
- 9200:9200
kibana:
image: kibana:7.14.2
container_name: kibana
restart: always
volumes:
- ./kibana.yml:/usr/share/kibana/config/kibana.yml
ports:
- 5601:5601
privileged: true #环境变量
kibana.yml
server.name: kibana
# kibana的主机地址 0.0.0.0可表示监听所有IP
server.host: "0.0.0.0"
#
# 这边设置自己es的地址,
elasticsearch.hosts: http://elasticsearch:9200
elasticsearch.username: 'kibana'
elasticsearch.password: '123456'
# # 显示登陆页面
xpack.monitoring.ui.container.elasticsearch.enabled: true
# 开启中文模式
i18n.locale: "zh-CN"
把以上文件放入服务器,如何在kibana.yml的文件夹执行 docker-compose 启动命令,控制台没报错即可!
此处更换了elasticsearch版本,强烈建议elasticsearch和kibana版本互相对应,否则可能出现各种奇奇怪怪的问题。
可视化界面查看运行状态或者使用docker ps命令查看
elasticsearch-analysis-ik
安装ik分词器
#进入es容器
docker exec -it es容器名或id /bin/bash
#切换到plugin目录
#elasticsearch-plugin install 对应版本ik分词器的zip地址
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.14.2/elasticsearch-analysis-ik-7.14.2.zip
等待完成,如何按y确认,重启docker容器即可
至此,我们所需的服务已经全部启动完成。
完整脚本
#安装必要的依赖项,包括使用yum-config-manager工具管理存储库的能力:
yum install -y yum-utils device-mapper-persistent-data lvm2
#添加Docker存储库:
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
#更新yum软件包索引:
yum makecache fast
#安装最新版本的Docker CE(社区版):
yum install docker-ce
# 启动Docker服务并将其设置为在系统启动时自动启动:
systemctl start docker
systemctl enable docker
#验证Docker是否正确安装:
docker version
#安装portainer
#拉取 Portainer 镜像:
docker pull portainer/portainer
#创建一个名为 portainer 的数据卷,以便将 Portainer 的数据持久化到磁盘上:
docker volume create portainer_data
#运行 Portainer 容器:
docker run -d -p 9000:9000 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
#其中:
#-d 参数表示在后台运行容器;
#-p 9000:9000 参数表示将主机的 9000 端口映射到容器的 9000 端口;
#--name portainer 参数表示将容器命名为 portainer;
#--restart=always 参数表示在容器异常退出后,Docker 引擎会自动重启该容器;
#-v /var/run/docker.sock:/var/run/docker.sock 参数表示将主机的 Docker 引擎 Unix 套接字文件映射到容器内,使得 Portainer 可以通过该套接字与 Docker 引擎进行通信;
#-v portainer_data:/data 参数表示将名为 portainer_data 的数据卷挂载到容器的 /data 目录,以便将 Portainer 的数据持久化到该数据卷上;
#portainer/portainer 参数表示使用 Portainer 镜像来启动容器。
docker pull mysql:latest
#创建一个 MySQL 数据存储目录:
mkdir -p /opt/mysql/data
#运行 MySQL 容器:
docker run -d --name mysql-server --restart=always -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_USER=cjy -e MYSQL_PASSWORD=123456 -v /opt/mysql/data:/var/lib/mysql -p 3306:3306 -d mysql:latest
#拉取 RabbitMQ 镜像:
docker pull rabbitmq:management
#这里我们选择了带有 RabbitMQ 管理插件的镜像,以便您可以使用 Web 界面来管理 RabbitMQ。
#运行 RabbitMQ 容器:
docker run -d --name rabbitmq --restart=always -p 5672:5672 -p 15672:15672 -v rabbitmq_data:/var/lib/rabbitmq --hostname rabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=123456 rabbitmq:management
#其中:
#-d 参数表示在后台运行容器;
#--name rabbitmq 参数表示将容器命名为 rabbitmq;
#-p 5672:5672 参数表示将主机的 5672 端口映射到容器的 5672 端口,以便客户端可以通过 AMQP 协议连接 RabbitMQ 服务器;
#-p 15672:15672 参数表示将主机的 15672 端口映射到容器的 15672 端口,以便您可以使用 Web 界面来管理 RabbitMQ;
#-v rabbitmq_data:/var/lib/rabbitmq 参数表示将名为 rabbitmq_data 的数据卷挂载到容器的 /var/lib/rabbitmq 目录,以便将 RabbitMQ 的数据持久化到该数据卷上;
#--hostname rabbitmq 参数表示将容器的主机名设置为 rabbitmq;
#-e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=password 参数表示设置 RabbitMQ 的默认用户名和密码;
#rabbitmq:management 参数表示使用 RabbitMQ 镜像来启动容器,并启用 RabbitMQ 管理插件。
#拉取 Redis 镜像:
docker pull redis
#运行 Redis 容器:
docker run -d --name redis --restart=always -p 6379:6379 -v redis_data:/data redis --appendonly yes
#其中:
#-d 参数表示在后台运行容器;
#--name redis 参数表示将容器命名为 redis;
#-p 6379:6379 参数表示将主机的 6379 端口映射到容器的 6379 端口,以便客户端可以通过 Redis 协议连接 Redis 服务器;
#-v 将redis_data挂载到容器里的/data
#--appendonly 表示开启aof持久化
#redis 参数表示使用 Redis 镜像来启动容器。
#拉取 ES 镜像:
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.13.3
#这里我们使用的是官方的 Elasticsearch 7.13.3 镜像,您可以根据自己的需要选择其他版本。
#运行 ES 容器:
docker run -d --name elasticsearch --restart=always -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -v es_data:/usr/share/elasticsearch/data docker.elastic.co/elasticsearch/elasticsearch:7.13.3
#其中:
#-d 参数表示在后台运行容器;
#--name elasticsearch 参数表示将容器命名为 elasticsearch;
#-p 9200:9200 -p 9300:9300 参数表示将主机的 9200 和 9300 端口映射到容器的 9200 和 9300 端口,以便客户端可以通过 HTTP 和 TCP 协议连接 Elasticsearch;
#-e "discovery.type=single-node" 参数表示将 Elasticsearch 配置为单节点模式;
#docker.elastic.co/elasticsearch/elasticsearch:7.13.3 参数表示使用 Elasticsearch 7.13.3 镜像来启动容器。
#现在您已经成功在 Docker 中安装了 Elasticsearch,并可以通过访问 http://服务器IP:9200 来测试 Elasticsearch 是否运行正常。如果您需要在生产环境中使用 Elasticsearch,请参考 Elasticsearch 官方文档中的安全配置和性能优化等相关信息。
#安装docker-compose
sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
docker-compose启动的容器是用yml启动的,yml在上面都已经贴出。
踩坑以及烦恼
- docker-compose
在拉取github的时候可能因为各种原因导致无法拉取,这时候可以去镜像加速网站或者开魔法进行拉取。
- Kafka 因为不想用zookeeper作为管理工具,使用了kraft,但是很多坑,笔者会在解决后进行更新 以下这个问题困扰了我很久
WARN [SocketServer listenerType=BROKER, nodeId=1] Unexpected error from /10.31.98.143 (channelId=172.20.0.2:9092-10.31.98.143:50943-1); closing connection (org.apache.kafka.common.network.Selector) org.apache.kafka.common.network.InvalidReceiveException: Invalid receive (size = 1195725856 larger than 104857600)
一番寻找资料之后得知是因为请求过大,Kafka默认最大是1m
但是我修改过server.properties文件后重启也是1m,很困惑。
由于看到Kafka容器是在运行的,我想试试看能不能使用,如何就写了代码链接,发现是可以使用的。我创建了一个名为test的topic并且使用springboot进行测试。
核心代码
@KafkaListener(topics = "test", groupId = "cc")
@KafkaListener(topicPartitions = {
@TopicPartition(topic = "test", partitions = {"0"})
})
public void process(String msg) {
System.out.println("msg = " + msg);
}
@GetMapping("/send")
public String send() throws InterruptedException, ExecutionException, TimeoutException {
kafkaTemplate.send("test", 0, "", "hello");
return "ok";
}
@PostConstruct
private void listener() {
kafkaTemplate.setProducerListener(new ProducerListener<String, String>() {
@Override
public void onSuccess(ProducerRecord producerRecord, RecordMetadata recordMetadata) {
System.out.println("生产者发送消息后监听到数据: " + producerRecord.value());
}
@Override
public void onError(ProducerRecord producerRecord, Exception exception) {
System.out.println("生产者发送消息后监听数据失败: " + producerRecord.value());
}
});
}
然后看到控制台输出如下
大家如果有什么建议和意见请在评论区指出,还有如果大家对这个Kafka错误有什么经验的话可以告诉笔者,谢谢大家~