3.3 Docker 的 DNS
這邊先科普一下 DNS 本身是什麼意思,全名:網域名稱系統( 英語:Domain Name System,縮寫:DNS ),白話來說就是網際網路世界的電話簿,那為什麼我們會需要電話簿呢?
這邊先假設大家都知道網際網路的互動是透過 IP 位置來找到對方並進行訊息的傳送 ( 想像是打電話給您的親朋好友,必須要知道手機號碼才有辦法聯繫 )。 舉個簡單的例子,在網址中輸入 https://142.251.42.238 會前往 google.com,但平常真的會輸入一大段 IP 位置嗎?也太難記了吧!
而 DNS 就是輸入 google.com 時會幫您找到 https://142.251.42.238 的應用程式,可以想像 IP 位置就是真實的地址,而 DNS 則是一個別名的概念,就像大家常常會提到北車 ( 台北車站 ),但你真的知道台北車站的地址嗎?或是你真的需要知道地址才可以到達台北車站嗎?
Docker 中的 DNS
在 Docker 的世界,我們可以忘掉 IP 位置這件事情,就如同前面章節有提過的,容器的 IP 位置會由 Docker 分配,每次容器啟動的時機不同,快一秒或慢一秒就會導致每個容器的 IP 位置不相同,所以若是要透過 IP 位置來讓容器們彼此溝通顯然是不切實際的事情。
這時候剛剛提到的 DNS 就是 Docker 提出的解決方案,要如何可以一直連線到某一個服務而不論其啟動順序呢?
答案就在一開始我們就學會的 --name
這個指令,當我們替容器命名後,在 Docker 的虛擬網路中,我們為他的命名就會是這個服務的 DNS,我們可以透過容器的名字輕易的訪問到容器本身。
如果使用 IP 位置來溝通
這裡示範用 IP 位置來連接到另外一個容器,是錯誤的示範,來看看如果容器啟動的順序不同會造成什麼樣的問題吧!
首先我們透過下方指令清空所有的容器。
$ docker container rm --force $(docker container ls --all --quiet)
把接下來啟動的容器都連接到剛剛建立的 app 虛擬網路內。
$ docker container run --publish 3000:3000 --detach --name whoami --network app robeeerto/whoami # 不換行
接著打開瀏覽器輸入 http://127.0.0.1:3000,應該會看到畫面顯示著:
容器名稱:eb356e256481 # 不會和我一樣
容器的 IP 位置:172.26.0.2 # 不會和我一樣
環境變數 AUTHOR 是:robertchang # 這邊會一樣
這邊的容器名稱就是我們剛剛啟動容器的 ID,而 IP 位置則是前面介紹過 Docker 分配的 IP 位置,至於第三個環境變數,則等到 Docker 映像檔篇 才會進行解說,這邊可以暫時不理會,接著我們在啟動第二個相同的容器吧!
$ docker container run --publish 3001:3000 --detach --name whoami-2 --network app robeeerto/whoami # 不換行
接著打開瀏覽器輸入 http://127.0.0.1:3001,應該會看到畫面顯示著:
容器名稱:c531f601ebf8 # 不會和我一樣
容器的 IP 位置:172.26.0.3 # 不會和我一樣
環境變數 AUTHOR 是:robertchang # 這邊會一樣
現在 app 的虛擬網路中有著 whoami 以及 whoami-2 兩個容器,接著我們試著用 IP 位置的方式來進行溝通吧!
$ docker container exec --interactive --tty whoami sh <- 進入第一個容器
/ # curl 172.26.0.3:3000
容器名稱:c531f601ebf8<br>容器的 IP 位置:172.26.0.3<br>環境變數 AUTHOR 是:robertchang
成功的透過 curl 這項工具和 whoami-2 這個容器進行溝通了。
乍看之下沒有問題,但若是容器的啟動順序不同呢?
如果把剛剛的流程走過一次但在中間穿插一個不一樣的服務會發生什麼事呢?
$ docker container rm --force $(docker container ls --all --quiet)
# 清空所有容器
$ docker container run --publish 3000:3000 --detach --name whoami --network app robeeerto/whoami # 不換行
$ docker container run --detach --name pg --env POSTGRES_PASSWORD=mysecretpassword --network app postgres # 不換行
$ docker container run --publish 3001:3000 --detach --name whoami-2 --network app robeeerto/whoami # 不換行
現在 app 虛擬網路中有了 whoami、pg、whoami-2 共三個容器,且啟動的順序是在兩個 whoami 的容器中間穿插了 pg,讓我們繼續用 IP 位置來嘗試連線 whoami-2 這個容器吧!
$ docker container exec --interactive --tty whoami sh <- 進入第一個容器
/ # curl 172.26.0.3:3000
curl: (7) Failed to connect to 172.26.0.3 port 3000 after 1 ms: Connection refused