根據 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)概念

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

圖表翻譯:

此圖示展示了容器建立與執行的流程:

  graph LR
    A[建立Dockerfile] --> B[執行docker build指令]
    B --> C[生成容器映像檔]
    C --> D[執行docker run指令]
    D --> E[啟動容器]
    E --> F[測試容器服務]

圖表翻譯: 此圖展示了從建立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,建立、發布和執行容器。

  graph LR
    A[建立容器映像檔] --> B[為容器映像檔加上標籤]
    B --> C[啟動容器]
    C --> D[驗證容器狀態]

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