—————— 原因和問題 ——————
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】
—— 我目前一般沒有設置別名,都用【服務名:端口】的形式訪問。
———— 占位符