通過docker run
命令的--link
參數可以讓容器之間通過連接(linking)系統進行交互。
參數格式:--link name:alias
,name是要鏈接的容器名稱, alias是此連接的別名。
容器的連接系統會依據容器的名稱,創建容器之間一個安全隧道,在啟動容器的時候不使用-p
和-P
參數(不用映射端口到宿主主機),從而避免了暴露端口到外部網絡。
通過docker run
命令的--name
參數來自定義容器名稱(容器的名稱是唯一的)。
通過docker ps
命令結果的NAMES部分,查看容器名稱。
Docker通過環境變量為容器公開連接信息,還添加host信息到父容器的/etc/hosts
文件。
用戶可以鏈接多個父容器到子容器。
一、什么是docker的link機制
同一個宿主機上的多個docker容器之間如果想進行通信,可以通過使用容器的ip地址來通信,也可以通過宿主機的ip加上容器暴露出的端口號來通信,前者會導致ip地址的硬編碼,不方便遷移,並且容器重啟后ip地址會改變,除非使用固定的ip,后者的通信方式比較單一,只能依靠監聽在暴露出的端口的進程來進行有限的通信。通過docker的link機制可以通過一個name來和另一個容器通信,link機制方便了容器去發現其它的容器並且可以安全的傳遞一些連接信息給其它的容器。其使用方式如下:
1.運行一個容器,通過–name指定一個便於記憶的名字,這個容器被稱為source container,也就是要連接的容器
docker run --name db -e MYSQL_ROOT_PASSWORD=server -d mysql
上面通過傳遞環境變量MYSQL_ROOT_PASSWORD=server,來設置mysql服務的密碼為server
2.運行另外一個容器,並link到上面啟動的容器,這個容器被稱為received container
sudo docker run -d --name web --link db:aliasdb nginx
上面通過--link
連接名為db的容器,並為其設置了別名aliasdb
完成了上面的兩個步驟后,在nginx的容器中就可以使用db或者aliasdb作為連接地址來連接mysql服務,即使容器重啟了,地址發生了變化,不會影響兩個容器之間的連接。
1.1、link機制的連接信息傳遞
雖然通過使用link機制nginx可以和mysql進行通信了,但是如何知道mysql的端口是多少呢,雖然說是固定的是 3306,但是也不排除更改端口號的問題,並且對應一些非固定端口的應用來說,只要要連接的容器的端口信息也是尤為重要的,link機制通過環境變量的方式提供了這些信息,除此之外像db的密碼這些信息也會通過環境變量提供,docker將source container中定義的環境變量全部導入到received container中,在received container中可以通過環境變量來獲取連接信息下面是db中提供的環境變量:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/mysql/bin:/usr/local/mysql/scripts HOSTNAME=c1a7c7f091eb MYSQL_ROOT_PASSWORD=server MYSQL_MAJOR=5.5 MYSQL_VERSION=5.5.48 HOME=/root
注: 使用docker exec db env
命令來獲得上面的結果
下面我們來看看在web這個容器中,這些變量是如何被導入的。
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=6337c0044215 ALIASDB_PORT=tcp://172.17.0.8:3306 ALIASDB_PORT_3306_TCP=tcp://172.17.0.8:3306 ALIASDB_PORT_3306_TCP_ADDR=172.17.0.8 ALIASDB_PORT_3306_TCP_PORT=3306 ALIASDB_PORT_3306_TCP_PROTO=tcp ALIASDB_NAME=/web/aliasdb ALIASDB_ENV_MYSQL_ROOT_PASSWORD=server ALIASDB_ENV_MYSQL_MAJOR=5.5 ALIASDB_ENV_MYSQL_VERSION=5.5.48 NGINX_VERSION=1.9.10-1~jessie HOME=/root
上面的變量被分成了五個部分:
- 第一個部分是web容器自身提供的一些環境變量,如NGINX_VERSION,HOSTNAME,HOME,PATH等.
- 第二個部分則是ALIASDB_ENV開頭的變量,這些都是從source container中導入的,變量來源於Dockerfile中使用ENV命令定義的變量,或者是docker run的時候通過-e 添加的環境變量。
- 第三個部分是ALIASDB_NAME 這個變量,這變量記錄了link的兩個容器的組合,這里就是
/web/db
- 第四個部分就是ALIASDB_PORT開頭的一系列變量,這些變量會有很組,每組變量的命名格式如下
<alias>_PORT_<port>_<protocol> <alias>_PORT_<port>_<protocol>_PORT <alias>_PORT_<port>_<protocol>_PROTO <alias>_PORT_<port>_<protocol>_ADDR
其中<port>
是在Dockerfile中使用EXPOSE導出的端口,還有docker run 的時候使用-p導出的端口。<protocol>
則是這些端口對應的協議。
- 第五個部分就是ALIASDB_PORT這個變量,這個變量是EXPOSE導出端口中的第一個端口對應的連接url,
如果有EXPOSE導出的端口,還有docker run -p指定導出的端口,那么通過-p指定的端口是第一個被導出的端口
1.2、link機制和/etc/hosts
使用了link機制后,可以通過指定的名字來和目標容器通信,這其實是通過給/etc/hosts
中加入名稱和IP的解析關系來實現的,下面是名為web的容器中的/etc/hosts
信息.
172.17.0.10 6337c0044215 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.8 aliasdb c1a7c7f091eb db
通過上面的信息可以看出,link機制給received container(這里是名為web的容器)添加了一條關於db容器的名稱解析。有了這個名稱解析后就可以不使用ip來和目標容器通信了,除此之外當目標容器重啟,docker會負責更新/etc/hosts
文件,因此可以不用擔心容器重啟后IP地址發生了改變,解析無法生效的問題。但是很不幸的是,環境變量無法更新,上文中提到了link機制會通過環境變量將一些db容器的信息導入到web容器中,這種導入是一次性的,此后這個容器更新了環境變量的信息是無法在web容器中更新的。
link機制和網絡新特性
通過上文中對link機制的介紹,可以發現link機制提供了如下幾個功能
- 名稱解析
- 對link的容器可以使用別名
- 安全的容器間連接通信
- 環境變量的注入
安全的容器間連接通信,這個需要結合docker daemon的-icc=false
這個選項,默認同一個宿主機上的所有容器可以互相通信,當使用-icc=false
的時候所有容器之間是無法進行互相通信的(具體原因會單獨出篇文章分析),但是使用link機制后,即使使用了-icc=false
兩個容器之間也可以進行基於端口的通信。很不幸的是當docker引入網絡新特性后,link機制變的有些多余,但是為了兼容早期版本,–link機制在默認網絡上的功能依舊沒有發生變化,docker引入網絡新特性后,內置了一個DNS Server,但是只有用戶創建了自定義網絡后,這個DNS Server才會起作用。在網絡新特性為未引入之前,有三種網絡,第一種就是docker0這種橋接網絡,用的也是最多的,第二個則是復用主機網絡,稱為HOST網絡,第三種就是none網絡,只創建了一個空的網絡命名空間,沒有網絡接口,無法和外界通信,可以讓使用者自己去構建網絡。當網絡新特性引入后,有了overlay網絡,有了用戶自定義網絡。用戶自定義網絡下,用戶可以通過docker的network子命令創建一個自定義的橋接網絡,這個自定義橋接的網絡和默認的docker0橋接網絡基本功能都是一致的,只是在這個自定義橋接網絡中擁有一些特性,可以替代link機制。這些特性包括如下幾個方面:
- 基於DNS的名稱自動解析
- 安全的隔離環境
- 動態的附加或者脫離一個網絡
- 支持使用–link設置別名
在用戶自定義網絡下,不使用link機制就可以實現名稱解析功能了,不再是通過link機制追加名稱解析關系到/etc/hosts
文件中了。並且在默認的docker0橋接網絡和自定義網絡下使用link機制的效果是不一樣的,在自定義網絡中link機制只是負責設置別名的,不再提供環境變量注入的功能了。自定義網絡中同時也提供了--net-alias
功能和link機制提供別名功能是一樣的。保留link機制目的是為了兼容。
參考文獻
Legacy container links
Linking containers in user-defined networks