再談 Docker Image

在上篇的 Docker 是什麼? 的介紹中我們知道了 Docker 三大元素,這篇就來講一下如何安裝及再談 Docker Image 吧 owo

如何安裝 Docker?

Mac 安裝 Docker

下載官方 Docker.dmg 安裝

Docker Desktop for Mac

透過 Homebrew 安裝

使用 brew 指令安裝

1
brew cask install docker

啟動 docker for mac

1
open /Applications/Docker.app

再談 Docker Image

上篇對於 Docker 三大元素的基本介紹有了一定的了解,接下來再來學習如何操作吧!

取得 Docker Image

可以使用 docker pull 指令從 Docker Hub 取得所需要的 Image。舉例下載一個 Ubuntu 12.04 作業系統的 Image。

1
2
3
4
5
6
7
8
9
10
11
12
sudo docker pull ubuntu:12.04
Password: //輸入密碼

12.04: Pulling from library/ubuntu
d8868e50ac4c: Pull complete
83251ac64627: Pull complete
589bba2f1b36: Pull complete
d62ecaceda39: Pull complete
6d93b41cfc6b: Pull complete
Digest: sha256:...
Status: Downloaded newer image for ubuntu:12.04
docker.io/library/ubuntu:12.04

完成後,即可隨時使用我們下載的這個 Image 了(讓這個 Image 執行 bash)

1
2
3
docker run -t -i ubuntu:12.04 /bin/bash

root@d7b639b8385a:/#

之後會再介紹這段指令的意思~

列出 Docker Image

使用 docker images 顯示本機已有的 Image

1
2
3
4
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest fce289e99eb9 12 months ago 1.84kB
ubuntu 12.04 5b117edd0b76 2 years ago 104MB

在終端機列出訊息中,可以看到幾段文字訊息

  • REPOSITORY:來自哪個 Registry
  • TAG:版本
  • IMAGE ID:Image 的 ID(唯一)
  • CREATED:建立時間
  • VIRTUAL SIZE:Image 檔案大小

題外話:可以看到 hello-world 的 TAG 是 latest,這代表著這個 Image 沒有設定 TAG,恩…

建立 Docker Image

修改別人的 Image 已建立新的 Image

首先,先把別人的 Image pull 下來並啟動 Container

1
2
3
4
5
6
7
8
9
10
11
12
13
14
docker run -t -i training/sinatra /bin/bash

Unable to find image 'training/sinatra:latest' locally
latest: Pulling from training/sinatra
Image docker.io/training/sinatra:latest uses outdated schema1 manifest format. Please upgrade to a schema2 image for better future compatibility. More information at https://docs.docker.com/registry/spec/deprecated-schema-v1/
a3ed95caeb02: Pull complete
6e71c809542e: Pull complete
d196a7609355: Pull complete
08f6dff5acea: Pull complete
ce65532003d0: Pull complete
54bcaa4d1a10: Pull complete
8572ad96f6e1: Pull complete
Digest: ...
Status: Downloaded newer image for training/sinatra:latest

稍微對這個別人的 Image 對點手腳,加個 gem install json 為例來試試

1
2
3
4
5
6
7
8
root@360d0440d1d4:/# gem install json

Fetching: json-2.3.0.gem (100%)
Building native extensions. This could take a while...
Successfully installed json-2.3.0
1 gem installed
Installing ri documentation for json-2.3.0...
Installing RDoc documentation for json-2.3.0...

安裝完成 gem install json 後,代表我們這個 Container 已經被改變了!按下 control+D 或 exit 跳出這個 Container!再透過 docker commit 指令來新增這個 commit

1
~ docker commit -m "Added json gem" -a "Chester" 7c61f457e695 chestertang/sinatra:v2

如果 docker ps 中沒有 container,那執行上方指令將會 Error response from daemon: No such container: 49d952a36c58,因此,可以試試看下以下指令來看擁有的 Container ID

1
docker ps -a

在這段指令中,指令分別代表的意思如下

  • -m "Added json gem":與 github commit 訊息一樣,後方的為這次 commit 的註解
  • -a "Chester":代表著是作者資訊
  • 7c61f457e695:Container ID,透過 docker ps / docker ps -a 取得
  • chestertang/sinatra:v2:v2 冒號前半段是 Repository 名稱(不能大寫),後半段是 TAG

再來看看 docker images 吧!

1
2
3
4
5
6
docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
chestertang/sinatra v2 3bae0e76683f 11 seconds ago 447MB
ubuntu 12.04 5b117edd0b76 2 years ago 104MB
training/sinatra latest 49d952a36c58 5 years ago 447MB

並且用剛剛新的 Images 來啟動 Container

1
2
3
docker run -t -i chestertang/sinatra:v2 /bin/bash

root@2f902d9238f5:/#

利用 Dockerfile 建立 Image

我們可以使用 docker build 來建立一個新的 Image。首先,需要建立一個 Dockerfile,裡面包含一些用來建立 Image 的指令。

新建一個資料夾和一個 Dockerfile

1
2
3
mkdir sinatra
cd sinatra
touch Dockerfile

開啟建立的 Dockerfile 並來透過 ubuntu 與安裝 Ruby 來安裝 sinatra

1
2
3
4
5
6
# This is a comment
FROM ubuntu:14.04
MAINTAINER Docker Chester <[email protected]>
RUN apt-get -qq update
RUN apt-get -qqy install ruby ruby-dev
RUN gem install sinatra

