輕松上手Docker,讓博客Docker化

jopen 8年前發布 | 17K 次閱讀 Docker

Docker是一個有趣的技術,在過去的兩年已經從一個變成了全世界的機構都在使用來部署應用的技術。在今天的文章中我將會討論如何通過Docker化一個現有應用來上手Docker。那這里選取的應用就是我的博客。

什么是Docker

在我們開始學習Docker的基礎之前讓我們首先理解什么是Docker并且為什么其那么流行。Docker是一個操作系統容器管理工具,通過將他們打包進一個操作系統容器中,能讓你輕松管理和部署應用。

容器 vs. 虛擬機

容器可能部署虛擬機一樣為人所熟悉,但是他們是另外一個方法來提供 操作系統虛擬化 的方法。然而,他們與標準的虛擬機有很大的差異。

標準的虛擬機通常包含一個完整的操作系統,操作系統軟件包,最后包含一兩個應用。這是通過一個向虛擬機提供了硬件虛擬化Hypervisor里達成的。這允許一單個服務器運行很多獨立的操作系統,以虛擬游客的身份。

容器與虛擬機類似之處在于他們允許一個單個服務器來運行多個操作系統的環境,這些環境然而不是完整的操作系統。容器通常只包含必要的OS軟件包和應用。他們通常不包含一個完整的操作系統或者硬件虛擬化。這也意味著相比虛擬機,容器的額外開銷更小。

容器和虛擬機通常被視為互相通途的技術,然而這通常是一個誤解。虛擬即使一個方法讓一個物理的服務器提供完全功能運轉的操作系統環境可以和其他虛擬機一起共享這些物理資源。一個容器通常是用來對單一主機的一個進程進行隔離來保證隔離的進程無法與處于同一個系統的其他進程進行互動。實際上,比起完全的虛擬機,容器與BSD的Jail,chroot過的進程更加類似。

在容器的基礎上Docker提供了什么

Docker自身不是一個容器的運行時環境;實際上Docker實際上是一種容器技術,類似于Solaris Zones和BSD Jails。Docker提供的是一個管理,打包和部署容器的方法。盡管這些類型的功能已經某一種成都的存在于虛擬機中,他們傳統上并不是為了絕多數的容器方案而存在的,而存在卻不如Docker一樣容易使用且功能完善。

現在我們知道了Docker是什么,讓我們開始通過安裝Docker并且部署一個公共的預先構建好的容器來學習Docker是怎么工作的。

從安裝開始

因為Docker不會默認安裝好,第一步就是安裝Docker軟件包;因為我們實例中使用額操作系統是Ubuntu 14.04,我們將會使用Apt包管理工具:

# apt-get install docker.io

Reading package lists... Done

Building dependency tree

Reading state information... Done

The following extra packages will be installed:

aufs-tools cgroup-lite git git-man liberror-perl

Suggested packages:

btrfs-tools debootstrap lxc rinse git-daemon-run git-daemon-sysvinit git-doc

git-el git-email git-gui gitk gitweb git-arch git-bzr git-cvs git-mediawiki

git-svn

The following NEW packages will be installed:

aufs-tools cgroup-lite docker.io git git-man liberror-perl

0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.

Need to get 7,553 kB of archives.

After this operation, 46.6 MB of additional disk space will be used.

Do you want to continue? [Y/n] y</pre>

要檢查是否有容器運行我們可以執行 docker 命令,然后使用 ps 選項:

docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

docker 命令的 ps 功能類似于Linux的 ps 命令。它將會顯示可用的Dokcer容器和他們的當前狀態。應為我們沒有啟動任何的Docker容器,命令顯示沒有任何的正在運行的容器。

部署一個預構建好的nginx Docker容器

我最喜歡的一個Docker特性其可有讓你用 yum 或者 apt-get 部署一個軟件包一樣的方式來部署一個預先構建好容器的能力。為了更好的說明這一點,讓我們來部署一個預先構建好的運行nginx服務器的容器。我們可以通過執行docker命令,但是這一次,我們使用的是 run 選項。

docker run -d nginx

Unable to find image 'nginx' locally

Pulling repository nginx

5c82215b03d1: Download complete 

e2a4fb18da48: Download complete 

58016a5acc80: Download complete 

657abfa43d82: Download complete 

dcb2fe003d16: Download complete 

c79a417d7c6f: Download complete 

