Docker實戰(zhàn)-容器相互訪問

問題引入

之前在找 Redis 好看的 GUI ,發(fā)現(xiàn)了 Redis 自家的 WebGUI「RedisInsight」還支持 Docker 部署 (1.11.1版本),打算使用 Docker Compose 來啟動 Redis 和 RedisInsight

最近「RedisInsight」2.x版本的桌面客戶端已經(jīng)推出了,可以看這篇文章了解
??顏值爆表!Redis官方可視化工具來啦,功能真心強大!

我們進入正題

因為我喜歡用 docker compose 來運行容器,所以這次問題也由我的兩份 docker-compose.yaml 文件開始

左邊是 RedisInsight,右邊是 Redis 的完全體—— RedisMod

redismod容器 redisinsight容器
image
image

啟動后,進入 RedisInsight 打算連接本地的 Redis,發(fā)現(xiàn)無法使用 127.0.0.1:6379 連接 Redis。

因為雖然宿主機可以通過 127.0.0.1:6379 連接 Redis,因為 Redis 容器通過端口映射的方式把 6379 端口映射到宿主機上;但是對于 RedisInsight 容器來說,是無法通過 127.0.0.1 這個網(wǎng)絡連接的,因為 Redis 不是在 RedisInsight 容器內(nèi)啟動,而且端口也不是向它映射,需要拿到 Redis 容器的 IP 地址才能正確連接。通過 docker inspect 容器id 可以看到兩個容器的 IP地址:

redismod容器IP地址 redisinsight容器IP地址
image
image

雖然可以使用宿主機的 IP 地址進行連接,但是 IP 地址不能保證不變,寫一個固定的值也不靈活。那有沒有什么辦法可以讓兩個容器互相連通互相訪問的同時還保持一定的靈活性呢?答案自然是有的。

前置知識

先回顧一下 Docker 的網(wǎng)卡

Docker 網(wǎng)卡介紹

image
  • bridge:默認網(wǎng)卡,類似于 VMware 的 NAT 模式,如果需要訪問容器內(nèi)部的端口需要進行端口映射。
  • host:直接使用主機網(wǎng)絡,類似于 VMware 的橋接模式,訪問容器內(nèi)部的端口時不需要進行端口映射,直接訪問即可,但是可能會與主機的端口號沖突。
  • none:禁止所有聯(lián)網(wǎng),沒有網(wǎng)絡驅(qū)動。

自定義網(wǎng)絡

使用 docker network create custom-local-net 創(chuàng)建一個名為 custom-local-net 的 Docker 網(wǎng)卡,這個網(wǎng)卡是基于 bridge 模式的,但是和 bridge 模式又有一定的區(qū)別。

這個問題官方給出了解釋:

User-defined bridges provide automatic DNS resolution between containers.
Containers on the default bridge network can only access each other by IP addresses, unless you use the --link option, which is considered legacy. On a user-defined bridge network, containers can resolve each other by name or alias.

這一段話官方給出了不少的信息量:

  1. 用戶自定義的網(wǎng)絡是基于 bridge 的,并且容器間可以通過容器名或別名進行自動 DNS 相互解析的功能
  2. 使用默認的 bridge 網(wǎng)絡僅僅能通過各自的 IP 地址來進行通信,除非使用 --link 選項
  3. --link 選項實現(xiàn)的容器相互訪問功能已經(jīng)被官方認定是過時的

由第 1 點可以得知,使用自定義網(wǎng)絡就能實現(xiàn)容器間相互通信的功能!

解決方案

docker run 使用 link 參數(shù)

在不使用 Docker Compose 的時候,在啟動命令中加入 --link 參數(shù),就可以實現(xiàn)容器之間的訪問

  • 啟動 redismod 容器

    docker run --rm --name redismod -p 6379:6379 -v /data/:/data -d redislabs/redismod:latest
    
  • 啟動 redisinsight容器

    docker run --rm --name redisinsight -p 8001:8001 -v /db:/db --link redismod -d redislabs/redisinsight:latest
    

使用 --link 中指定的 redismod 即可映射到 redismod 的容器網(wǎng)絡中。

image

然后在 Host 處填寫 [redismod] 就可以自動解析為 redismod 容器的 IP 地址。

image
image-20220517233113573

可以看到是連接成功的

使用同一份 docker-compose.yaml 文件

相比使用 docker run 命令啟動容器,顯然 docker compose 才是更為推薦的那一個方式,把啟動所需的鏡像、環(huán)境等全都寫到一份 docker-compose.yaml 文件中,方便使用。

如果使用 docker compose 的方式,就是把兩個容器的啟動信息都寫到同一份文件中,再在需要依賴另一個容器的容器啟動信息中加入 depends_on、links 參數(shù),這樣 redisinsight 也可以使用 redismod 解析到其容器的 IP地址,得到的結果和上面使用 docker run 的方式得到的結果是一樣的。