Dockerfile 的基本語法的思如下:

  • # 來表示註解
  • FROM 指令告訴 Docker 使用哪個 Image 作為基底
  • MAINTAINER 表示誰是這個 file 的維護者
  • RUN 開頭的指令會在建立中執行,比如在這裏使用 apt-get 來安裝 rubysinatra 套件

建立完成 Dockerfile 後可以使用 docker build 建立 Docker Image

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
28
29
30
31
32
33
docker build -t="chestertang/sinatra:v2" .

Uploading context 2.56 kB
Uploading context
Step 0 : FROM ubuntu:14.04
---> 99ec81b80c55
Step 1 : MAINTAINER Kate Smith <[email protected]>
---> Running in 7c5664a8a0c1
---> 2fa8ca4e2a13
Removing intermediate container 7c5664a8a0c1
Step 2 : RUN apt-get -qq update
---> Running in b07cc3fb4256
---> 50d21070ec0c
Removing intermediate container b07cc3fb4256
Step 3 : RUN apt-get -qqy install ruby ruby-dev
---> Running in a5b038dd127e
Selecting previously unselected package libasan0:amd64.
(Reading database ... 11518 files and directories currently installed.)
Preparing to unpack .../libasan0_4.8.2-19ubuntu1_amd64.deb ...
Setting up ruby (1:1.9.3.4) ...
Setting up ruby1.9.1 (1.9.3.484-2ubuntu1) ...
Processing triggers for libc-bin (2.19-0ubuntu6) ...
---> 2acb20f17878
Removing intermediate container a5b038dd127e
Step 4 : RUN gem install sinatra
---> Running in 5e9d0065c1f7
. . .
Successfully installed rack-protection-1.5.3
Successfully installed sinatra-1.4.5
4 gems installed
---> 324104cde6ad
Removing intermediate container 5e9d0065c1f7
Successfully built 324104cde6ad

其中 -t 標記添加 TAG,指定新的 Image 的使用者資訊。 “.” 是 Dockerfile 所在的路徑,也可以換成具體的 Dockerfile 的路徑。

Dockerfile 是設定專案必定使用的方式,這個將在之後的有更深入的一篇例子來實作

從本機匯入

要從本機匯入 Image,可以使用 OpenVZ 來建立(https://wiki.openvz.org/Download/template/precreated)

比如,先下載一個 ubuntu-14.04 的映像檔,之後使用以下命令匯入:

1
cat ubuntu-14.04-x86_64-minimal.tar.gz  |docker import - ubuntu:14.04

然後查看新匯入的 Docker Image

1
2
3
4
docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 14.04 05ac7c0b9383 17 seconds ago 215.5 MB

上傳 Docker Images

可以透過 docker push 指令,把自己建立的 Docker Image 分享上傳到 Repository 。例如,使用者在 Docker Hub 上完成註冊後,可以推送自己的 Docker Image 到 Repository 中。

1
2
3
4
5
6
7
docker push chestertang/sinatra

sudo docker push chestertang/sinatra

The push refers to a repository [chestertang/sinatra]
Sending image list
Pushing repository chestertang/sinatra

儲存和載入 Image

儲存 Image

如果要建立 Docker Image 到 local 檔案,可以使用 docker save 指令來儲存

1
2
3
4
5
6
docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 14.04 c4ff7513909d 5 weeks ago 225.4 MB

docker save -o ubuntu_14.04.tar ubuntu:14.04

載入映像檔

可以使用 docker load 從建立的 local 檔案再匯入到 local Image,例如:

1
docker load --input ubuntu_14.04.tar || docker load < ubuntu_14.04.tar

移除 local 端 Docker Image

如果要移除 local 端的 Docker Image,可以使用 docker rmi 命令。(注意:如果有 Container 是透過現在這個 Image 在執行的話,必須先將 Container 刪除完畢後才能刪除 Image)

先來列出有的 Container 與 Image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
83be203c6040 chestertang/sinatra:v2 "/bin/bash" 48 minutes ago Exited (0) 18 minutes ago elastic_hertz
2f902d9238f5 chestertang/sinatra:v2 "/bin/bash" 4 days ago Exited (130) 4 days ago confident_ritchie
d7b639b8385a ubuntu:12.04 "/bin/bash" 7 days ago Exited (127) 7 days ago dreamy_hypatia
1d8d58333b3d ubuntu:12.04 "/bin/bash" 7 days ago Exited (130) 7 days ago wizardly_morse
c9a19d3553c9 ubuntu:12.04 "/bin/bash" 7 days ago Exited (0) 7 days ago interesting_dubinsky
bcf468d00ca2 hello-world "/hello" 9 days ago Exited (0) 9 days ago inspiring_newton

docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
chestertang/sinatra v2 3bae0e76683f 7 days ago 447MB
ubuntu 14.04 6e4f1fe62ff1 5 weeks ago 197MB
hello-world latest fce289e99eb9 13 months ago 1.84kB
ubuntu 12.04 5b117edd0b76 2 years ago 104MB
joshhu/webdemo latest c58bf6158823 4 years ago 243MB
training/sinatra latest 49d952a36c58 5 years ago 447MB

來刪除 training/sinatra 這個 image

1
2
3
4
docker rmi training/sinatra

Untagged: training/sinatra:latest
Untagged: training/sinatra@sha256:...

如果如上所述,在被刪除的這個 Image 底下還有 Container 未被刪除就會出現以下訊息:

1
2
3
docker rmi fce289e99eb9

Error response from daemon: conflict: unable to delete fce289e99eb9 (must be forced) - image is being used by stopped container bcf468d00ca2

這時候就需要透過 docker rm 先去把底下的 Container 都刪除完畢完後,才能移除 Image!


資料來源