abb90243122c: Download complete 

d6137c9e2964: Download complete 

85e566ddc7ef: Download complete 

69f100eb42b5: Download complete 

cd720b803060: Download complete 

7cc81e9a118a: Download complete 

docker 命令的 run 功能告訴Docker來找一個指定的Docker鏡像,并且啟動一個運行該鏡像的容器。默認情況下,Docker容器會在前臺運行,意味這當你執行 docker run 你的shell會綁定到這個容器的console和在容器里面運行的進程。為了在將這個Docker容器在后臺啟動,我包含了一個 -d (detach,脫離)的標記。

現在再次運行 docker ps ,我們可以看到正在運行的nginx容器:

docker ps

CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS            NAMES

f6d31ab01fc9        nginx:latest        nginx -g 'daemon off   4 seconds ago       Up 3 seconds        443/tcp, 80/tcp     desperate_lalande 

在上面的輸出中,我們可以看到運行中的容器 desperate_lalande ,并且該容器是從鏡像 nginx:latest 構建而來。

Docker鏡像

鏡像是Docker的核心特性之一,并且與虛擬機的鏡像很類似。跟虛擬機的鏡像類似的是,一個Docker鏡像是一個保存好并且打包好的容器。然而Docker,并不止步于鏡像創建。Docker也包含了通過Docker倉庫分發這些鏡像的能力,這個概念與軟件包倉庫類似。正是這給了Docker可以如同用yum來部署一個軟件包一樣來部署容器的能力。為了更好的理解這如何工作的,讓我們再看看docker run的輸出:

docker run -d nginx

Unable to find image 'nginx' locally

第一條消息我們可以看到 docker 不能在本地找到一個名為nginx的鏡像。我們之所以看到這個消息是因為當我們執行 docker run 的時候我們告訴Docker啟動一個容器,一個基于名為nginx鏡像的容器。因為Docker正在啟動一個基于特定鏡像的容器,它需要首先找到這個鏡像。在檢查遠端的倉庫之前,Docker首先檢查是否本地已經存在有一個該特定名稱的鏡像。

因為我們的系統是全新的,沒有一個名為nginx的Docker鏡像,這意味著Docker需要在Docker倉庫里面下載:

Pulling repository nginx

5c82215b03d1: Download complete

e2a4fb18da48: Download complete

58016a5acc80: Download complete

657abfa43d82: Download complete

dcb2fe003d16: Download complete

c79a417d7c6f: Download complete

abb90243122c: Download complete

d6137c9e2964: Download complete

85e566ddc7ef: Download complete

69f100eb42b5: Download complete

cd720b803060: Download complete

7cc81e9a118a: Download complete </pre>

這正如輸出的第二部分所顯示的一樣。默認情況下,Docker使用Docker Hub倉庫,這是由Docker公司運行的倉庫服務。

如Github一樣,Docker Hub對于公共的倉庫免費,但是對于私有倉庫需要付費。然而,你也可以部署你自己的Docker倉庫,實際上這只是運行 docker run registry 這么簡單。在這篇文章中,我們不會部署一個自己的注冊表服務(registry service)。

停止和移除鏡像

在我們開始構建一個自己的Docker容器之前,讓我們首先清理我們的Docker環境。我們需要停止之前啟動的容器并且移除它。

要啟動一個Docker容器我們執行 docker 命令并且使用 run 命令選項,要停止這個已啟動的鏡像我們只需要執行 docker 命令并使用 kill 選項并指定該容器的名稱。

# docker kill desperate_lalande

desperate_lalande</pre>

如果我們再次執行 docker ps 我們看到容器沒有運行了。

docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

然而在這一刻,我們僅僅停止了這個容器,盡管它沒有運行了,但是它還是存在的。默認情況下 docker ps 值會顯示運行中的容器,如果我們添加了 -a (all,所有)標志,它就會顯示所有不管是否運行與否的容器。

docker ps -a

CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS                           PORTS               NAMES

f6d31ab01fc9        5c82215b03d1        nginx -g 'daemon off   4 weeks ago         Exited (-1) About a minute ago                       desperate_lalande  

要完全的移除該容器,我們可以使用 docker 命令并且使用 rm 命令選項。

docker rm desperate_lalande

desperate_lalande

