目錄

昨天介紹完了映像檔基礎的指令,當然還有一些特殊的指令,等到需要用到的時候會再做解釋,這邊就要來建置人生的第一個映像檔啦!

先麻煩大家到小弟我的 Github 去 Clone 這個檔案目錄到你的本機,若是不願意髒了你的本機也沒關係,可以用看地就好。

Git Clone Project
  • bash
1
2
3
4
5
6
7
8
$ git clone https://github.com/Robeeerto/docker-whoami.git
Cloning into 'docker-whoami'...
remote: Enumerating objects: 21, done.
remote: Counting objects: 100% (21/21), done.
remote: Compressing objects: 100% (15/15), done.
remote: Total 21 (delta 6), reused 17 (delta 5), pack-reused 0
Receiving objects: 100% (21/21), done.
Resolving deltas: 100% (6/6), done.

接著進入到資料夾裡面:

Directory Tree
  • bash
1
2
3
4
5
6
7
8
$ cd docker-whoami
.
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── README.md
├── whoami.rb

確保自己在這個資料夾內後,輸入以下的指令:

Docker Build Image
  • bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ docker image build --tag whoami .
[+] Building 37.1s (11/11) FINISHED
 => [internal] load build definition from Dockerfile                       0.0s
 => => transferring dockerfile: 529B                                       0.0s     
 => [internal] load .dockerignore                                          0.0s
 => => transferring context: 2B                                            0.0s
 => [internal] load metadata for docker.io/library/ruby:3.1.2-alpine       4.0s
 => [auth] library/ruby:pull token for registry-1.docker.io                0.0s
 => [1/5] FROM docker.io/library/ruby:[email protected]:499a31......     4.7s
 => => resolve docker.io/library/ruby:[email protected]:499a31......     0.0s
 => => sha256:e543eab4b71b99007ce154c6843c43bab8818efc18d0... 172B / 172B  0.3s
 => => sha256:499a310e8fab835ad47ab6251302aba1f5a5d0ded... 1.65kB / 1.65kB 0.0s
 => => sha256:7dcfcfa70588c4b81a6c81f47fcf6f58d486ae11f... 1.36kB / 1.36kB 0.0s
 => => sha256:6c65fdec191f877ffca756613f1e8acafb9f7258f... 6.10kB / 6.10kB 0.0s
 => => sha256:05c438b754fcec3ffc269d59394b0fa7cd82b09a.. 29.16MB / 29.16MB 0.0s
 => => extracting sha256:05c438b754fcec3ffc269d59394b0fa7cd82b09......     3.2s
 => => extracting sha256:e543eab4b71b99007ce154c6843c43bab8818ef......     1.2s
 => [internal] load build context                                          0.0s
 => => transferring context: 1.99kB                                        0.0s
 => [2/5] RUN apk add --update --no-cache     build-base     curl         10.6s
 => [3/5] WORKDIR /app                                                     0.1s
 => [4/5] COPY . .                                                         0.1s
 => [5/5] RUN gem install bundler:2.3.19 && bundle install...             15.5s
 => exporting to image                                                     1.9s
 => => exporting layers                                                    1.8s
 => => writing image sha256:7925639f0e50aa0da9d23674fb2bfb08970....        0.0s
 => => naming to docker.io/library/whoami                                  0.0s

接著就完成了人生的第一個映像檔了,可以測試一下這個映像檔到底可不可以使用,接著就拿出你們學習過啟動容器的方法來運行 whoami 這個映像檔啦!這邊就不再做示範了。

建置 Docker Image 的每個階段

但是單靠 build 出一個映像檔還是不夠,我們需要了解在建置映像檔的過程中到底發生了什麼事,以及該注意什麼才是重點。

從最一開始的指令來看:

Docker Build Image
  • bash
1
$ docker image build --tag whoami .

--tag 的作用就是給予要建置的映像檔標籤名的意思,而最後面有一個非常重要的 . ( 半形句號 ) 是常常會有人忽略而導致沒辦法建置映像檔的關鍵,這個 . ( 半形句號 ) 所代表的是『 這裡 』的意思,也就是 Docker 預設會在現在這個目錄中尋找 Dockerfile,並以其為主建置映像檔。

那如果我根據 staging、production 分別有好幾種不同的建置方式該怎麼做呢?Docker 則提供了 --file 的選項給你使用,例如我們想要建置的是 production 的映像檔,我們則可以這樣輸入:

Build Image With Different Dockerfile
  • bash
1
$ docker image build --tag whoami:production --file Dockerfile.production . #不換行

要記得,最後那個 . ( 半形句號 ) 還是要加上去,要讓 Docker 知道自己現在處於哪個路徑,當然也不侷限於 . ( 半形句號 ) 的使用,也可以指定 Dockerfile 存在的路徑,例如 ./docker/ 的相對路徑,總之不要讓 Docker 迷路了,它會不知道自己在哪。

接著根據整個建置映像檔的紀錄來看,呼應到我們前面所說的,第一個階段是從 FROM 這個指令開始,因為本地端沒有 ruby:3.1.2-alpine 這個映像檔的關係,就從 DockerHub 上面抓了官方的映像檔作為基底。

至於 Dockerfile 中的第二個動作應該是 ENV 為首的指令,為什麼沒有出現在建置過程中的紀錄中呢?這是因為 ENV 為首的指令雖然製造出了一層映像層 ( 空的,0 KB ),但由於其本身的指令並不會對檔案系統有更動,故沒有出現在建置過程中的紀錄上。

這邊再提一個小重點,Dockerfile 中的每一次指令都會製造一個新的映像層,至於會不會出現在建置的紀錄中端看這個指令對於檔案系統是否有更動,例如安裝套件、新增資料夾等等的動作,都會出現在建置的紀錄中;反之,如 EXPOSE 這樣的指令就沒有出現在建置的紀錄中,因為其並沒有對檔案系統有任何的更動。

而利用之前提過的 docker image history 可以看到映像檔的所有映像層,而透過 docker image inspect 則可以看到映像檔的檔案系統層,有興趣的人可以自己去研究一下。

接著的二、三、四、五階段,都按照著 Dockerfile 的說明執行動作,所以我才說映像檔就是運行容器的說明書,只要寫好正確的步驟,就能夠保證應用程式順利地執行,是不是也開始感覺到 Docker 的魅力啦?

小結

今天建置了一個映像檔,也稍微解釋了一下每個階段做的事情,明天則會介紹關於建置過程中的快取機制。