深入理解docker的link機制

2021-09-08 19:03:01 字數 4114 閱讀 6925

摘要: 什麼是docker的link機制 同乙個宿主機上的多個docker容器之間如果想進行通訊,可以通過使用容器的ip位址來通訊,也可以通過宿主機的ip加上容器暴露出的埠號來通訊,前者會導致ip位址的硬編碼,不方便遷移,並且容器重啟後ip位址會改變,除非使用固定的ip,後者的通訊方式比較單一,只能依靠監聽在暴露出的埠的程序來進行有限的通訊。通過docker的link機制可以通過乙個name來和另一

什麼是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服務,即使容器重啟了,位址發生了變化,不會影響兩個容器之間的連線。

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:

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

使用了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機制提供了如下幾個功能

安全的容器間連線通訊,這個需要結合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容器之間如果想進行通訊,可以通過使用容器的ip位址來通訊,也可以通過宿主機的ip加上容器暴露出的埠號來通訊,前者會導致ip位址的硬編碼,不方便遷移,並且容器重啟後ip位址會改變,除非使用固定的ip,後者的通訊方式比較單一,只能依靠監聽在暴露出的埠的程序來進行有限的通訊...

深入理解 Docker 映象 json 檔案

很多時候,當大家談論起docker,經常會提到docker作為容器解決方案,在虛擬化資源方面存在不小優勢。輕量級虛擬化技術的優點暫且不談,從軟體生命週期來看,docker在打包軟體 分發軟體方面的能力同樣出眾。而後者很大程度上依賴於docker的映象技術。docker映象技術提供了一套標準,創造性地...

深入理解C語言 深入理解指標

關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...