盡管這個容器已經被移除了;我們仍然可以隨時使用nginx鏡像。我們想要重新運行 docker run -d nginx ,容器將會立即啟動而不需要再次拉取名叫nginx的鏡像。這是因為Docker已經在本地保存了一個備份。

要查看所有本地的鏡像我們可以是運行docker命令并且使用 image 選項。

docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

nginx               latest              9fab4090484a        5 days ago          132.8 MB

構建我們自己的自定義鏡像

到目前為止我們已經使用了一些基礎的Docker命令來啟動,停止和移除一個普通的預選構建好的鏡像。而為了Docker化這個博客,我們將要構建我們自己的Docker鏡像,這意味要創建一個Docker文件。

在絕大多數的虛擬機環境中,假如你想要創建一個機器的鏡像,你需要首先創建一個虛擬機,安裝好操作系統,安裝好應用程序,最后將其轉化成一個模板或者鏡像。然而,對于Docker來說,這些步驟都可以通過Dockerfile進行自動化。一個Dockerfile是一個可以向Docker提供構建指令的方式。在這一節中,我們將要創建一個可以用來部署本博客的自定義Dockerfile。

理解應用

在我們開始創建Dockerfile之前,我們需要首先理解要不是這個博客我們需要什么。

這個博客自身實際上是通過一個自己便寫的名為hamerkop的靜態網站生成器生成的一個靜態的HTML網頁。這個生成器非常的簡單,專門為這個博客編寫,湊合能用就行。這個博客的所有的代碼和源文件都能在公共的 Github倉庫 中訪問到。為了部署這個博客我們只需要從Github拿到該倉庫的內容,然后安裝Python和一些Python的模塊,并且執行 hamerkop 應用。要對外服務這些生成的內容我們需要使用nginx;這意味著我們也需要安裝好nginx。

到目前為止,我們的Dockerfile應該足夠簡單,但是就這些也足夠讓我們學到不少 Dockerfile語法 。要開始我們克隆Github倉庫代碼然后用最喜歡的編輯器來創建一個Dockerfile;我這里使用vi。

git clone https://github.com/madflojo/blog.git

Cloning into 'blog'...

remote: Counting objects: 622, done.

remote: Total 622 (delta 0), reused 0 (delta 0), pack-reused 622

Receiving objects: 100% (622/622), 14.80 MiB | 1.06 MiB/s, done.

Resolving deltas: 100% (242/242), done.

Checking connectivity... done.

cd blog/

vi Dockerfile

FROM - 繼承一個Docker鏡像

Dockerfile的第一條指令是FROM指令。這是用來將一個已經存在的Docker鏡像指定為基礎鏡像。這基本上為我們提供了繼承另一個Docker鏡像的方法。在這個情形下,我們將會從我們之前用到的nginx鏡像開始,如果我們想要從一個最原始的開始,我們可以通過指定 ubuntu:latest 使用 Ubuntu 鏡像。

## 本Dockerfile用來生成http://bencane.com一個實例

FROM nginx:latest

MAINTAINER Benjamin Cane <ben@bencane.com></pre>

除了FROM指令之外,我還包含了一個MAINTAINER指令,其是用來顯示Dockerfile的作者的。

因為Docker支持使用#來作為評論的標示,我將會使用這種語法來解釋Dockerfile的各個部分。

運行一個測試構建

因為我們繼承了nginx Docker鏡像,我們當前的Dockerfil也繼承了所有用來構建該nginx鏡像的所有指令。這意味著即使在這一刻,我們已經能從這個Dockerfile中構建出一個Docker鏡像并且用這個鏡像運行出一個容器。生成的鏡像基本上跟nginx鏡像一樣,但是我們現在就開始構建這個Dockerfile,之后還有幾次,以此來幫助解釋Docker的構建過程。

為了開始從一個Dockerfile中開始一個構建,我們可以簡單地執行 docker 命令并且使用 build 命令選項。

# docker build -t blog /root/blog

Sending build context to Docker daemon 23.6 MB

Sending build context to Docker daemon

Step 0 : FROM nginx:latest

---> 9fab4090484a

Step 1 : MAINTAINER Benjamin Cane <ben@bencane.com>

---> Running in c97f36450343

---> 60a44f78d194

Removing intermediate container c97f36450343

Successfully built 60a44f78d194</pre>

