同乙個宿主機上的多個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服務,即使容器重啟了,位址發生了變化,不會影響兩個容器之間的連線。
雖然通過使用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:
aliasdb_port_3306_tcp=tcp:
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
上面的變數被分成了五個部分:
_port__
_port___port
_port___proto
_port___addr
其中
是在dockerfile中使用expose匯出的埠,還有docker run 的時候使用-p匯出的埠。
則是這些埠對應的協議。
使用了link機制後,可以通過指定的名字來和目標容器通訊,這其實是通過給/etc/hosts
中加入名稱和ip的解析關係來實現的,下面是名為web的容器中的/etc/hosts
資訊.
172.17
.0.10 6337c0044215
127.0
.0.1
localhost
::1localhost
ip6-localhost
ip6-loopback
fe00
::0ip6-localnet
ff00
::0ip6-mcastprefix
ff02
::1ip6-allnodes
ff02
::2ip6-allrouters
172.17
.0.8
aliasdb
c1a7c7f091eb
db
通過上面的資訊可以看出,link機制給received container(這裡是名為web的容器)新增了一條關於db容器的名稱解析。有了這個名稱解析後就可以不使用ip來和目標容器通訊了,除此之外當目標容器重啟,docker會負責更新/etc/hosts
檔案,因此可以不用擔心容器重啟後ip位址發生了改變,解析無法生效的問題。但是很不幸的是,環境變數無法更新,上文中提到了link機制會通過環境變數將一些db容器的資訊匯入到web容器中,這種匯入是一次性的,此後這個容器更新了環境變數的資訊是無法在web容器中更新的。
通過上文中對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機制。這些特性包括如下幾個方面:
在使用者自定義網路下,不使用link機制就可以實現名稱解析功能了,不再是通過link機制追加名稱解析關係到/etc/hosts
檔案中了。並且在預設的docker0橋接網路和自定義網路下使用link機制的效果是不一樣的,在自定義網路中link機制只是負責設定別名的,不再提供環境變數注入的功能了。自定義網路中同時也提供了--net-alias
功能和link機制提供別名功能是一樣的。保留link機制目的是為了相容。
legacy container links
linking containers in user-defined networks
深入理解docker的link機制
摘要 什麼是docker的link機制 同乙個宿主機上的多個docker容器之間如果想進行通訊,可以通過使用容器的ip位址來通訊,也可以通過宿主機的ip加上容器暴露出的埠號來通訊,前者會導致ip位址的硬編碼,不方便遷移,並且容器重啟後ip位址會改變,除非使用固定的ip,後者的通訊方式比較單一,只能依...
深入理解 Docker 映象 json 檔案
很多時候,當大家談論起docker,經常會提到docker作為容器解決方案,在虛擬化資源方面存在不小優勢。輕量級虛擬化技術的優點暫且不談,從軟體生命週期來看,docker在打包軟體 分發軟體方面的能力同樣出眾。而後者很大程度上依賴於docker的映象技術。docker映象技術提供了一套標準,創造性地...
深入理解C語言 深入理解指標
關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...