三十分鐘 Docker 新手入門

astaxie發表於2016-10-10

簡介

如果您是 Docker 新手請您花大約三十分鐘的時間來了解 Docker 相關的知識和內容。 Docker 與 Linux 息息相關,因此在閱讀本文件之前請您確保以下條件:

  1. 對 Linux 的命令列操作有一定了解,並且懂得一些基礎命令。
  2. 對 Linux 服務管理有一定的瞭解。
  3. 當閱讀完本文之後您可以瞭解什麼是 Docker、使用它有什麼好處、以及 Docker 具體的使用方法。

為什麼選擇 Docker?

  1. 相對於虛擬機器來說 Docker 有映象管理。
  2. 相對於虛擬機器來說更強大的遷移能力。
  3. 雲端計算的未來,再也不用受到環境 API 的限制。

安裝 Docker

Docker 的安裝十分簡單方便,如果您有 Linux 虛擬機器 VPS 可以直接參考 Docker 極速下載 執行如下指令碼來安裝 Docker:

user$ curl -sSL https://get.daocloud.io/docker | sh

在 Docker 安裝完成以後,國內的特殊網路環境會導致在構建 Docker 映象或者是抓取(pull)來自 Docker Hub 上的映象時會遇到連線問題,這時我們就需要使用 DaoCloud 加速器服務

  1. 註冊 DaoCloud 賬號,開啟控制檯進入加速服務。
  2. 在網頁的最下方有詳細的使用步驟請參考。

如果您使用的是 Windows 或 Mac 請您下載安裝 Boot2Docker。

這裡我推薦使用 Ubuntu Server 作業系統,無論是在裸機上還是虛擬機器上。

Hello World

這部分的程式碼來自 Docker 使用者指南,但是與使用者指南不同的是我們會描述更多的執行過程。

案例 1 啟動一個容器

root# docker run ubuntu:14.04 /bin/echo 'Hello world'
Hello world
  1. 注意操作 Docker 是需要許可權的,這裡使用 root 使用者操作,當然您也可以把 docker 加入自己的使用者。
  2. run 作為 Docker 的子命令來控制新建容器並且執行。Docker 命令雖然比較多,但是命令是分級來執行的,多參照 help 就會習慣。
  3. ubuntu:14.04 代表映象的名字和版本號,託管在 Docker Hub 上,如果本地沒有抓取過那麼執行命令的時候會自動從 Docker Hub 抓取。
  4. /bin/echo 為在容器內執行的程式(應用)。
  5. 'Hello world' 為程式執行的引數。

提示:Docker 在命令執行完畢後不會銷燬容器,但是狀態為變為 Exited。

從這句命令中我們可以看到 Docker 可以根據情況判斷映象存在的情況,在後文中會介紹映象的管理。同時 ubuntu:14.04 將會被載入到快取中,如果後面的映象構建依賴於它並不會花費額外的網路頻寬抓取,十分方便。

案例 2-1 以互動模式啟動一個容器

root# docker run -t -i ubuntu:14.04 /bin/bash
root@af8bae53bdd3:/#

與上面的案例不同的是這條命令帶有 -t 和 -i 選項,這兩個選項在這指的是:

-i, --interactive=false Keep STDIN open even if not attached
-t, --tty=false Allocate a pseudo-TTY

上面來自 docker help run 的輸出,help 命令是獲取文件幫助資訊最簡短而高效的途徑。本次啟動的程式是 bash,執行 bash 之後,容器會在互動的模式下啟動。當 bash 退出後就會停止執行。這就是 Docker 執行程式的最簡單方式。

提示:此程式執行完成之後,容器不會被銷燬,但是狀態為 Exited。此外對於以互動模式啟動的容器可以先按下 Ctrl+P 然後按下 Ctrl+Q 這樣的按鍵順序脫離(detach)一個容器,脫離後的容器狀態仍為 Up 並且程式會繼續在後臺執行,這時可以使用 attach 命令重新附到一個已經脫離的程式。

案例 2-2 檢視容器內的檔案以及容器本身

在上一個例子中如果容器沒有關閉通過如下命令可以看出:

root@33d90ffaf1ac:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@33d90ffaf1ac:/# pwd
/
root@33d90ffaf1ac:/#

Docker 中整個容器是一個 Linux 環境,ubuntu 映象的預設使用者為 root,預設工作目錄為根目錄。

root@33d90ffaf1ac:/# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  18172  3104 ?        Ss   08:50   0:00 /bin/bash
root        16  0.0  0.0  15572  2200 ?        R+   09:04   0:00 ps aux

容器中的程式相當簡潔,只有正在執行的兩個程式沒有其他任何程式。

並且 PID 號碼是獨立存在的,與宿主機完全沒有關係。

案例 3 檢視後臺執行容器的日誌資訊

root# sudo docker run -t -i -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
8b8aad0aa7670441f99ce88fbac021bfb9cb124e7de4417a00ed3c0ccc6cb203

在這個案例中加入了新的選項 -d,這個選項中可以讓 Docker 後臺執行程式。

如果我們檢視執行的結果:

root# docker logs 8b8aad0aa767
hello world
hello world
hello world

從上面的命令來看,使用 logs 能看到程式的輸出 log 過程,這樣對服務的除錯是非常有幫助的。如果容器沒有自己設定的名字很難快速準確的排程容器。

案例 4 快速準確的排程容器--給容器起名字

root# docker run -t -i -d --name helloubuntu ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
8b8aad0aa7670441f99ce88fbac021bfb9cb124e7de4417a00ed3c0ccc6cb203

上面的命令跟之前案例中的命令對比多了一個 --name 選項給排程容器帶來了很多方便,使用者可以自己設定容器的名字,當然如果未指定名字系統會自動起一個隨機的名字給容器。那麼我們檢視 logs 的時候就可以通過命令 docker logs helloubuntu 來檢視日誌資訊了。

注意:容器名必須以英文字母和數字開頭,並且只能包含英文數字、下劃線 _、小數點 .、和減號 -。

案例 5 列出所有正在執行的容器和它們的基本資訊

root# docker ps -a
CONTAINER ID  IMAGE         COMMAND  CREATED     STATUS      PORTS  NAMES
53d90769be11  ubuntu:14.04  [...]    2 min ago   Up 2 min           helloubuntu
8b8aad0aa767  ubuntu:14.04  [...]    14 min ago  Up 14 min          dreamy_fermat
deaaa8e60c9f  ubuntu:14.04  [...]    14 min ago  Up 1 sec           distracted_darwin
33d90ffaf1ac  ubuntu:14.04  [...]    26 min ago  Exited (0)         tender_franklin

注意:由於文件寬度關係,樣例中有些內容被縮寫以方便展示。

# docker ps -a 這個命令中我們可以看到容器的 ID、使用的映象、啟動的命令、建立的時間、當前狀態、埠對映狀態和名字。

案例 6 容器管理

以下管理命令都可以通過傳入容器的 ID 或者名字來管理指定的容器:

  • stop 停止一個正在執行的容器。
  • start 執行一個正在停止的容器。
  • restart 重啟一個容器。
  • rm 刪除一個容器。

傳入多個 ID 或者名字可以操作多個容器。例如:docker rm name1 name2 可以同時刪除兩個容器。

提示:如果要刪除所有容器 docker rm $(docker ps -q -a)。

階段總結

當您看到這裡的時候可以說對 Docker 已經有了初步的操作能力,包括執行容器中的程式、檢視容器內容、執行容器、停止容器、檢視容器、重啟容器和刪除容器。但是距離在 Docker 上執行自己的業務或者組織開發還是有一定距離的。接下來我們開始進階學習,重點研究一下 Docker 操作的組成要素。

Docker 組成要素

如果將輪船拉著集裝箱執行在大海上,與 Docker 執行容器裡面的程式類比:

  • Linux 相當於大海,有不同的海洋氣候各有不同。
  • Docker 相當於能行駛在各種大海上的輪船,容器相當於各種規格的集裝箱。
  • Docker 內的系統相當於貨物的包裝。
  • 目標程式則相當於貨物。

當您看完上面的描述之後可以瞭解到每一種角色不同的作用以及所處的位置有所瞭解。

當然理論上的 Docker 只是一個輪船圖紙,必須得有一個守護程式才能執行。

映象也是一樣,它只是集裝箱的圖紙,需要在 Docker 中執行容器。

通過 Docker 執行您的 Web 應用,Step By Step

程式碼檔案請參考: DaoCloud 搭建靜態部落格 以及 整個研究過程參考

Step 1:準備自己的網際網路應用 - 參考檔案中的 static 這個檔案為編譯好的 golang 應用程式。

Step 2:準備 Linux RootFS - 參考檔案中的 root.fs 為打包好的 BusyBox。

Step 3:準備 Dockerfile:

# 從一個空映象中開始建立,沒有任何依賴。
FROM scratch
MAINTAINER DaoCloud <example@daocloud.io>

# 給 Docker 檔案系統中新增根目錄,也是 Linux 的一些基礎目錄。
ADD ./rootfs.tar /

# 給映象新增工作目錄 /app
RUN mkdir -p /app

# 設定預設工作路徑
WORKDIR /app

# 複製應用進入到映象中
COPY ./static /app

# 複製應用依賴的靜態檔案目錄
COPY ./public /public

# 對外開放的服務介面為 8080
EXPOSE 8080

# 容器執行時預設呼叫的啟動命令
CMD ["/app/static"]

Step4:構建映象 - sudo docker build -t [標籤] . 注意:最後有一個點 . 表示構建時的當前目錄。

Step5:執行映象 - 這一步就不贅述了,請參閱最開始的一個章節。

這裡重點講解一下第三步中 Dockerfile 的格式。參照 Dockerfile 中的註釋。

關於 Dockerfile 內部的指令的教程網上雖然很多,但是坑也不少。首先要注意,構建用的依賴檔案都要放到同一個目錄中,為了安全和可移植性儘量不要用到目錄之外的檔案。

