Docker-compose port 與 expose 差異

原本要寫個用 docker compose 來起 MongoDB container 的文章,發現整個弄完不到三分鐘,好像有點過於簡單。
就順便用這個為範本來討論一下port的功能與expose的差異,在剛開始接觸的時候被搞混了一下。

攥寫yml檔案

docker compose的檔案是用yml寫的,如果不知道什麼是 yml,可以參考一下連結,基本上就是比json更高可視化、更簡潔(更小)的設定檔。

將以下內容存成 docker-compose.yml 檔案即可

1
2
3
4
5
6
7
version: '3'
services:
database:
image: mongo
container_name: Mongo_DkrCmps_Test
ports:
- "27117:27017"

執行

下面兩個指令分別就是啟動與關閉這份 docker-compose

1
2
docker-compose up    //啟動
docker-compose down //關閉

alt

上圖就是寫好yml後執行,如果沒有MongoDB的image就會從網路上下載,下載好後就可以看到MongoDB的container已經在運行。

Ports

Ports參數是該container的port號要綁定在主機端的port位置
例如上面的例子就是將MongoDB預設的27017 port綁定在主機的 27117,這樣一來只需要連 localhost:27117 而不用暴露原始的 port號;更多細節會在後面文章談。

多個Port綁定?

這當然可以,我們把範例改成下面這樣

1
2
3
4
5
6
7
8
9
version: '3'
services:
database:
image: mongo
container_name: Mongo_DkrCmps_Test
ports:
- "27117:27017"
- "27118:27017"
- "27119"

請務必記得port需要使用雙引號當成字串處理,以免docker在解析上出問題

重新執行後我們使用 docker-compose ps 指令來看結果

alt

可以很清楚看到27117 與 27118皆綁定到 container的27017。
而主機端的任意port號會被綁定到container的27119。(個人覺得用途很奇妙?)

所以 ports 與 expose 有何不同?

簡單來說一個可以公開使用一個無法。
Ports: 能連到主機的這些 port 都能夠使用。
expose: 僅能在此 docker-compose 內的 container 們使用。

1
2
3
4
5
6
7
8
9
version: '3'
services:
database:
image: mongo
container_name: Mongo_DkrCmps_Test
ports:
- "27117:27017"
expose:
- "27118"

啟動後,我們一樣用docker-compose ps來查看,結果如下圖:

alt

我們可以發現 0.0.0.0:27117 可以連到 27017,但是 27118 無法在本機端連線,因為此yml範例中只有一個container,所以 27118 在這邊就沒功能了。

  • 為什麼不用dockerfile就好?
    因為專案之後還會陸續加入其他container,每次都打一堆指令會很不方便。

  • 這也太簡單了吧?
    如果什麼都使用預設值當然很簡單就是這樣,所有工具的官網都是這樣騙的

  • 為什麼截圖只有看到 dc up 指令
    可以參考這篇文章(macOS 編輯自己的快速指令),基本上就是利用別名的概念新增自己的快速鍵。

  • 每次都要開兩個視窗來啟動、關閉docker-compose很麻煩
    -d 參數是一定有支援的,只是在開發、測試階段我個人習慣還是看到terminal的訊息,協助debug

  • 我不能直接用ctrl+c關閉嗎?
    這答案可以也不可以,其實 docker-compose updocker-compose down已經是內建的綜合指令了。

    • docker-compose up 包含了 buildcreatestart 指令
    • docker-compose down 包含了 stoprm 指令

      細節我在這邊不多談,主要是舊的容器不會被刪除和volumne是否還會繼續留著引用的問題,所以還是建議乖乖下 docker-compose down 的指令。