version: '3'
services:
  redismod:
    image: redislabs/redismod:latest
    ports:
      - 6379:6379
    volumes:
      - /redismod/data:/data

  redisinsight:
    image: redislabs/redisinsight:latest
    ports:
      - 8001:8001
    volumes:
      - /redisinsight/db:/db

docker run 使用自定義網(wǎng)絡

在上面我們簡單地介紹了一下如何自定義網(wǎng)絡,并且知道使用 link 參數(shù)的方式已經(jīng)是過時的,那通過自定義網(wǎng)絡,讓 Redis 容器和 RedisInsight 容器處于同一個網(wǎng)絡,并且他們可以互相進行 DNS 解析,就可以讓 RedisInsight 訪問到 Redis 容器了。

另外,docker run 命令也可以手動指定容器連接的網(wǎng)絡,使用 network 參數(shù)。

  • 自定義網(wǎng)絡 custom-local-net

    docker network create custom-local-net
    
  • 啟動 redismod 容器

    docker run --rm --name redismod -p 6379:6379 -v /redismod/data:/data --network custom-local-net -d redislabs/redismod:latest
    
  • 啟動 redisinsight 容器

    docker run --rm --name redisinsight -p 8001:8001 -v /redisinsight/db:/db --network custom-local-net -d redislabs/redisinsight:latest
    

進入 redisinsight 容器中 ping redismod 發(fā)現(xiàn)是能 ping 通的,在控制臺中自然也能通過 redismod 作為 host 來連接 redis 數(shù)據(jù)庫。

image

docker compose 使用自定義網(wǎng)絡

使用同一份 docker-compose.yaml 文件的方法雖然可行,但是還存在一定的局限性,假如需要鏈接一個使用 docker run 運行的容器,又怎么樣實現(xiàn)互相訪問呢?或者如果是這個需要容器本就處于一個已創(chuàng)建的自定義網(wǎng)絡呢?

另外使用 docker run 能指定自定義網(wǎng)絡,docker compose 自然也是可以的,通過 networks 指令。custom-local-net 網(wǎng)絡已經(jīng)被創(chuàng)建了,所以在 docker-compose.yaml 文件中直接指定即可。

其中在 docker-compose.yaml 文件中有兩種使用自定義網(wǎng)絡的方式:

  • 創(chuàng)建并使用,如果沒有手動使用 docker network create 命令,需要在使用前創(chuàng)建

    version: '3'
    services:
      redisinsight-local-net:
        image: redislabs/redisinsight:latest
        ports:
          - 8001:8001
        volumes:
          - /redisinsight/db:/db
        networks:
          - custom-local-net-2
    
      redismod-local-net:
        image: redislabs/redismod:latest
        ports:
          - 6379:6379
        volumes:
          - /redismod/data:/data
        networks:
          - custom-local-net-2
    
    
    networks:
      custom-local-net-2:
        # 聲明使用的網(wǎng)絡是使用 bridge 驅(qū)動來創(chuàng)建的
        driver: bridge
        ipam:
          # 網(wǎng)絡配置
          config:
            # 分配的子網(wǎng)網(wǎng)段
            - subnet: 172.25.64.0/18
            # 網(wǎng)關地址
              gateway: 172.25.64.1
    
    
  • 聲明并使用,如果已經(jīng)手動創(chuàng)建了網(wǎng)絡,在 docker-compose.yaml 文件中只需聲明一下即可

    version: '3'
    services:
      redisinsight-local-net:
        image: redislabs/redisinsight:latest
        ports:
          - 8001:8001
        volumes:
          - /redisinsight/db:/db
        networks:
          - custom-local-net
    
      redismod-local-net:
        image: redislabs/redismod:latest
        ports:
          - 6379:6379
        volumes:
          - /redismod/data:/data
        networks:
          - custom-local-net
    
    
    networks:
      custom-local-net:
          # 聲明這個網(wǎng)絡是外部定義的
        external: true
    
image
image

最終也是實現(xiàn)了訪問 redismod 的網(wǎng)絡

總結

Docker 容器之間相互訪問是實際生產(chǎn)中難以繞開的一道坎,誠然可以使用橋接模式,但是橋接模式不太利于環(huán)境的遷移。顯然使用能自動完成 DNS 解析的網(wǎng)絡模式會更為靈活,也更為優(yōu)雅。

參考資料

【Docker系列】Docker Compose 網(wǎng)絡_小葉柏杉的博客-CSDN博客_docker-compose 網(wǎng)絡模式

如果這篇文章對你有幫助,請給我一個免費的大拇哥??

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容