docker 的 link 和 network 網絡互連問題


——————  原因和問題 ——————

 

docker的每個容器相當於有個內網地址。比如 mymysql 容器172.17.0.2,mynginx 容器為172.17.0.3 ,那么他們的通信機制是連到了 docker0 這個bridge,大概如下圖:

 

容器之間互相訪問,一般形式是:ip+端口,比如:

// 進入容器:
docker run exec -it /bin/bash

// ping 一下端口發現是通的(得已經做了映射到本地)
ping 172.17.0.2:3306

—— 問題:每次部署或啟動,相同容器的 IP 會發生變化。

—— 解決方法:docker中采用link來為容器起個名字,以后訪問只要名字+端口就行了,IP 變化了也沒關系。

 

// link的使用方法:—— 請注意,這里只是介紹,請不要使用 link,將被廢棄。

第一種:使用 run 的參數

// 1、創建容器 test1
docker run -d --name test1 nginx

// 2、創建容器 test2並 link 到 test1。
docker run -d --name test2 --link test1 nginx

// 3、進入test2,並 ping test1,發現是可以 ping 通的。
docker exec -it test2 /bin/sh
ping test1

—— test2 link 到 test,其實就是修改了 test2自己的 host 文件和設置了環境變量而已。所以test2能 ping 通 test1,但是 test1無法 ping通 test2

 

第二種:在 yml 文件中的使用方法:

links:
 - db
 - db:database     //連接到 db 服務,並命名為 database
 - redis

使用的別名將會自動在服務容器中的/etc/hosts里創建。例如:

172.12.2.186  db
172.12.2.186  database
172.12.2.187  redis

—— 相應的環境變量也將被創建。

—— 使用 link 會默認連接到 【目錄_defeat】 網絡中,

 

 

 

—————— 關於使用 network ——————

實際中是非常少使用 link 的,並且下一代版本將會被廢棄。應該使用 network。

將容器連接到自己創建的同一個網絡上,就可以相互 ping 通了。(記住,這里是自己創建的網橋才能 ping 通)

以下是常用的命令:

// 創建一個叫做 my-bridge 的網橋,使用的連接方式是 bridge
docker network create -d bridge my-bridge

// 顯示所有 bridge,可以看到我們剛剛創建的 my-bridge 網絡,id為75e4133b9ab2
docker network ls

// 創建容器mynginx2並添加到 my-bridge 網絡中 
docker run --name mynginx2 --network my-bridge -p 8080:80 -d nginx:latest

// 使用 inspect 查看。NETWORK 顯示的是 my-bridge,且 ID 為75e4133b9ab2。 內網 IP 為172.18.0.2(之前沒指定都是默認的172.17.xx.xx,即默認的 docker0 )
docker inspect mynginx2

——同理,你也可以通過 docker inspect my-bridge,會發現自建的 my-bridge 的 containers里面有 mynginx2

//查看 my-bridge 網絡里面的容器
docker inspect my-bridge

//手動將某個容器加入網橋
docker network connect my-bridage test2

———— 使用 docker network ls 的時候,會發現,本來就有三中網絡,分別為 host none bridge,並且這原始的三種是無法刪除的、 

 

  

// 在 yml 文件中定義networks:

version: '3'
services:
  nginx:
    image: nginx:1.15-alpine
    container_name: mynginx
    ports:
      - "80:80"
    volumes:
      - ${DIR_WWW}:${DIR_WWW}:rw
      - ./conf/nginx/conf.d:/etc/nginx/conf.d/:ro
      - ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./log/nginx/:/var/log/nginx/:rw
    networks: - front

  phpfpm:
    image: raven666/ct-phpfpm:v1
    container_name: myphpfpm
    expose:
      - "9000"
    volumes:
      - ${DIR_WWW}:${DIR_WWW}:rw
      - ./conf/php/php.ini:/usr/local/etc/php/php.ini:ro
      - ./conf/php/php-fpm.d/www.conf:/usr/local/etc/php-fpm.d/www.conf:rw
      - ./conf/supervisor/conf.d:/etc/supervisor/conf.d/:ro
      - ./log/php-fpm/:/var/log/php-fpm/:rw
      - ./log/supervisor/:/var/log/supervisor/:rw
    command: supervisord -n
 networks: - front - backend
      
  mysql:
    image: mysql:5.7
    container_name: mymysql
    env_file: .env
    ports:
      - "3306:3306"
    volumes:
      - ./conf/mysql/mysql.cnf:/etc/mysql/conf.d/mysql.cnf:ro
      - ${DIR_MYSQL_DATA}:/var/lib/mysql/:rw
      - ./log/mysql/:/var/log/mysql/:rw
    environment:
      MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}"
      MYSQL_DATABASE: "${MYSQL_DATABASE}" networks: - backend

  redis:
    image: redis:latest
    container_name: myredis
    env_file: .env
    command: redis-server --requirepass "${REDIS_PASSWORD}" --appendonly yes
    ports:
      - "6379:6379"
    volumes:
      - ${DIR_REDIS_DATA}:/data
 networks: - backend

networks: front: backend:

—— 因為我們指定了網絡,所以up 之后,就會自動生成兩個網絡,分別為【當前目錄名_front】和【當前目錄名_backend】

—— 以上不指定 driver,則會默認使用 bridge。

—— 加入同一個網絡的容器之間可以互聯,比如以上加入front 的 nginx 和 phpfpm,它們就可以互聯。同理,php 和 mysql,redis 都加入了 backend,也可以互聯。

       容器之間的訪問可以使用【服務名:端口】的形式,或者【別名:端口】的形式。

那么,如何設置別名呢?如下例子:

services:
  phpfpm:
    networks:
      front:
        aliases:
         - fpm
      backend:
        aliases:
         - fpm_back

—— phpfpm 在 front 網絡中的別名叫做 fpm,所以加入 front 網絡中的容器都可以使用以下兩個方式訪問:

1、【服務名:端口】   ==>>   【phpfpm:9000】  <<== 我們目前的 nginx 設置的就是這個。

2、【別名:端口】    ==>>    【fpm:9000】

—— 我目前一般沒有設置別名,都用【服務名:端口】的形式訪問。

 

 

 

 

 

 

 

 

 

 

 

 

———— 占位符

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM