Docker筆記 - 更改Container的Configuration

Albert Hg
alberthg-docker-notes
11 min readJan 29, 2021

上一篇-進入Container 的文章中我們說明了如何使用 docker exec 操作 Container,在建立 Container 的同時,就會同時一起設定 Container 的 Configuration,然而該如何更改已經建立好的 Container 的 Configuration 呢?

這篇文章將主要會說明該如何修改 Configuration,另外也會提出其他更好的做法。

文章架構

  • 甚麼情況會想要修改 Container 的 Configuration
  • 查看 Container 的 Configuration
  • Docker VM — Hyper-V Virtual Hard Disk
  • 進入 Docker VM — 使用 justincormack/nsenter1
  • 修改 Configuration
  • 其他建議 — 使用 Docker Volume

甚麼情況會想要修改 Container 的 Configuration

假設已經跑了一個服務在 Docker 中,但有時候我們可能會想要讓外部可以連接的 Port 改為其他號,例如 8080 改為 80。

但是!Docker 沒有提供給我們直接修改已經建立好的 Container 的 Configuration 的方法,所以當如果我們真的想要修改,那麼要怎麼做呢?

在開始討論如何修改之前,我們先來看一下該如何查看 Configuration。

查看 Container 的 Configuration

docker inspect [OPTIONS] NAME|ID [NAME|ID...]

透過 docker inspect,就可以查詢 Docker 物件的 Configuration。所謂的 Docker 物件代表的就是像 Image、Container 等等的物件,這些物件都會有自己的 Id 或 Name,我們就能透過這些 Id 或 Name 來進行查詢。

例如:

# 啟動一個 httpd 的 container
$ docker run -d --name my-http -p 8080:80 httpd
# 查詢 container 的 configuration
$ docker inspect my-http
...
"HostsPath": "/var/lib/docker/containers/a572e.../hosts",
...
"PortBindings": {
"80/tcp": [
{
"HostIp": "",
"HostPort": "8080"
}
]
},
...

在這裡面可以找到 HostsPath 的關鍵字,這代表了相關 Configuration 都放在這個路徑中。

可是這個路徑是在哪裡?如果你用 Mac,你沒辦法找到對應的路徑在 Mac 裡。如果你用 Windows 的 Linux Containers,你也沒辦法在對應的路徑找到他。所以這個路徑到底在哪裡?(謎之路徑)

Docker VM — Hyper-V Virtual Hard Disk

這個謎之路徑其實就在這個 VM 中。如果你的 Docker 是在 Windows 的 Linux Containers,你可以打開你的 Docker Dashboard,接著進入設定的 Resources,可以找到「Disk Image Location」的路徑。

進入這個路徑內,你可以找到一個 DockerDesktop.vhdx 的檔案,這個就是 Docker 掛載虛擬機的地方。而這個 DockerDesktop.vhdx 也就是存放了所有跟 Docker 相關的東西,例如存放的 Image、存放的 Container 等。

我們剛剛看到的 HostsPath 其實就是掛載在這個 vhdx 的虛擬機的路徑。如果我們想要可以修改 Configuration,那我們就要先想辦法可以進入到這個掛載的虛擬機內。

進入 Docker VM — 使用 justincormack/nsenter1

如果要在 Windows 中進入這個掛載的 VM 會很麻煩。而在 Mac 或 Unix 系統的環境中有 screen 指令可以進入 VM,但也會遇到一些問題,例如下方這篇文章:

這裡提供一個通用作法,也就是在 Windows 環境中,或者是 Mac 的環境中,都可以成功的方法 — 使用 justincormack/nsenter1。使用方式如下:

$ docker run -it --rm --privileged --pid=host justincormack/nsenter1

這就是在 Docker 內掛上一個可以讓你使用 nsenter 來進入 PID 1 的空間的 Container。透過這個方式,我們就可以直接進入到 VM 中。

接著我們就可以 cd 到 HostsPath 的路徑了!

修改 Configuration

在開始修改之前,我必須先說真的非常非常不建議這麼做,比較建議的做法會在後續提到,這小節的內容則可以當作參考,大概知道可以這樣改就好。

回到重點,如果要修改一個已經建立的 Container 的 Port 應該怎麼做呢?

  1. 先停止要修改的 Container
  2. 查詢要修改的 Container 的 Config,並記得如 HostsPath 的路徑
  3. 進入 Docker VM
  4. cd 至如 HostsPath 的路徑
  5. 開始修改 Config,修改 hostconfig.json (參考下方)
  6. 離開 Docker VM,重啟 Docker (重啟很重要,不然修改的內容會被還原)
  7. 執行修改後的 Container

hostconfig.json 要修改的內容如下:


"PortBindings":{"80/tcp":[{"HostIp":"","HostPort":"8080"}]}
改為
"PortBindings":{"80/tcp":[{"HostIp":"","HostPort":"<其他Port號>"}]}

進入 Docker VM 後如果要修改文件,只有 Vi 可以用 (連 Vim 都沒有),這裡簡單提一下怎麼使用 Vi 編輯 hostconfig.json

/var/lib/docker/containers/<container-id># vi hostconfig.json進入 Vi 的編輯頁面後,先按一下「i」(代表編輯)
編輯完後按一下 Esc,輸入「:w」後按 Enter (代表儲存)
再輸入「:q!」離開 Vi 的編輯頁面

是不是覺得要改個 Port 號很麻煩呢?改了其中一個 Container 的 Config 還要重啟 Docker 其實也非常不合乎邏輯。

其他建議 — 使用 Docker Volume

其實 Docker 會這樣設計也是有原因的,對於 Container 來說,有幾個宗旨:

  1. Containers are immutable,是不可變動的
    所有相關的東西,都被好好的打包在 Container 中,不想讓任何東西或設定被變動的原因是因為希望可以達到開發、測試環境能與生產環境盡可能有一樣的環性或行為
  2. Containers are lightweight,輕量化
    Docker 在設計 Container 時,希望 Container 能夠輕量化,讓 Container 能夠好好的分配記憶體的使用
  3. Containers are fast,運行快速
    綜合以上因素,Docker 希望 Container 能夠在建立或執行等動作上不需要花太多時間,就如同啟動一個傳統的、標準的 Linux Process 一樣快

就如同這些原因,所以 Docker 不希望我們去修改已經建立好的 Container 的 Config。縱使在 Container 中有想要保留的資料,也不要使用這樣的方式來修改 Config。因為 Container 占用資源少、重新建立的耗費便宜等特性,所以如果想要修改 Config,那麼就重新建立一個就好。

但是重新建立不就代表之前寫在 Container 的內容都會不見嗎?其實在使用 Container 的建議中有提到以下幾點:

  1. Don’t store data in containers,不要儲存資料在裡面
  2. Don’t ship your application in two pieces,不要佈署你的服務在已經正在執行的 Container 上
  3. Don’t run more than one process in a single container,不要執行多個 Process 在一個 Container 上

在 Container 的使用建議中有提到資料最好不要儲存在 Container 中,因為這會造成重新建立 Container 的資料遺失。另外也會造成 Container 的體積太過龐大,而失去了 Container Lightweight 的特性。

那麼替代方案是甚麼呢?那就是 Docker Volume。

原先 Container 與 Container 是相互獨立,並沒有關聯的,但為了想要共用資料,就可以將資料獨立存放在另外一個地方,而這個地方就是 Volume。因為篇幅的關係,這裡就先拋磚引玉一下,Volume 的部分則會在下一篇說明如何使用。

文末

本篇說明了如何暴力修改 Container 的 Configuration,雖然這不是一個推薦的好辦法,但會想要寫這一篇主要是希望可以幫助了解 Docker VM 是甚麼,以及有甚麼工具能幫助我們進入到 Docker VM 中,同時釐清關於 Docker VM 的相關細節。

這一篇文章的尾端有提到了 Volume,相關說明則會寫在下一篇。

前往

上一篇

下一篇

其他參考連結

--

--

Albert Hg
alberthg-docker-notes

I am a programmer but love other things. I am a nobody but keep myself going. I am a person who wishes to reach the heaven but lost the wings.