天天看點

Day 21:Docker 入門教程

編者注:我們發現了有趣的系列文章 《30天學習30種新技術》 ,正在翻譯,一天一篇更新,年終禮包。下面是第 21 天的内容。

Day 21:Docker 入門教程
幾個月以前,紅帽(Red Hat)宣布了在 Docker 技術上和 dotCloud 建立 合作關系 。在那時候,我并沒有時間去學習關于 Docker 的知識,是以在今天,趁着這個 30 天的挑戰 ,我決定去學習一下 Docker 究竟是怎樣的。這篇博文并不是說以後怎麼在 OpenShift 上用 Docker 的。請閱讀由 Mike McGrath 撰寫的 " 關于 OpenShift 和 Docker 的技術思考 "。也可以看看這個 Stackoverflow 的問題 ,了解一下 Docker 和 OpenShift 的差别。

什麼是 Docker?

Docker

提供了一個可以運作你的應用程式的封套(envelope),或者說容器。它原本是 dotCloud 啟動的一個業餘項目,并在前些時候

開源了

。它吸引了大量的關注和讨論,導緻 dotCloud 把它重命名到 Docker Inc。它最初是用 Go 語言編寫的,它就相當于是加在 LXC(LinuX Containers,linux 容器)上的管道,允許開發者在更高層次的概念上工作。

Docker 擴充了 Linux 容器(Linux Containers),或着說 LXC,通過一個高層次的 API 為程序單獨提供了一個輕量級的虛拟環境。Docker 利用了 LXC, cgroups 和 Linux 自己的核心。和傳統的虛拟機不同的是,一個 Docker 容器并不包含一個單獨的作業系統,而是基于已有的基礎設施中作業系統提供的功能來運作的。這裡有一個

Stackoverflow 的答案

,裡面非常詳細清晰地描述了所有 Docker 不同于純粹的 LXC 的功能特性

Docker 會像一個可移植的容器引擎那樣工作。它把應用程式及所有程式的依賴環境打包到一個虛拟容器中,這個虛拟容器可以運作在任何一種 Linux 伺服器上。這大大地提高了程式運作的靈活性和可移植性,無論需不需要許可、是在公共雲還是私密雲、是不是裸機環境等等。

Docker 由下面這些組成:

1. Docker 伺服器守護程式(server daemon),用于管理所有的容器。

2. Docker 指令行用戶端,用于控制伺服器守護程式。

3. Docker 鏡像:查找和浏覽 docker 容器鏡像。它也通路這裡得到:

https://index.docker.io/

我為什麼要關心這些?

Docker 之是以有用,是因為把代碼從一個機器遷移到另一個機器經常是困難的。它嘗試去使得軟體遷移的過程變得更加可信和自動化。Docker 容器可以移植到所有支援運作 Docker 的作業系統上。

可以看這篇文章了解更多:

how the Fedora Project is embracing Docker

但是我已經在使用虛拟機(VMs)了

到現在為止,要把程式可靠地移植的唯一選擇是虛拟機(Virtual Machines,VMs)。虛拟機現在已經很常見了,但虛拟機是非常低級,它提供的是完整的作業系統環境。虛拟機的問題是,遷移的時候太大了。它們包含了大量類似硬體驅動、虛拟處理器、網絡接口等等并不需要的資訊。 虛拟機也需要比較長時間的啟動,同時也會消耗大量的記憶體、CPU 資源。

Docker 相比起來就非常輕量級了。運作起來就和一個正常程式差不多。這個容器不僅僅運作快,建立一個鏡像和制作檔案系統快照也很快。它可以在 EC2, RackSpace VMs 那樣的虛拟環境中運作。事實上,在 Mac 和 Windows 系統上使用 Docker 的更好方式是使用 Vagrant。Docker 的初衷其實是發揮類似 VM 的作用,但它啟動得更快和需要更少的資源。

它就像 Vagrant 一樣嗎?

我遇到的一個疑問是,我應該用 Vagrant 還是 Docker 去為我的下一個項目建立沙箱環境?答案再一次是一樣的。

Docker 比起 Vagrant 來說,運作起來會更加省資源。Vagrant 提供的環境其實是基于 Virtual Box 提供的虛拟機。可以閱讀 Stackoverflow 的

這個回答

了解更多。

噢,不是!另一個應用程式打包系統