COPY 或者 ADD 的目的地址比如說上面的 /app/ 與 /public 意義不同,第一個是複製檔案到 app 下,第二個是複製目錄到根名字叫 public。

為了更詳細的介紹 Dockerfile 新增一個額外的案例:

FROM node:slim

MAINTAINER DaoCloud <example@daocloud.io>

RUN apt-get update \
    && apt-get install -y git ssh-client ca-certificates --no-install-recommends \
    && rm -r /var/lib/apt/lists/*

RUN echo "Asia/Shanghai" > /etc/timezone \
    && dpkg-reconfigure -f noninteractive tzdata

RUN npm install hexo@3.0.0 -g

RUN mkdir /hexo
WORKDIR /hexo

EXPOSE 4000

CMD ["/bin/bash"]

在這個 Dockerfile 中:

FROM node:slim 表示構建的時候依賴於 Node.js 系統,並標明瞭標籤為 slim,但是沒標明也不需要標明的是 node 依賴於 Debian,這是使用者自己需要了解的,下一步就開始執行,當開始構建時是可以執行 Dockerfile 中的指令碼的。

第一個 RUN:後面標記的是需要讓 Debian 更新源並且安裝一系列的軟體,最後清空無用快取。

第二個 RUN:設定時區。

第三個 RUN:安裝 Hexo 部落格系統。

最後新建目錄設定工作目錄開放 4000 埠上文中已經提過。

在補充的這個例子中我們可以清楚的看到構建自己的映象可以依賴於其他映象構建環境基本上都已經準備好了,非常方便。第二個例子是構建 Hexo 部落格環境的做法。

管理 Docker 映象

拿來主義:pull(抓取)

第一種是直接抓取比如說下載一個 docker 管理用的 dockerui 工具,我們可以直接告訴 docker pull 回來:

root# docker pull dockerui/dockerui

也可以通過執行的方式來抓回映象:

root# docker run -d -p 9000:9000 --privileged \
        -v /var/run/docker.sock:/var/run/docker.sock dockerui/dockerui

這樣用直接訪問 http://localhost:9000/ 的方法來管理 docker 了。

檢視自己所有的映象

root# docker images
REPOSITORY          TAG      IMAGE ID       CREATED        VIRTUAL SIZE
hexo3               latest   66f7fc371b44   9 days ago     261.5 MB
node                slim     84326d4c0101   11 days ago    164.5 MB
dockerui/dockerui   latest   9ac79962b9b0   2 weeks ago    5.422 MB
busybox             latest   8c2e06607696   7 weeks ago    2.433 MB
garland/butterfly   latest   114f9c134231   3 months ago   394.5 MB
progrium/busybox    latest   8cee90767cfe   4 months ago   4.789 MB

搜尋需要的映象

推薦到 Docker Hub Registry 上搜尋。

但是也可以通過命令 docker search 關鍵詞 進行搜尋。

清空所有當前映象

使用命令:docker rmi $(docker images -q)

如果當前已經沒有映象了命令會報錯找不到映象。

警告:請謹慎清空所有映象。

構建映象的快取

在構建映象時 Dockerfile 中的指令會進入快取,如果構建時可以使用快取,docker 可以做到快速完成構建。

Docker 資料卷的掛載與外部服務訪問

首先要注意的一點:容器被刪除后里面的資料會被刪除,因此要注意掛載資料卷使資料持久化。

因此這裡介紹一下掛載宿主機中的目錄作為資料捲到 Docker 中的方法:

root# docker run -it -d -p 4000:4000 -v /root/blog/:/hexo --name hexo hexo3 這是上一個案例中執行 Hexo 部落格的方法,注意掛載描述在 -v 之後,容器中就可以訪問到宿主機中的持久化位置了。

注意,在資料庫應用中最需要根據配置檔案將資料庫持久化的位置放到宿主機中。

對於開發更加詳細的意見可以產考 使用 Docker 做開發的建議團隊工作流

為了使 Hexo 部落格可以被宿主機以外的裝置訪問,這裡使用 -p 引數來發布 Docker 的埠到宿主機中。

Docker 學習建議:

  1. 在詳細實踐完成本文之後如果您有精力,並且英文閱讀能力還不錯請您移步到 Docker官方文件 繼續更深入的學習。
  2. Docker 只是一種非常實用的工具,不要以 Docker 為目的去學習 Docker,重要的不是 Docker 而是您用 Docker 做什麼。

總結

由於篇幅有限新手教程就到這裡,希望您在這半個小時到一個小時中能有一次非常完美的 Docker 學習體驗,在接下來的學習中您還可以繼續從 Docker 官方的文件中瞭解更多的 Docker 相關的資訊,尤其是 Docker 容器與容器之間的問題解決,以及更多更加豐富的命令引數使用,比如環境變數的控制。

相信做完這部分實踐之後您已經瞭解了 Docker 能夠做什麼,如何進行基礎方面的使用。在下一篇中我們會 根據您現有的基礎介紹如何使用 DaoCloud 各項服務。

在接下來的學習中,如果需要請您學習使用版本控制工具 Git,及其相關基礎知識。

相關文章