1. 程式人生 > >Docker 也是本地開發的一神器:部署單機版 Pulsar 和叢集架構 Redis

Docker 也是本地開發的一神器:部署單機版 Pulsar 和叢集架構 Redis

# 原文連結:[Docker 也是本地開發的一神器:部署單機版 Pulsar 和叢集架構 Redis](https://blog.csdn.net/Howinfun/article/details/109240374) # 一、前言: 現在網際網路的技術架構中,不斷出現各種各樣的中介軟體,例如 MQ、Redis、Zookeeper,這些中介軟體在部署的時候一般都是以主從架構或者叢集的架構來部署,公司一般都會在開發環境、測試環境和生產環境各部署一套。 當我們開發的時候,一般就會連著開發環境。但是呢,一般公司的開發環境都只能在內網使用,當我們回家了,除非公司提供有 VPN,不然就沒辦法使用了。有時候我們是有VPN了,但是開發起來還是很不方便。例如我們現在的 MQ 中介軟體使用的是 Pulsar,但是 Pulsar 的 tenant 和 namespace 都是不能自動建立的,所以平時開發起來非常的不方便,只能每次需要時都找一遍 DBA。 所以,一般我們都會在本地自己部署一套,但是自己部署有下面的兩個難點: 1. 中介軟體有自己的實現語言,例如 RabbitMQ,當我們部署 RabbitMQ 時,首先要安裝好 Erlang 語言。 2. 部署叢集架構會耗費大量的系統資源,導致本來資源就吃緊的筆記本更加卡頓,開發起來非常的不爽。 # 二、Docker: Docker 可以完美地解決上面的問題,並且讓部署變得極其的簡單。下面以我自己用到的中介軟體為例子。 ## A、Pulsar: 上面提到,Pulsar 的租戶是不能自動建立的,名稱空間也是不能自動建立的,如果我們要使用,只能找到負責這塊的同事幫忙建立了。而我最近做的功能:廣播中心和會員匯出都使用到 Pulsar,但是不想麻煩同事,而且我經常會在家裡幹活,所以 最後直接到官網上面,找了[本地如何部署](http://pulsar.apache.org/docs/en/standalone-docker/)。 官網介紹了多種部署方式:有利用壓縮包的,Docker的,Kubernetes的。當然了,有 Docker 的部署方式,我們必須使用 Docker 的部署方式,反正拉取一個映象啟動一個容器就直接搞定了,相當的方便。 下面上命令: ```shell docker run -it -d -p 6650:6650 -p 8080:8080 -v data -v conf --name=mypulsar apachepulsar/pulsar:2.6.1 bin/pulsar standalone ``` 命令是非常的簡單:將 pulsar 的 6650和8080埠號開放出來,並繫結到宿主機對應的埠號,這樣我們能直接訪問宿主機 ip:port 就能訪問到容器。接著,將 Pulsar 的 data 和 conf 掛載到宿主機中,這樣資料就不會丟失了。接著利用 pulsar standalone 命令啟動一個單機版的 Pulsar。 接著,不管我們是需要建立租戶或者名稱空間,直接進入容器中建立即可。 進入容器: ```shell docker exec -it mypulsar /bin/bash ``` 關於tenant 和 namespace 的增刪改查命令: ```shell ## 1 租戶 #檢視有哪些租戶(public 是系統預設的租戶) pulsar-admin tenants list ##建立租戶 pulsar-admin tenants create my-tenant #刪除租戶 pulsar-admin tenants delete my-tenant ## 2 名稱空間 #檢視指定租戶下邊的名稱空間 pulsar-admin namespaces list my-tenant #建立指定租戶名稱空間 pulsar-admin namespaces create my-tenant/my-namespace #刪除指定租戶名稱空間 pulsar-admin namespaces delete my-tenant/my-namespace ``` ## B、Redis: Redis 一般我們生產的架構都是使用 Cluster 的,但是如果是自己部署一套叢集的 Redis,是相當的麻煩,以前我自己也寫過文章:[Linux 部署 Redis 叢集](https://blog.csdn.net/Howinfun/article/details/81873434) 如果使用 Docker 的話,會非常的簡單。 ### 1 自定義網路 #### 1.1 建立 Redis 的專屬網路 Redis 叢集的各個節點公用一個專屬網路,節點間就可以互相訪問了,而避免了每個節點之間都要用 --link 去做網路互通。 > docker network create 命令建立的網路預設是 bridge 模式。 ```shell winfun@localhost ~ % docker network create redis-net --subnet 172.26.0.0/16 5001355940f43474d59f5cb2d78e4e9eeb0a9827e53d8f9e5b55e7d3c5285a09 winfun@localhost ~ % docker network list NETWORK ID NAME DRIVER SCOPE 4d88d473e947 bridge bridge local 79a915fafbb5 host host local f56e362d3c68 none null local 5001355940f4 redis-net bridge local winfun@localhost ~ % ``` #### 1.2 檢視自定義網路詳情 我們可以利用命令 docker network inspect redis-net 來檢視自定義網路的詳情,可以看到現在網路裡面是沒有容器的。 ```shell winfun@localhost mydata % docker network inspect redis-net [ { "Name": "redis-net", "Id": "aed8340bbf8ab86cedc1d990eb7612854ba2b0bd4eae0f978ff95eadc3dbcf65", "Created": "2020-10-22T08:46:55.695434Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.26.0.0/16" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ] ``` ### 2 開始部署 #### 2.1 建立六個Redis節點的配置 ```shell for port in $(seq 1 6); \ do \ mkdir -p /Users/winfun/mydata/redis/node-${port}/conf touch /Users/winfun/mydata/redis/node-${port}/conf/redis.conf cat << EOF >/Users/winfun/mydata/redis/node-${port}/conf/redis.conf port 6379 bind 0.0.0.0 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-announce-ip 172.26.0.1${port} cluster-announce-port 6379 cluster-announce-bus-port 16379 appendonly yes EOF done ``` #### 2.2 啟動容器 ```shell for port in $(seq 1 6); \ do \ docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \ -v /Users/winfun/mydata/redis/node-${port}/data:/data \ -v /Users/winfun/mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \ -d --net redis-net --ip 172.26.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf done ``` #### 2.3 檢視啟動成功的6個容器 ```shell winfun@localhost mydata % docker ps | grep redis ed5972e988e8 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 11 seconds ago Up 10 seconds 0.0.0.0:6376->6379/tcp, 0.0.0.0:16376->16379/tcp redis-6 61cd467bc803 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 12 seconds ago Up 11 seconds 0.0.0.0:6375->6379/tcp, 0.0.0.0:16375->16379/tcp redis-5 113943ba6586 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 12 seconds ago Up 11 seconds 0.0.0.0:6374->6379/tcp, 0.0.0.0:16374->16379/tcp redis-4 5fc3c838851c redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 13 seconds ago Up 12 seconds 0.0.0.0:6373->6379/tcp, 0.0.0.0:16373->16379/tcp redis-3 f7d4430f752b redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 13 seconds ago Up 12 seconds 0.0.0.0:6372->6379/tcp, 0.0.0.0:16372->16379/tcp redis-2 bd3e4a593427 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 14 seconds ago Up 13 seconds 0.0.0.0:6371->6379/tcp, 0.0.0.0:16371->16379/tcp redis-1 ``` ## 3 再檢視網路 ### 3.1 檢視網路中的容器 我們上面啟動容器時,都指定使用 redis-net 網路,所以我們可以先看看 redis-net 網路的資訊: 我們可以看到 “Containers”包含了我們啟動的6個容器,也就是6個redis 節點。 ```shell winfun@localhost mydata % docker network inspect redis-net [ { "Name": "redis-net", "Id": "aed8340bbf8ab86cedc1d990eb7612854ba2b0bd4eae0f978ff95eadc3dbcf65", "Created": "2020-10-22T08:46:55.695434Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.26.0.0/16" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "113943ba6586a4ac21d1c068b0535d5b4ef37da50141d648d30dab47eb47d3af": { "Name": "redis-4", "EndpointID": "3fe3b4655f39f90ee4daf384254d3f7548cddd19c384e0a26edb6a32545e5b30", "MacAddress": "02:42:ac:1a:00:0e", "IPv4Address": "172.26.0.14/16", "IPv6Address": "" }, "5fc3c838851c0ca2f629457bc3551135567b4e9fb155943711e07a91ebe9827f": { "Name": "redis-3", "EndpointID": "edd826ca267714bea6bfddd8c5d6a5f3c71c50bd50381751ec40e9f8e8160dce", "MacAddress": "02:42:ac:1a:00:0d", "IPv4Address": "172.26.0.13/16", "IPv6Address": "" }, "61cd467bc8030c4db9a4404b718c5c927869bed71609bec91e17ff0da705ae26": { "Name": "redis-5", "EndpointID": "7612c44ab2479ab62341eba2e30ab26f4c523ccbe1aa357fc8b7c17a368dba61", "MacAddress": "02:42:ac:1a:00:0f", "IPv4Address": "172.26.0.15/16", "IPv6Address": "" }, "bd3e4a593427aab4750358330014422500755552c8b470f0fd7c1e88221db984": { "Name": "redis-1", "EndpointID": "400153b712859c5c17d99708586f30013bb28236ba0dead516cf3d01ea071909", "MacAddress": "02:42:ac:1a:00:0b", "IPv4Address": "172.26.0.11/16", "IPv6Address": "" }, "ed5972e988e8301179249f6f9e82c8f9bb4ed801213fe49af9d3f31cbbe00db7": { "Name": "redis-6", "EndpointID": "b525b7bbdd0b0150f66b87d55e0a8f1208e113e7d1d421d1a0cca73dbb0c1e47", "MacAddress": "02:42:ac:1a:00:10", "IPv4Address": "172.26.0.16/16", "IPv6Address": "" }, "f7d4430f752b5485c5a90f0dc6d1d9a826d782284b1badbd203c12353191bc57": { "Name": "redis-2", "EndpointID": "cbdc77cecda1c8d80f566bcc3113f37c1a7983190dbd7ac2e9a56f6b7e4fb21f", "MacAddress": "02:42:ac:1a:00:0c", "IPv4Address": "172.26.0.12/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ] ``` ### 3.2 檢視容器間是否能網路互通 我們還可以嘗試利用 redis-1 來對 redis-2 執行 ping 命令,看看網路是否可以互通: ```shell winfun@localhost mydata % docker exec -it redis-1 ping redis-2 PING redis-2 (172.26.0.12): 56 data bytes 64 bytes from 172.26.0.12: seq=0 ttl=64 time=0.136 ms 64 bytes from 172.26.0.12: seq=1 ttl=64 time=0.190 ms 64 bytes from 172.26.0.12: seq=2 ttl=64 time=0.483 ms ^C --- redis-2 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 0.136/0.269/0.483 ms ``` ## 4 建立叢集 ### 4.1 利用 redis-cli 命令建立叢集: ```shell winfun@localhost conf % docker exec -it redis-1 /bin/bash OCI runtime exec failed: exec failed: container_linux.go:349: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown # 只能使用sh,redis 的映象沒有 bash winfun@localhost mydata % docker exec -it redis-1 /bin/sh /data # cd /usr/local/bin/ /usr/local/bin # redis-cli --cluster create 172.26.0.11:6379 172.26.0.12:6379 17 2.26.0.13:6379 172.26.0.14:6379 172.26.0.15:6379 172.26.0.16:6379 --cluster-repl icas 1 >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 172.26.0.15:6379 to 172.26.0.11:6379 Adding replica 172.26.0.16:6379 to 172.26.0.12:6379 Adding replica 172.26.0.14:6379 to 172.26.0.13:6379 M: 6de9e9eef91dbae773d8ee1d629c87e1e7e19b82 172.26.0.11:6379 slots:[0-5460] (5461 slots) master M: 43e173849bed74f5bd389f9b272ecf0399ae448f 172.26.0.12:6379 slots:[5461-10922] (5462 slots) master M: 1e504dc62b7ccc426d513983ca061d1657532fb6 172.26.0.13:6379 slots:[10923-16383] (5461 slots) master S: 92b95f18226903349fb860262d2fe6932d5a8dc2 172.26.0.14:6379 replicates 1e504dc62b7ccc426d513983ca061d1657532fb6 S: 7e5116ba9ee7bb70a68f4277efcbbbb3dcfd18af 172.26.0.15:6379 replicates 6de9e9eef91dbae773d8ee1d629c87e1e7e19b82 S: 203e3e33b9f4233b58028289d0ad2dd56e7dfe45 172.26.0.16:6379 replicates 43e173849bed74f5bd389f9b272ecf0399ae448f Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join ... >>> Performing Cluster Check (using node 172.26.0.11:6379) M: 6de9e9eef91dbae773d8ee1d629c87e1e7e19b82 172.26.0.11:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: 92b95f18226903349fb860262d2fe6932d5a8dc2 172.26.0.14:6379 slots: (0 slots) slave replicates 1e504dc62b7ccc426d513983ca061d1657532fb6 S: 203e3e33b9f4233b58028289d0ad2dd56e7dfe45 172.26.0.16:6379 slots: (0 slots) slave replicates 43e173849bed74f5bd389f9b272ecf0399ae448f M: 1e504dc62b7ccc426d513983ca061d1657532fb6 172.26.0.13:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 7e5116ba9ee7bb70a68f4277efcbbbb3dcfd18af 172.26.0.15:6379 slots: (0 slots) slave replicates 6de9e9eef91dbae773d8ee1d629c87e1e7e19b82 M: 43e173849bed74f5bd389f9b272ecf0399ae448f 172.26.0.12:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. ``` ### 4.2 利用 redis-cli 連線當前節點,檢視叢集資訊: ```shell /usr/local/bin # redis-cli -c 127.0.0.1:6379> cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:91 cluster_stats_messages_pong_sent:95 cluster_stats_messages_sent:186 cluster_stats_messages_ping_received:90 cluster_stats_messages_pong_received:91 cluster_stats_messages_meet_received:5 cluster_stats_messages_received:186 ``` ### 4.3 嘗試增加一個key ```shell # 設定一個key,返回提示這個key分配到槽[12539],對應的是節點 redis-3[192.168.0.13] 127.0.0.1:6379> set key hello -> Redirected to slot [12539] located at 172.26.0.13:6379 OK # 並且會將 redis-cli 切換到節點 redis-3[172.26.0.13] 172.26.0.13:6379> ``` ## 5 測試 至此,應該可以說,我們已經成功利用 Docker 在本地部署了一套 Redis 叢集。 那麼接下來,我們會直接在程式碼中測試這Redis 是否可以使用。 ```java /** * 測試Redis叢集 * @author winfun * @date 2020/10/21 5:48 下午 **/ public class TestCluster { public static void main(String[] args) throws Exception{ Set nodes = new HashSet<>(3); nodes.add(new HostAndPort("127.0.0.1",6371)); nodes.add(new HostAndPort("127.0.0.1",6372)); nodes.add(new HostAndPort("127.0.0.1",6373)); JedisCluster cluster = new JedisCluster(nodes); String value = cluster.get("key"); System.out.println("get: key is key,value is "+value); String result = cluster.set("key2","hello world"); System.out.println("set: key is key2,result is "+result); cluster.close(); } } ``` 但是結果是不如意的,返回的是一個異常: ![訪問叢集異常](https://img-blog.csdnimg.cn/20201023125339128.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0hvd2luZnVu,size_16,color_FFFFFF,t_70#pic_center) 從這裡可以猜測到,估計是沒法連線到我們在 Docker 中部署的 Redis 叢集。 所以在下次除錯的時候,我就看看 JedisCluster 拿到的叢集節點的資訊是怎麼樣的。 如下圖:![Redis 叢集節點資訊](https://img-blog.csdnimg.cn/20201023125408374.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0hvd2luZnVu,size_16,color_FFFFFF,t_70#pic_center) 我們可以看到,即使我們給 JedisCluster 配置的寫的是本地 IP 和對映好的 Port。 但是沒想到,JedisCluster 自己又拿裡一遍叢集的元資料,此時候的節點的IP都是自定義網路 redis-net 分配的子網了,宿主機可能就走不通了(關於這個問題,我們可以考慮使用 host 型別的自定義網路)。 ## 6 應用也部署到自定義網路中 那麼怎麼測試呢? 我下面將自己編寫一個簡單的 SpringBoot 專案,然後利用 Dockerfile 根據專案生成的 jar 包構建成一個映象,然後利用 Docker 部署起來,並且將部署後的容器加入到自定義網路 redis-net 中,最後進行測試。 ### 6.1 建立 SpringBoot 專案 配置如下: #### 6.1.1 pom.xml: 主要引入了 web 和 redis 的 starter。 ```xml org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot spring-boot-starter-web ``` #### 6.1.2 專案的 application.properties : ```properties server.port=8080 # 這裡我們也可以直接寫容器名,因為應用會部署到 Redis 叢集的同一個網路中。 #spring.redis.cluster.nodes=redis-1:6379,redis-2:6379,redis-3:6379 spring.redis.cluster.nodes=172.26.0.11:6379,172.26.0.12:6379,172.26.0.13:6379 ``` #### 6.1.3 Controller如下: ```java /** * RedisCluster 測試 * @author winfun * @date 2020/10/22 3:19 下午 **/ @RequestMapping("/redisCluster") @RestController public class RedisClusterController { @Autowired private StringRedisTemplate redisTemplate; /*** * String:根據 key 獲取 value * @author winfun * @param key key * @return {@link String } **/ @GetMapping("/get/{key}") public String get(@PathVariable("key") String key){ return redisTemplate.opsForValue().get(key); } /*** * String:設定 key/value 對 * @author winfun * @param key key * @param value value * @return {@link String } **/ @GetMapping("/set/{key}/{value}") public String set(@PathVariable("key") String key,@PathVariable("value") String value){ redisTemplate.opsForValue().set(key,value); return "success"; } } ``` ### 6.2 將專案打包並生成映象 #### 6.2.1 將專案打包成 Jar 包 ```shell mvn clean package ``` #### 6.2.2 生成映象 編寫 Dockerfile 檔案: ```shell FROM java:8 MAINTAINER winfun # jar 名稱為專案打包後的 jar ADD redis-cluster-test-0.0.1-SNAPSHOT.jar app.jar EXPOSE 8080 ENTRYPOINT ["java","-jar","app.jar"] ``` 接著去到 Dockerfile 當前目錄,執行下面命令: ```shell winfun@localhost redis-cluster-test % docker build -t winfun/rediscluster . Sending build context to Docker daemon 25.84MB Step 1/5 : FROM java:8 8: Pulling from library/java 5040bd298390: Pull complete fce5728aad85: Pull complete 76610ec20bf5: Pull complete 60170fec2151: Pull complete e98f73de8f0d: Pull complete 11f7af24ed9c: Pull complete 49e2d6393f32: Pull complete bb9cdec9c7f3: Pull complete Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d Status: Downloaded newer image for java:8 --->
d23bdf5b1b1b Step 2/5 : MAINTAINER winfun ---> Running in a99086ed7e68 Removing intermediate container a99086ed7e68 ---> f713578122fc Step 3/5 : ADD redis-cluster-test-0.0.1-SNAPSHOT.jar app.jar ---> 12ca98d789b8 Step 4/5 : EXPOSE 8080 ---> Running in 833a06f2dd32 Removing intermediate container 833a06f2dd32 --->
82f4e078510d Step 5/5 : ENTRYPOINT ["java","-jar","app.jar"] ---> Running in 517a1ea7f138 Removing intermediate container 517a1ea7f138 ---> ed8a66ef4eb9 Successfully built ed8a66ef4eb9 Successfully tagged winfun/rediscluster:latest ``` ### 6.3 啟動容器,進行測試 #### 6.3.1 啟動容器,並將容器加入上面建立的自定義網路 redis-net 構建後,我們可以利用 `docker ps` 命令看看我們的映象: ```shell winfun@localhost ~ % docker images | grep rediscluster winfun/rediscluster latest ed8a66ef4eb9 52 minutes ago 669MB ``` 利用 `docker run` 命令執行此映象啟動一個容器: ```shell winfun@localhost ~ % docker run -it -d -p 8787:8080 --name myrediscluster winfun/rediscluster 705998330f7e6941f5f96d187050d29c4a59f1b16348ebeb5ab0dbc6a1cd63e1 ``` 利用 `docker network connect` 將這個容器加入到上面的自定義網路 redis-net 中: ```shell winfun@localhost ~ % docker network connect redis-net myrediscluster ``` 當我們再檢視自定義網路 redis-net 的詳情,我們可以在 Containers 中找到 myrediscluster 這個容器,並且還給這個容器分配了自定義網路 redis-net 的一個 IP 地址。 如下圖: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2020102312565098.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0hvd2luZnVu,size_16,color_FFFFFF,t_70#pic_center) #### 6.3.2 我們此時可以直接到瀏覽器呼叫 RedisClusterController的介面: **設定一個 key/value**: ![set命令](https://img-blog.csdnimg.cn/20201023125825714.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0hvd2luZnVu,size_16,color_FFFFFF,t_70#pic_center) **根據key獲取value**: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201023125849150.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0hvd2luZnVu,size_16,color_FFFFFF,t_70#pic_center) 從上面可以看到,已經完全沒問題了。 但是呢,這樣我們每次測介面,都需要重新構建映象然後部署。 ### 6.4 bridge 和 host 模式 我們都知道,上面我們建立的自定義網路 redis-net 的模式是橋接模式,也就是 bridge。 他的最大特點是將 Docker 中容器的網路和宿主機隔離開來,容器的IP和宿主機的IP是不通的,所以在上面利用 JedisCluster 來操作 Redis 叢集時,當 JedisCluster 獲取到叢集的節點資訊是 Docker 中容器的 IP 時,是訪問不通的。 所以解決這個問題,其實我們可以利用 host 模式,它的原理其實就是容器共享宿主機的網路環境。這樣的話,JedisCluster 訪問 Redis 叢集應該就沒問題了。 對,就是**應該**,因為我自己嘗試了很多遍 host 模式下的 Redis 叢集部署,部署和利用 redis-cli 命令操作都是沒問題的。但是,當利用 JedisCluster 訪問叢集時,連叢集節點的資訊都沒拿到!! 所以需要大家自己去嘗試一下,具體可參考下面的文章: https://www.cnblogs.com/niceyoo/p/13011626.html ### 7 最後 到此,我相信大家都體驗了一波 Docker 的強大。在開發時利用好,簡直就是開發的神器。可以在本地利用最少的系統資源,輕鬆地去搭建一套完整的開發環境,包括各種中介軟體。