當第一次讀到 Docker 打包應用程式時,我困惑了。我們為什麼需要再多一個應用打包系統(packaging system)?我早已經把我的 Java 程式打包成 JAR 或 WAR 了。在花了些時間閱讀了關于 Docker 的資料後,我明白了 Docker 應用包(application package)的含義。Docker 就是虛拟機和你的像 WAR 或 JAR 那樣的應用包之間的橋梁。一方面來說,虛拟機是非常重量級的(耗資源),因為移植時要附帶些不需要的東西。另一方面來說,應用代碼包(the application code packages)是非常的輕量的,并沒有附帶足夠可靠地運作起來的資訊。Docker 很好地平衡了這兩方面。

在 Docker 中,應用程式包(application package)意味着一個包含了應用程式代碼和所需部署環境的包。例如,在 Java 中我們一般把我們的 Web 應用程式打包在一個 WAR 檔案中。這個 WAR 檔案是一個非常簡約的軟體包,它僅僅包含了應用程式的代碼。但應用程式需要特定部署的環境去高效地運作起來。有時候部署的環境和開發時的環境是不同的。例如開發者使用 Java 7 開發程式,但部署時的環境是在 OpenJDK Java 6 中;又或者是在 Mac 上開發的,但在 RHEL 上部署。情況也有可能是:有一些系統庫(system libraries)在開發環境和模拟環境(staging environment)中,在不同的應用程式上有不同的效果。Docker 通過不僅僅打包應用程式,也打包應用程式的依賴環境來解決這個問題。

開始使用 Docker

在 Fedora 機器上使用這篇

博文

中的指令安裝 Docker

$ vagrant up

$ vagrant ssh

​​

然後安裝 Docker Fedora 鏡像:

$ sudo docker pull mattdm/fedora

上面的指令會從

上下載下傳 Docker Fedora 鏡像。

安裝了 Docker Fedora 鏡像後,我們可以使用下面指令列出所有的鏡像:

$ sudo docker images

REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE

shekhargulati/node_image_007   latest              e12b3054d981        50 minutes ago      470.3 MB (virtual 601.8 MB)

mattdm/fedora                         12.04               8dbd9e392a96        7 months ago        131.5 MB (virtual 131.5 MB)

上面清單中第一個鏡像就是我以前建立的。它打包了 NodeJS 及 Express Fremework。第二個鏡像就是存儲的 Docker Fedora 鏡像了。

現在,我們在 Docker 容器内運作一個腳本:

$ sudo docker run -t -i -p 3000 mattdm/fedora /bin/bash

在運作完上面的指令後,我們就在 Docker 的容器裡面了。我們可以通過

ls

指令列出所有的指令。

現在我們建立下面的目錄結構

/home/shekhar/dev

$ mkdir -p home/shekhar/dev

$ cd home/shekhar/dev

現在,我會安裝 NodeJS。運作下面的指令去在 Fedora Docker 鏡像上安裝 Node:

$ sudo yum install npm

接着,我們安裝 Express 架構:

$ npm install express -g

Express 架構安裝後,我們建立一個新的 Express 程式,然後運作它:

$ express myapp

$ cd myapp

$ npm install

$ node app.js

上面會在

3000

端口啟動 NodeJS Express 程式。

現在打開另一個指令行标簽,列出所有的 Docker 程序:

$ sudo docker ps

CONTAINER ID        IMAGE                                 COMMAND             CREATED             STATUS              PORTS                     NAMES

4a5715a915e5        mattdm/fedora   /bin/bash           5 minutes ago       Up 5 minutes        0.0.0.0:49157->3000/tcp   red_duck

你會注意到,

3000

端口和本機上的

49157

綁定了。你可以通過下面所示的

curl

指令測試 Express 應用:

$ curl 0.0.0.0:49157

<!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>Express</h1><p>Welcome to Express</p></body></html>

現在 commit 鏡像,然後 push 到 Docker 鏡像系統資料庫(registry)。在你做這步之前,你必須通過

https://index.docker.io/account/signup/

去注冊一個 Docker 系統資料庫。

$ sudo docker commit 4a5715a915e5 shekhargulati/node_image_007

$ sudo docker push shekhargulati/node_image_007

請使用你自己的使用者名和鏡像名。

是以,我的第一個鏡像已經上傳到 Docker 系統資料庫上面了:

https://index.docker.io/u/shekhargulati/node_image_007/

你可以使用

pull

指令下載下傳這個鏡像:

$ docker pull shekhargulati/node_image_007

這就是今天的内容。保持回報!