Linux 桌面玩家指南:18. 我對 Docker 的使用的學習心得
特別說明:要在我的隨筆後寫評論的小夥伴們請注意了,我的部落格開啟了 MathJax 數學公式支援,MathJax 使用 $
標記數學公式的開始和結束。如果某條評論中出現了兩個 $
,MathJax 會將兩個 $
之間的內容按照數學公式進行排版,從而導致評論區格式混亂。如果大家的評論中用到了 $
,但是又不是為了使用數學公式,就請使用 \$
轉義一下,謝謝。
想從頭閱讀該系列嗎?下面是傳送門:
- Linux 桌面玩家指南:01. 玩轉 Linux 系統的方法論
- Linux 桌面玩家指南:02. 以最簡潔的方式打造實用的 Vim 環境
- Linux 桌面玩家指南:03. 針對 Gnome 3 的 Linux 桌面進行美化
- Linux 桌面玩家指南:04. Linux 桌面系統字型配置要略
- Linux 桌面玩家指南:05. 發部落格必備的圖片處理和視訊錄製神器
- Linux 桌面玩家指南:06. 優雅地使用命令列及 Bash 指令碼程式語言中的美學與哲學
- Linux 桌面玩家指南:07. Linux 中的 Qemu、KVM、VirtualBox、Xen 虛擬機器體驗
- Linux 桌面玩家指南:08. 使用 GCC 和 GNU Binutils 編寫能在 x86 真實模式執行的 16 位程式碼
- Linux 桌面玩家指南:09. X Window 的奧祕
- Linux 桌面玩家指南:10. 沒有 GUI 的時候應該怎麼玩
- Linux 桌面玩家指南:11. 在同一個硬碟上安裝多個 Linux 發行版以及為 Linux 安裝 Nvidia 顯示卡驅動
- Linux 桌面玩家指南:12. 優秀的文字化編輯思想大碰撞(Markdown、LaTeX、MathJax)
- Linux 桌面玩家指南:13. 使用 Git 及其 和 Eclipse 的整合
- Linux 桌面玩家指南:14. 數值計算和符號計算
- Linux 桌面玩家指南:15. 深度學習可以這樣玩
- Linux 桌面玩家指南:16. 使用 CUDA 發揮顯示卡的計算效能
- Linux 桌面玩家指南:17. 在 Ubuntu 中使用 deepin-wine,解決一些依賴 Windows 的痛點問題
前言
關於 Docker 的介紹,我這裡就不廢話了。Docker 是什麼?Docker 和虛擬機器有什麼區別?Docker 適用的場景是什麼?這些介紹早就爛大街了。大家可以去 Docker 的官網首頁看介紹,也可以在部落格園的首頁隨便搜一下,入門級的文章到處都是。如果想了解更深一點的技術細節,可以看sparkdev 的部落格,我這裡先對sparkdev 表示感謝,我這篇隨筆中,引用了他的部分內容。而且,我這篇的標題是“我對 Docker 的使用的學習心得”,重點是學習它的使用,而不是它的原理。
安裝 Docker
在 Ubuntu 中安裝 Docker 真的是太方便了。完全不用訪問 Docker 的官網,不需要自己去下載, apt
超級牛力瞬間搞定。稍微需要注意的是,不是安裝 docker
軟體包,而是安裝 docker.io
軟體包。首先,我先用 sudo aptitude search docker
命令檢視 Ubuntu 的軟體源中有哪些和 Docker 有關的包,如下圖:

其中 docker
被明確標記為 transitional package,所以我們安裝下面的 docker.io
包,使用 sudo aptitude install docker.io
命令。安裝完成後,使用 sudo docker --version
檢視一下,發現是最新的版本,而且是社群版,不是企業版,所以其版本號為 18.06.1-ce。如下圖:

拉兩個映象測試一下
只要稍微瞭解一點 Docker 的人都知道有一個 dockerhub,和我們常用的 github 一樣,可以獲得別人精心製作並分享的資源。在 github 中,我們可以找到我們感興趣的專案,並把它 clone 到本地。而在 dockerhub 中,這些資源叫 Image,我們可以把我們感興趣的 Image 拉到本地,並以該 Image 為基礎,執行一些 Container。
關於 Image 和 Container 的概念,我這裡不再廢話。我選擇了一個 ubuntu,還有一個 spacevim。使用的命令分別為 sudo docker pull ubuntu
和 sudo docker pull spacevim
。如下圖:

配置 Docker 使用中國的 Image 倉庫
上面拉取 Image 的操作看似簡單,其實經歷過失敗,主要原因就是國外的倉庫被牆擋住了。解決這個問題的方法,就是設定 Docker 使用中國的 Image 倉庫。其設定方法為修改 /etc/docker/daemon.json
配置檔案,如果沒有該檔案,就新建一個。將其內容修改為:
{ "registry-mirrors":["https://registry.docker-cn.com"] }
然後,使用如下命令重啟 Docker 服務:
systemctl daemon-reload systemctl restart docker
執行一個容器
使用 sudo docker image ls
命令可以檢視我們的機器上有哪些 Image,使用 sudo docker container ps -a
命令,可以檢視我們的機器上有哪些 Container。在上圖中,在我們拉取映象之前,它們的顯示結果都是空的。 sudo docker container ps -a
命令之所以要加上 -a
引數,就是為了顯示所有的 Container,包括執行的和停止的。
拉取完了以後,再使用 sudo docker image ls
命令,顯示的就不再是空的了。如下圖:

然後,使用 sudo docker run -it spacevim/spacevim nvim
命令執行一個容器,啟動 SpaceVim,如下圖:

在上圖中,我分別寫了一個 C 語言的檔案和一個 Python 語言的檔案,同時修改了一下 SpaceVim 自己的配置檔案。
介紹一下 SpaceVim
SpaceVim 是一個非常優秀的 Vim 整合專案,簡單點說,就是通過各種外掛把 Vim 打造成一個萬能的 IDE,而且它對 NeoVim 支援非常好。確實很漂亮,功能也確實很強大。但是,我係統上用的 Vim 是我自己配的一個非常簡潔的 Vim(請看我前面的隨筆),如果再在系統上安裝 SpaceVim 就不太方便。所以,使用 SpaceVim 官方提供的 Docker Image 就是一個非常方便的選擇了。
Docker 的最常用命令和引數
從上面的截圖可以看出,我們最常用的命令就是 sudo docker run
命令,它就是以某個 Image 為基礎執行一個新的 Container,注意,是新的 Container 哦。也就是說,每執行一次 sudo docker run
,就建立一個新的 Container,哪怕它們用的是同一個 Image。如果要啟動一個已經存在的 Container 怎麼辦呢?別擔心,有 sudo docker container start
命令。
最常用的引數是 -i
和 -t
,只有這樣,我們才能夠和 Container 中的程式進行互動。其次,就是 -p
引數,可以把 Container 中的某個埠對映到主機的某個埠,這對網路服務非常重要。還有 -v
引數,可以把主機的某個目錄對映到 Container 中的某個目錄,這樣,共享檔案就很方便了。
使用 SpaceVim 時遇到的問題:在一個 Container 中可以執行多個程式嗎?
使用 SpaceVim 的 Image 啟動一個 Container 後,問題來了。每次啟動這個 Container,就自動執行 nvim,進入 SpaceVim 的介面,編輯檔案是不成問題,可是這個編輯器介面畢竟不是 Shell 不是嗎?我們其它的管理工作怎麼做?
而我們使用 ubuntu 的 Image 啟動 Container 後就很方便了,直接進入 Bash。所以問題來了,在一個 Container 中可以執行多個程式嗎?
答案是肯定的,那就是 sudo docker container exec
命令,如下圖:

從上圖可以看出,我們進入 Ubuntu 時,直接和 Shell 進行互動,所以可以非常方便地使用 ls
、 pwd
等命令,甚至可以使用 cat /etc/os-release
命令檢視系統的版本資訊。當然,還可以使用 apt
安裝軟體。而要想進入 SpaceVim 所在的容器,就需要使用 sudo docker container exec -i spacevim-1.0 bash
命令再啟動一個 Shell,這樣就可以使用 ls
命令看到我們剛才編輯的 test.c
和 test.py
了。甚至可以使用 ps
命令檢視該容器中執行的程序。
Docker 的學習資源
Docker 的官網就別看了,難受。買書呢?費錢!還不一定能找到優秀的。最好的辦法就是檢視 Docker 的手冊頁啦。使用 sudo dpkg -L docker.io
命令,可以看到系統中安裝了好多手冊頁,如下圖:

如果輸入 man docker
,就是下面這樣:

如果輸入 man docker run
,就是下面這樣:

如果想自己寫 Dockfile,就輸入 man Dockfile
。我就不繼續截圖了。每一個手冊頁都可以從頭讀到尾,這種流暢的感覺是在 Docker 的官網上檢視文件體會不到的。
下一個問題:我們可以把我們的 Container 再打包帶走嗎?
執行一個 Container 後,我們可以在上面編輯檔案、更改配置,還可以按需安裝軟體。做了很多工作後,我們可以把這個 Container 打包帶走嗎?當然可以了,使用 sudo docker container commit
命令可以基於一個 Container 再建立一個映象。然後使用 sudo docker push
命令就可以把這個映象再上傳到 dockerhub 上了。當然,這只是理想狀態,畢竟有牆的存在,而且 dockerhub 要註冊後才能上傳映象。所以上傳這個事就不是那麼好做啊。
不過沒關係,我們可以打包用 U 盤帶走。 sudo docker image save
命令可以把 Image 匯出為本地檔案。使用 U 盤帶走後,使用 sudo docker image load
命令可以從這個檔案再匯入映象。
下一個問題:Docker 中的程式可以訪問我們主機上的所有硬體資源嗎?
其實我關心的是顯示卡。在我的上上篇隨筆中,我寫到了使用 CUDA 加速計算,而 CUDA 需要 Nvidia 的顯示卡支援。如果我要用 Docker 構建一個 CUDA 的開發環境,那就需要我 Docker 中的程式能夠訪問主機的顯示卡資源。從理論上講,這是可以的。畢竟 Docker 不同於虛擬機器,Docker 是和主機共享核心的,而 Nvidia 的驅動,只是一個核心模組。於是,我在使用 Ubuntu 映象的 Container 中測試了一下。使用 lsmod
命令檢視核心模組,發現它確實是使用的 Nvidia 的驅動,如下圖:

另外,使用 sudo aptitude install nvidia-cuda-toolkit
安裝 cuda-toolkit,也是可以安裝的。因此,證明 Docker 中的程式可以訪問主機上的所有硬體資源。使用 Docker 構建我們自己的開發環境不是夢。
最後一個問題:Docker 中能執行 GUI 程式嗎?
答案是可以。
先來分析一下思路。在 Docker 中執行控制檯程式時,我們需要給程式一個標準輸入輸出,就可以和程式互動了。在 Docker 中執行 Web 服務時,我們需要給程式一個 IP 和埠,就可以和服務互動了。GUI 程式需要什麼呢?它們需要一個 X Server 的 Display。我們給它就行了。
DISPLAY的格式是 unix:埠
或 主機名:埠
,前一種格式表示使用本地的 unix 套接字,後一種表示使用 tcp 套接字。預設情況下,X11的服務端會監聽本地的 unix:0
埠,而 DISPLAY 的預設值為 :0
,這實際上是 unit:0
的簡寫。因此如果在 Linux 的控制檯啟動一個圖形程式,它就會出現在當前主機的顯示螢幕中。
而 unix 套接字就是一個檔案,所以,可以使用 -v
引數,將主機的 unix 套接字共享到 Container 中,然後,執行在 Container 中的 GUI 程式,就會出現在主機的螢幕上。
其實早在2015年的“Docker全球開發者大會”上,Docker 自家的美女程式設計師“傑西·弗萊澤爾(Jessie Frazelle)”就展示了一系列黑魔法一樣的映象。這些映象中的大多數都使用了圖形介面。比如,她使用這樣的命令 docker run -d -v /tmp/.X11-unix:/tmp/.X11-unix jess/libreoffice
在 Docker 中運行了 LibreOffice(這只是舉例,真要執行成功還有很多細節需要完善),其中最重要的引數就是 -v /tmp/.X11-unix:/tmp/.X11-unix
,也就是把主機的 unix 套接字對映到 Container 中。
OK,關於 Docker,今天就寫這麼多。我感覺我又找到了新世界的大門。
版權申明
該隨筆由京山遊俠在2019年03月08日釋出於部落格園,引用請註明出處,轉載或出版請聯絡博主。QQ郵箱:[email protected]