在上面的例子中,我們使用 -t (tag,標簽)標志來將這個鏡像貼上名為"blog"的標簽。這基本上讓我們可以對鏡像進行命令,假如不為鏡像指定一個標簽,這個鏡像就只能通過一個由Dokcer指定的鏡像ID(Image ID)來調用。在這個場景下,這鏡像ID是 60a44f78d194 ,正如我們在docker命令的成功構建消息中看到的一樣。

除了 -t 標志,我也指定了 /root/blog 目錄。這個目錄就是“構建目錄(build directory)”,這個目錄包含了Dockerfile和其他必要的構建這個容器的文件。

現在我們已經完成了一個成功的構建,讓我們開始對這個鏡像進行定制化。

使用 RUN 來執行apt-get

這個用來生成HTML頁面的靜態網站生成器是使用Python來編寫的,因此在Dockerfile中第一個自定義的任務是安裝Python。要安裝Python包,我們需要用到Apt包管理器,這意味著我們需要在Dockerfile中說明需要執行 apt-get update 和 apt-get install python-dev ;我們可以通過RUN指令來完成這一點。

## Dockerfile that generates an instance of http://bencane.com

FROM nginx:latest

MAINTAINER Benjamin Cane <ben@bencane.com></pre>

Install python and pip

RUN apt-get update

RUN apt-get install -y python-dev python-pip

在上面我們僅僅是運行RUN指令來告訴Docker當其構建這個鏡像的時候,它需要執行指定的apt-get命令。然而有意思的部分是,這些命令只會在這個容器的情景中才會值性。這意味著即使 python-dev 和 python-pip 安裝到了容器中,卻沒有安裝到主機中。或者更簡單的話說,在在容器中,pip是可以執行的,但是出了容器之外,pip命令是找不到的。

同樣重要的一點是,Docker的構建過程中是不接受用戶的輸入的。這意味這所有由RUN指令來執行的命令必須不藉由用戶輸入而完成。這給構建過程增加了一點復雜度,因為很多應用是需要用戶輸入的。在我們這個場景中,RUN所有執行的命令都不需要用戶輸入。

安裝Python模塊

現在Python安裝好了我們需要安裝一些Python模塊。要在Docker之外做這件事情,我們通常是使用pip命令并且引用在博客的倉庫中的一個名叫 requirements.txt 文件。在之前的一個步驟里,我們使用了git命令將博客的Github倉庫克隆到/root/blog目錄下;這個目錄也同時是我們創建Dockerfile的地方。這很重要,因為這意味著Git倉庫的內容能被Docker在構建過程中訪問到。

當執行構建的時候,Docker會將構建的情景設置成為一個指定的構建目錄。這意味該文件夾任何的文件以及子目錄中的文件都能被構建過程所使用,而處于該目錄之外(處于構建情景之外的),是不能被訪問到的。

要安裝必需的Python模塊,我們需要將requirements.txt文件從構建目錄拷貝到容器之中去。我們可以在Dockerfile中使用 COPY 指令。

## Dockerfile that generates an instance of http://bencane.com

FROM nginx:latest MAINTAINER Benjamin Cane <ben@bencane.com></pre>

Install python and pip

RUN apt-get update 

RUN apt-get install -y python-dev python-pip

Create a directory for required files

RUN mkdir -p /build/

Add requirements file and run pip

COPY requirements.txt /build/ 

RUN pip install -r /build/requirements.txt

在Dockerfile中我們添加了3個指定。第一個指令使用 RUNS 在容器中創建了一個 /build 目錄。這個目錄將用來拷貝任何所用來生成靜態HTML頁面所需的任何文件。第二個指令是COPY指令,用來將requirements.txt從構建目錄拷貝到容器中的/build目錄。第三個使用了RUN指令,用來執行pip命令;這會安裝所有在requirements.txt文件中指定的模塊。

COPY是一個當構建定制化的鏡像時需要理解的很重要的指令。沒有Dockerfile文件中指定復制文件,Docke鏡像就不會包含這個requirements.txt文件。在Docker容器一切都是被隔離的情況下,除非在Dockerfile中特別指定過,容器是不大可能包含所需的依賴的。

重新運行一個構建

現在我們有了一些可以讓Docker執行的定制化的任務了,讓我們來試著對這個blog鏡像進行另外一次構建。

docker build -t blog /root/blog

Sending build context to Docker daemon 19.52 MB

Sending build context to Docker daemon 

Step 0 : FROM nginx:latest

