docker中的link和network網絡互連問題
原因和問題
docker 的每個容器相當于有個內網地址。
比如 mymysql 容器 172.17.0.2,mynginx 容器為 172.17.0.3 ,那么他們的通信機制是連到了 docker0 這個 bridge,大概如下圖:

容器之間互相訪問,一般形式是:ip + 端口,比如:
// 進入容器: docker run exec -it /bin/bash // ping 一下端口發(fā)現是通的(得已經做了映射到本地) ping 172.17.0.2:3306
問題:每次部署或啟動,相同容器的 IP 會發(fā)生變化。
解決方法:docker 中采用 link 來為容器起個名字,以后訪問只要名字 + 端口就行了,IP 變化了也沒關系。
link 的使用方法
請注意,這里只是介紹,請不要使用 link,將被廢棄。
第一種:使用 run 的參數
// 1、創(chuàng)建容器 test1 docker run -d --name test1 nginx // 2、創(chuàng)建容器 test2并 link 到 test1。 docker run -d --name test2 --link test1 nginx // 3、進入test2,并 ping test1,發(fā)現是可以 ping 通的。 docker exec -it test2 /bin/sh ping test1
test2 link 到 test,其實就是修改了 test2 自己的 host 文件和設置了環(huán)境變量而已。
所以 test2 能 ping 通 test1,但是 test1 無法 ping 通 test2
第二種:在 yml 文件中的使用方法
links: - db - db:database //連接到 db 服務,并命名為 database - redis
使用的別名將會自動在服務容器中的 / etc/hosts 里創(chuàng)建。
例如:
172.12.2.186 db 172.12.2.186 database 172.12.2.187 redis
- 相應的環(huán)境變量也將被創(chuàng)建。
- 使用 link 會默認連接到 【目錄_defeat】 網絡中,
關于使用 network
實際中是非常少使用 link 的,并且下一代版本將會被廢棄。應該使用 network。
將容器連接到自己創(chuàng)建的同一個網絡上,就可以相互 ping 通了。(記住,這里是自己創(chuàng)建的網橋才能 ping 通)
以下是常用的命令:
// 創(chuàng)建一個叫做 my-bridge 的網橋,使用的連接方式是 bridge docker network create -d bridge my-bridge // 顯示所有 bridge,可以看到我們剛剛創(chuàng)建的 my-bridge 網絡,id為75e4133b9ab2 docker network ls // 創(chuàng)建容器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,會發(fā)現自建的 my-bridge 的 containers里面有 mynginx2 //查看 my-bridge 網絡里面的容器 docker inspect my-bridge //手動將某個容器加入網橋 docker network connect my-bridage test2
使用 docker network ls 的時候,會發(fā)現,本來就有三中網絡,分別為 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_backphpfpm 在 front 網絡中的別名叫做 fpm,所以加入 front 網絡中的容器都可以使用以下兩個方式訪問:
1、【服務名: 端口】 ==>> 【phpfpm:9000】 <<== 我們目前的 nginx 設置的就是這個。
2、【別名: 端口】 ==>> 【fpm:9000】
我目前一般沒有設置別名,都用【服務名: 端口】的形式訪問。
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Docker創(chuàng)建一個Nginx服務器的方法步驟
使用Dokcer可以很好的對鏡像進行管理,創(chuàng)建和使用容器。這篇文章主要介紹了Docker創(chuàng)建一個Nginx服務器的方法步驟,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01
解析docker妙用SpringBoot構建微服務實戰(zhàn)記錄
Spring Boot 是 Spring 開源組織的子項目,是 Spring 組件一站式解決方案,本文通過詳細案例給大家解析docker妙用SpringBoot構建微服務實戰(zhàn)記錄,感興趣的朋友跟隨小編一起看看吧2021-11-11

