返回文章列表

容器映像檔建置執行與標籤設定

本文詳細說明如何建置、執行及為容器映像檔設定標籤,包含使用 Dockerfile 建立 Nginx 映像檔、設定埠對映、自訂 index.html 檔案,以及使用 docker tag 命令為映像檔加上標籤,方便後續管理與佈署。

容器技術 Web 開發

根據 Ubuntu 22.04 建立 Nginx 容器映像檔,首先需安裝必要的套件,並將自訂的 index.html 檔案複製到容器中,取代 Nginx 預設的網頁。透過埠對映,將容器的 80 埠對映到本機的不同埠,例如 8082、8083、8084 等,避免埠衝突。執行容器後,可使用 curl 指令測試網頁伺服器是否正常運作,並確認自訂的 index.html 內容是否正確顯示。為了方便管理容器映像檔,可以使用 docker tag 命令為映像檔加上標籤,例如 mynginx:01,取代複雜的映像檔 ID,簡化後續的 docker run 操作。文章最後提供一個練習,引導讀者使用 Apache HTTP 伺服器建立容器映像檔,並進行相關操作。

建構我們的首個容器映像檔

執行容器

在成功建立容器映像檔後,我們現在可以執行剛剛建立的容器。清單4-12展示瞭如何執行容器。

清單4-12. 執行我們剛剛建立的容器

docker run -d --name mynginx01 -p 8082:80 aed4ca1695a0

執行上述指令後,系統會回傳容器的ID:

10686bdb60fbb7b83622cd555b6b8cd4e0dfbf4574d7c8c088a26d8b1f2ea8ce

上述指令的語法與前一章節類別似:

  • -d:在背景執行容器。
  • --name:為容器命名,在此例中為mynginx01
  • -p 8082:80:將本機的8082埠對映到容器的80埠。
  • aed4ca1695a0:容器映像檔的ID,請記得替換成您自己的映像檔ID。

請注意,本機的8080和8081埠已經被佔用,而容器的80埠是我們在建立映像檔時暴露出來的。現在,我們可以使用docker ps指令來確認容器是否正在執行,如清單4-13所示。

清單4-13. 確認容器正在執行

docker ps

執行結果如下:

CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                  NAMES
10686bdb60fb   aed4ca1695a0   "/usr/sbin/nginx -g ..."   2 minutes ago   Up 2 minutes   0.0.0.0:8082->80/tcp   mynginx01

容器正在執行中,這與我們的預期相符。

測試我們的映像檔

為了測試我們的映像檔,我們只需像之前一樣使用curl指令存取localhost:8082,如清單4-14所示。

清單4-14. 測試nginx伺服器

curl localhost:8082

執行結果如下:

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<SNIP>
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

目前顯示的仍然是預設的index.html檔案,我們將很快用自訂的index.html檔案替換它。

將自訂的index.html納入映像檔

nginx的預設index.html檔案通常位於/var/www/html/index.nginx-debian.html。如果我們在建立映像檔的過程中替換這個檔案,我們自訂的index.html就會被納入映像檔中。清單4-15展示了更新後的Dockerfile。

清單4-15. 更新後的Dockerfile