---> 9fab4090484a

Step 1 : MAINTAINER Benjamin Cane <ben@bencane.com>

---> Using cache

---> 8e0f1899d1eb

Step 2 : RUN apt-get update

---> Using cache

---> 78b36ef1a1a2

Step 3 : RUN apt-get install -y python-dev python-pip

---> Using cache

---> ef4f9382658a

Step 4 : RUN mkdir -p /build/

---> Running in bde05cf1e8fe

---> f4b66e09fa61

Removing intermediate container bde05cf1e8fe

Step 5 : COPY requirements.txt /build/

---> cef11c3fb97c

Removing intermediate container 9aa8ff43f4b0

Step 6 : RUN pip install -r /build/requirements.txt

---> Running in c50b15ddd8b1

Downloading/unpacking jinja2 (from -r /build/requirements.txt (line 1))

Downloading/unpacking PyYaml (from -r /build/requirements.txt (line 2))

<truncated to reduce noise>

Successfully installed jinja2 PyYaml mistune markdown MarkupSafe

Cleaning up...

---> abab55c20962

Removing intermediate container c50b15ddd8b1

Successfully built abab55c20962

從上面的構建輸出我們可以看到構建成功了,但是我們也可以看到另外一個有意思的消息; ---> Using cache (使用緩存)。這個消息告訴我們的是,Docker能夠在構建過程中使用他的構建緩存。

Docker構建緩存

當Dcoker構建一個鏡像的時候,它不會僅僅構建一個單一的鏡像;它實際上在整個構建過程中會構建出多個鏡像。實際上我們可以從以上的輸出看到,在每一步之后,Docker都創建了一個新的鏡像。

Step 5 : COPY requirements.txt /build/

---> cef11c3fb97c</pre>

上面片段中的最后一行實際上是Docker在告訴我們創建了一個新的鏡像,它通過輸出鏡像ID來告訴我們這一點;cef11c3fb97c。這個策略一個有用之處在于Docker能夠使用這些鏡像作為后續構建步驟的緩存。這很有用,因為它能讓Docker加快同樣容器的新構建的構建過程。如果仔細我們看上面的例子,我們可以發現Docker能夠使用一個已經緩存了的鏡像,而不是重新安裝python-dev和python-pip包。然而,因為Docker無法一個構建執行過mkdir命令,每一個后續的步驟都執行了。

Docker的構建緩存即是一個饋贈也是一個詛咒;這么說的原因是要使用緩存或者重新執行指令這個決定是在一個很狹窄的范圍做出的。比如,如果如果有對 requirements.txt 文件的更改,Docker會在構建過程中檢測到這個改動然后從那一點重新開始。然而執行 apt-get 命令卻情況不同。如果提供Python包的Apt倉庫包含了一個 python-pip 包更新的版本;Docker無法檢測到這個變化,然后簡單地使用緩存。這意味著可能我們安裝了軟件包的一個較老的版本。盡管這個對于 python-pip 軟件包來說這不是什么問題,如果安裝包緩存了一個包含已知漏洞的軟件包,那么就是一個問題。

介于這個原因,周期性的重新構建鏡像并且不使用Docker的緩存是有用的。你可以在執行一個Dcoker構建的時候制定 --no-cache=True 來禁用緩存。

部署blog的其余部分

當Python軟件包和模塊都安裝好后,現在我們應該拷貝必需的應用文件,然后運行 hamerkop 應用了。要完成這一步我們可以簡單地使用更多的 COPY 和 RUN 指令。

FROM nginx:latest

MAINTAINER Benjamin Cane <ben@bencane.com></pre>

安裝python和pip

RUN apt-get update

RUN apt-get install -y python-dev python-pip

創建一個文件夾放置必需文件

RUN mkdir -p /build/

添加依賴文件然后運行pip

COPY requirements.txt /build/

RUN pip install -r /build/requirements.txt

添加博客代碼和必需文件

COPY static /build/static

COPY templates /build/templates

COPY hamerkop /build/

COPY config.yml /build/

COPY articles /build/articles

運行生成器

RUN /build/hamerkop -c /build/config.yml

現在我們補上了其余的構建指令了,讓我們來再來一次構建并且驗證是否鏡像能夠構建成功。

docker build -t blog /root/blog/

Sending build context to Docker daemon 19.52 MB

Sending build context to Docker daemon 

Step 0 : FROM nginx:latest

---> 9fab4090484a

Step 1 : MAINTAINER Benjamin Cane <ben@bencane.com>

---> Using cache

---> 8e0f1899d1eb

Step 2 : RUN apt-get update

---> Using cache

---> 78b36ef1a1a2

Step 3 : RUN apt-get install -y python-dev python-pip

---> Using cache

---> ef4f9382658a

Step 4 : RUN mkdir -p /build/

---> Using cache

---> f4b66e09fa61

Step 5 : COPY requirements.txt /build/

---> Using cache

---> cef11c3fb97c

Step 6 : RUN pip install -r /build/requirements.txt

---> Using cache

---> abab55c20962

Step 7 : COPY static /build/static

---> 15cb91531038

Removing intermediate container d478b42b7906

Step 8 : COPY templates /build/templates

---> ecded5d1a52e

Removing intermediate container ac2390607e9f

Step 9 : COPY hamerkop /build/

---> 59efd1ca1771

Removing intermediate container b5fbf7e817b7

Step 10 : COPY config.yml /build/

---> bfa3db6c05b7

Removing intermediate container 1aebef300933

Step 11 : COPY articles /build/articles

---> 6b61cc9dde27

Removing intermediate container be78d0eb1213

Step 12 : RUN /build/hamerkop -c /build/config.yml

---> Running in fbc0b5e574c5

Successfully created file /usr/share/nginx/html//2011/06/25/checking-the-number-of-lwp-threads-in-linux

Successfully created file /usr/share/nginx/html//2011/06/checking-the-number-of-lwp-threads-in-linux

<truncated to reduce noise>

Successfully created file /usr/share/nginx/html//archive.html

Successfully created file /usr/share/nginx/html//sitemap.xml

---> 3b25263113e1

Removing intermediate container fbc0b5e574c5

Successfully built 3b25263113e1

運行一個定制化的容器

在成功構建后,我們現在可以通過運行docker命令并且使用 run 選項來啟我們的定制化的容器,就如我們之前運行nginx容易類似。

docker run -d -p 80:80 --name=blog blog

5f6c7a2217dcdc0da8af05225c4d1294e3e6bb28a41ea898a1c63fb821989ba1

與先前一樣, -d (脫離)標志是用來告訴Docker在后臺運行容器。然后我們這里也使用兩個新的標志。第一個標志是 --name ,這是用來給容器一個用戶指定名稱。在之前的例子里,我們沒有指定名稱,因此Docker隨機生成了一個名稱。第二個新出現的標志是 -p ,這個標志能讓用戶來將一個端口從主機機器映射到容器中的一個端口。

我們使用的nginx基礎鏡像暴露了80端口來提供HTTP服務。默認情況下,與Docker容器內部綁定的端口并沒有與主機系統綁定。為了讓外部的系統訪問容器內部暴露的端口,這些端口必須通過使用 -p 標志從主機端口映射到容器端口。假如我們想要端口從主機的8080端口,映射到容器中的80端口,我們可以通過使用這種語法 -p 8080:80 。

從上面的命令中,看起來我們的容器已經啟動成功了。我們可以通過運行執行 docker ps來驗證 。

{{{

docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

d264c7ef92bd blog:latest nginx -g 'daemon off 3 seconds ago Up 3 seconds 443/tcp, 0.0.0.0:80->80/tcp blog

{{{

總結

到這里,我們已經有了一個運行中的自定制的Docker容器。盡管這個文章中我們觸及到了不少的Dockerfile指令,我們還未能討論所有的指令。要獲取一個完整的指令列表你可以查看 Docker的手冊頁面 ,那里很好的解釋了每個指令。

另外一個很好的資源是 Docker最佳實踐 頁面,包含了不少的構建自定制Dockerfile最佳實踐。有些點子是分有用,比如策略性地在Dockerfile中安排指令的順序。在上面的例子中,我們的Dockerfile用到的COPY指令,被放在了最后。這么做的原因是,articles目錄會頻繁更改。最好將可能經常變動的指令放到最后,這樣可以優化Docker的緩存步驟。

在這個文章中我覆蓋了如何從一個預先構建好的容器開始,如何構建然后部署一個自定制的容器。盡管Docker要學習的內容還有很多,這篇文章會助你邁出第一步。

來自: http://dockone.io/article/961

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!