FROM ubuntu:22.04
COPY ubuntupkgs/*.deb /tmp/
RUN dpkg -i /tmp/*.deb
RUN rm -rf /var/www/html/index.nginx-debian.html
COPY index.html /var/www/html/
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]
EXPOSE 80/tcp

我們新增了兩行指令:

  1. RUN rm -rf /var/www/html/index.nginx-debian.html:刪除預設的index.nginx-debian.html檔案。
  2. COPY index.html /var/www/html/:將我們自訂的index.html檔案複製到容器中的/var/www/html/目錄。

接著,我們可以使用docker build指令重新建立映像檔,如清單4-16所示。

清單4-16. 重新建立容器映像檔

docker build .

執行結果如下:

Sending build context to Docker daemon  1.968MB
Step 1/7 : FROM ubuntu:22.04
 
---
> 08d22c0ceb15
Step 2/7 : COPY ubuntupkgs/*.deb /tmp/
 
---
> Using cache
 
---
> 1bfeb9969945
Step 3/7 : RUN dpkg -i /tmp/*.deb
 
---
> Using cache
 
---
> 0feb1cd39cf6
Step 4/7 : RUN rm -rf /var/www/html/index.nginx-debian.html
 
---
> Using cache
 
---
> f1154c7b40a8
Step 5/7 : COPY index.html /var/www/html/
 
---
> 0b06c88e4552
Step 6/7 : ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]
 
---
> Running in 52a0f6c74a3b
Removing intermediate container 52a0f6c74a3b
 
---
> 623180dcc6a1
Step 7/7 : EXPOSE 80/tcp
 
---
> Running in 8be2c5e7e0e9
Removing intermediate container 8be2c5e7e0e9
 
---
> 390c89ba092d
Successfully built 390c89ba092d

請記下新的容器ID。接著,我們可以使用這個新的映像檔來啟動另一個容器,如清單4-17所示。這次,我們將本機的8083埠對映到容器的80埠。

清單4-17. 啟動更新後的容器映像檔

docker run -d --name mynginx02 -p 8083:80 390c89ba092d
curl localhost:8083

執行結果如下:

<html>
<title>My own container image </title>
<body>
Hello world!<br>
This is my index file embedded in my first container image!!<br>
</body>
</html>

現在,我們的自訂index.html已經成功地被納入容器映像檔中並且可以正常存取。

#### 內容解密:

  1. docker run指令引數解析

    • -d:使容器在背景執行。
    • --name:為容器指定名稱。
    • -p:進行埠對映,將主機埠與容器埠進行繫結。
  2. curl指令測試

    • 使用curl存取localhost對應的埠,驗證nginx伺服器是否正常執行。
  3. Dockerfile更新內容

    • RUN rm -rf /var/www/html/index.nginx-debian.html:刪除預設的index.html
    • COPY index.html /var/www/html/:將自訂的index.html複製到容器中。
  4. docker build指令

    • 根據更新後的Dockerfile重新建立映像檔。
  5. 連續整合(CI)概念

    • 透過自動化建立和測試容器映像檔,實作連續整合的基礎。

圖表翻譯:

此圖示展示了容器建立與執行的流程: 圖表翻譯: 此圖展示了從建立Dockerfile到測試容器服務的完整流程。首先,我們建立Dockerfile,接著執行docker build指令生成容器映像檔。然後,使用docker run指令啟動容器,最後測試容器中的服務是否正常執行。

為容器映像檔加上標籤

由於很難記住或使用映像檔ID,我們可以為容器映像檔加上友好的名稱,也就是標籤。在本文中,我們將為容器映像檔加上標籤。首先,我們需要使用docker images命令來查詢我們要標記的容器映像檔的IMAGE ID,如清單4-18所示。

清單4-18:顯示目前的容器映像檔列表

docker images
shiva@wks01:~/container-static-website$ docker images
REPOSITORY   TAG         IMAGE ID       CREATED         SIZE
<none>       <none>      390c89ba092d   11 minutes ago   86.1MB
<none>       <none>      aed4ca1695a0   38 minutes ago   86.1MB
ubuntu/nginx  latest      c1c59dacd1ed   4 weeks ago      140MB
ubuntu       22.04       08d22c0ceb15   4 weeks ago      77.8MB
ubuntu       latest      08d22c0ceb15   4 weeks ago      77.8MB
ubuntu       20.04       1c5c8d0b973a   4 weeks ago      72.8MB
hello-world  latest      feb5d9fea6a5   18 months ago    13.3kB
shiva@wks01:~/container-static-website$

內容解密:

此命令輸出了目前系統中的容器映像檔列表,包括映像檔的REPOSITORY、TAG、IMAGE ID、CREATED和SIZE等資訊。可以看到,我們剛剛建立的映像檔沒有REPOSITORY和TAG名稱,只有IMAGE ID。

使用IMAGE ID非常不方便,因此我們需要為容器映像檔加上標籤。標記映像檔的命令格式如下:

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

在我們的例子中,我們希望將IMAGE ID為390c89ba092d的映像檔標記為mynginx:01,因為這個映像檔包含了我們建立的nginx網頁伺服器,如清單4-19所示。

清單4-19:為容器映像檔加上標籤

docker tag 390c89ba092d mynginx:01
shiva@wks01:~/container-static-website$ docker tag 390c89ba092d mynginx:01
shiva@wks01:~/container-static-website$

內容解密:

此命令將IMAGE ID為390c89ba092d的映像檔標記為mynginx:01。這使得我們可以使用友好的名稱來操作容器映像檔。

然後,我們使用docker images命令來驗證標記結果,如清單4-20所示。

清單4-20:顯示加上標籤後的容器映像檔列表

docker images
shiva@wks01:~/container-static-website$ docker images
REPOSITORY   TAG         IMAGE ID       CREATED         SIZE
mynginx      01          390c89ba092d   13 minutes ago   86.1MB
<none>       <none>      aed4ca1695a0   40 minutes ago   86.1MB
ubuntu/nginx  latest      c1c59dacd1ed   4 weeks ago      140MB
ubuntu       22.04       08d22c0ceb15   4 weeks ago      77.8MB
ubuntu       latest      08d22c0ceb15   4 weeks ago      77.8MB
ubuntu       20.04       1c5c8d0b973a   4 weeks ago      72.8MB
hello-world  latest      feb5d9fea6a5   18 months ago    13.3kB
shiva@wks01:~/container-static-website$

內容解密:

現在,IMAGE ID為390c89ba092d的映像檔有了友好的名稱mynginx:01。我們可以使用這個名稱來啟動容器。

現在,我們可以使用新的名稱來啟動容器,如清單4-21所示。

清單4-21:啟動容器並將網頁伺服器對映到未使用的連線埠

docker run -d --name mynginx04 -p 8084:80 mynginx:01
shiva@wks01:~/container-static-website$ docker run -d --name mynginx04 -p 8084:80 mynginx:01
20d136c66141942f167a5f3cf24a3d30a68d0bc8559ab8ff17b1f788d16d3886
shiva@wks01:~/container-static-website$

內容解密:

此命令啟動了一個名為mynginx04的容器,並將容器的80連線埠對映到主機的8084連線埠。容器使用了我們剛剛建立的mynginx:01映像檔。

然後,我們可以使用docker ps命令來驗證容器是否成功啟動,如清單4-22所示。

清單4-22:確認容器成功啟動

docker ps
shiva@wks01:~/container-static-website$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS                    PORTS                                      NAMES
20d136c66141   mynginx:01     "/usr/sbin/nginx -g ..."   18 seconds ago   Up 17 seconds             0.0.0.0:8084->80/tcp, :::8084->80/tcp   mynginx04
9da0cfa8be22   390c89ba092d   "/usr/sbin/nginx -g ..."   15 minutes ago   Up 15 minutes             0.0.0.0:8083->80/tcp, :::8083->80/tcp   mynginx02
50231cd5dd48   aed4ca1695a0   "/usr/sbin/nginx -g ..."   22 minutes ago   Up 22 minutes             0.0.0.0:8082->80/tcp, :::8082->80/tcp   mynginx01
5e25f3c059ec   ubuntu/nginx:latest   "/docker-entrypoint...."   3 hours ago      Up 3 hours                0.0.0.0:8081->80/tcp, :::8081->80/tcp   nginx02
b51b6f4a5934   ubuntu/nginx:latest   "/docker-entrypoint...."   3 hours ago      Up 3 hours                0.0.0.0:8080->80/tcp, :::8080->80/tcp   nginx01
shiva@wks01:~/container-static-website$

內容解密:

此命令輸出了目前正在執行的容器列表。可以看到,我們剛剛啟動的容器mynginx04正在執行,並且網頁伺服器的80連線埠已經對映到主機的8084連線埠。

練習

與前面的練習類別似,請嘗試使用apache2/httpd伺服器建立自己的容器映像檔,使用自己的index.html,建立、發布和執行容器。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title 容器映像檔建置執行與標籤設定

package "Docker 架構" {
    actor "開發者" as dev

    package "Docker Engine" {
        component [Docker Daemon] as daemon
        component [Docker CLI] as cli
        component [REST API] as api
    }

    package "容器運行時" {
        component [containerd] as containerd
        component [runc] as runc
    }

    package "儲存" {
        database [Images] as images
        database [Volumes] as volumes
        database [Networks] as networks
    }

    cloud "Registry" as registry
}

dev --> cli : 命令操作
cli --> api : API 呼叫
api --> daemon : 處理請求
daemon --> containerd : 容器管理
containerd --> runc : 執行容器
daemon --> images : 映像檔管理
daemon --> registry : 拉取/推送
daemon --> volumes : 資料持久化
daemon --> networks : 網路配置

@enduml

圖表翻譯: 此圖表呈現了建立容器映像檔的流程。首先,我們需要建立容器映像檔(A),然後為容器映像檔加上標籤(B),接著啟動容器(C),最後驗證容器狀態(D)。這個流程展示了容器映像檔從建立到佈署的完整過程。