iT邦幫忙

2023 iThome 鐵人賽

0
Software Development

救救我啊我救我!CRUD 工程師的惡補日記系列 第 36

【Docker】將容器打包成映像檔並上傳

  • 分享至 

  • xImage
  •  

上一篇文章,我們在 MySQL 容器中放置 sql 檔,完成資料庫的初始化。而本文要介紹的,是將這種經過客製化的容器,轉換為映像檔,再上傳到 Docker Hub 共享。最後討論這道程序,能夠在多人開發上帶來什麼好處。


一、事前準備

本文將以 MySQL 為練習對象,請執行下面的指令,取得映像檔。

docker image pull mysql:8.2.0

隨後再建立出容器,但不需要啟動。

docker container create -p 3306:3306 --name SchoolMySQL -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=school mysql:8.2.0

以上的 MYSQL_DATABASE 參數,會建立名為「school」的資料庫。

接著請讀者事先準備一份用「mysqldump」備份出來的「.sql」檔。或者將以下的 SQL 腳本存為 sql 檔。目的是透過它來建立資料表,並插入一些初始資料。

CREATE DATABASE IF NOT EXISTS `school`;

CREATE TABLE `school`.`student` (
  `id` VARCHAR(20) NOT NULL,
  `studentId` VARCHAR(20) NOT NULL,
  `name` VARCHAR(20) NOT NULL,
  `birthday` DATE NOT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO `school`.`student`
VALUES("1", "10346000", "Vincent", "1996-01-01");

最後將 sql 檔放置在主機的某資料夾,再複製到 MySQL 容器的 /docker-entrypoint-initdb.d 路徑下,讓 MySQL 在初次啟動時執行。

docker container cp . SchoolMySQL:"/docker-entrypoint-initdb.d"

這時讀者可以啟動容器,並確認 MySQL 真的如預期地完成資料庫的初始化。後續再從容器中刪除該 SQL 腳本,原因後面會說。

以上的準備完成後,讓我們進入正題,開始建立映像檔。

二、以容器建立映像檔

(一)打包容器

在主機與容器之間,可以做資料的移入和移出,或者軟體本身也可能自行產生資料,我們視為容器已經經過「客製化」了。例如在上一節進行了資料庫內容的初始化。

那麼「將容器打包為映像檔」,指的就是以容器目前的狀態為基礎,來建立出新的映像檔。之後透過這個新映像檔來建立容器,其檔案系統的狀況均會與先前的相同,都具有那些客製化的部份。

附帶一提,第一節將初始化腳本從容器中刪除的原因,是避免使用新映像檔建立容器時,會重複執行。

以容器建立映像檔的 Docker 指令寫法為 docker container commit {容器 id | 容器名稱} {映像檔名稱}。範例指令如下:

docker container commit SchoolMySQL mysql-for-school-system

把容器打包成映像檔,能讓我們輕鬆建立出檔案系統處於相同狀態的容器,是個方便的功能。

(二)加上 Tag

如果映像檔沒有 tag,則預設為「latest」。為了區別映像檔的不同版本,可為其加上適當的 tag。

加 tag 的指令寫法為 docker image tag {映像檔 id | 映像檔名稱} {新映像檔名稱}:{tag}

這個指令除了給予 tag,同時也能重新命名映像檔。範例指令如下:

docker image tag mysql-for-school-system mysql-for-college-system:1.0.0

此處的 tag 名稱為「1.0.0」,可以自己取名。並且將映像檔改名為「mysql-for-college-system」。完成後,會看到新舊映像檔並存。

三、上傳映像檔

(一)取得帳號

準備好客製化的映像檔後,本節讓我們上傳到 Docker Hub。首先要請讀者註冊該平台的帳號。
dockerhub-homepage-indicate-signup.png
https://ithelp.ithome.com.tw/upload/images/20231206/20131107SYENKYxHlz.png

註冊後,可透過指令在 command line 登入,指令寫法為 docker logn --username {帳號},隨後再輸入密碼即可。

(二)上傳

要上傳的映像檔,其名稱必須包含帳號名稱。如果沒有,請重新命名。指令寫法為
docker image tag {映像檔 id | 映像檔名稱} {帳號}/{新映像檔名稱}:{tag}

範例指令如下:

docker image tag mysql-for-college-system your_username/mysql-for-college-system:1.0.0

如果已知映像檔是會被上傳的,那麼在前面「以容器建立映像檔」或「加上映像檔 tag」的階段,就可以將帳號名稱加上去了:

  • docker container commit {容器 id | 容器名稱} {帳號}/{映像檔名稱}:{tag}
  • docker image tag {映像檔 id | 映像檔名稱} {帳號}/{新映像檔名稱}:{tag}

而上傳的指令寫法為 docker image push {帳號}/{映像檔名稱}:{tag}。範例指令如下:

docker image push your_username/mysql-for-college-system:1.0.0

稍等一段時間,最後就可以在 Docker Hub 看到上傳完成的映像檔了。
dockerhub-repository-list.png
https://ithelp.ithome.com.tw/upload/images/20231206/20131107sWxhSdBjwB.png

當別臺電腦想取得這個映像檔,只要下個指令即可。

docker image pull {上傳者帳號}/mysql-for-college-system:1.0.0

四、在開發工作的應用

本文介紹如何上傳經過客製化後的映像檔,那麼這道程序在多人開發上有什麼幫助呢?本節將從不同面向來思考。

(一)打包資料庫

以本文將 MySQL 做為示範對象為例,我們可以在 DB 中預先插入大量測試資料,例如會員、產品、優惠券序號、訊息等。讓開發人員在本地就有資料可以運用。

如果後端或前端的程式沒有寫好,導致 DB 的資料「髒掉」了,那麼重新建立容器即可重回先前初始資料的狀態。

對比筆者前公司在開發階段可能會共用同一個 DB,上述將其做成映像檔共享,讓同事們各自獨立在本地運行容器,也不失為一種安全的做法。

(二)前後端的串接

假設我是負責後端的同事,當我在本地寫好程式,會想要有個 UI 畫面來操作,以便驗證結果。這時可以下載前端同事上傳的映像檔,啟動容器即可。不必從版本控制平台(如 Github)中下載前端的專案,也不用記得要如何在本地使用 Node.js 管理和運行前端程式。

假設我是前端的同事,則道理也相同。我不需要了解如何準備後端的程式與資料庫,只要透過後端同事所上傳的映像檔啟動容器就好。

雙方需要知道的,只剩下啟動容器的 Docker 指令和環境參數而已。這點可記在內部文件,或利用之後介紹的「Docker Compose」進一步簡化。

(三)站在部署角度

當產品的程式碼都完成了,接下來便會部署(deploy)到測試環境或生產環境。前端、後端與資料庫各自會有一套將成品打包成映像檔的方式,只是如何打包並非本文重點。

總之建立出映像檔並上傳後,需要部署的 server 只要執行 docker container run 指令,即可下載映像檔並啟動容器,相當簡便。而不必透過其他工具或技術(如 FileZilla),將程式的產出傳送到 server 上。

另外不論是前端或後端程式,難免會有一些用來存放連線設定的配置檔。不同的環境,要連線的地址也不同。經由給映像檔加上不同的 tag,能幫助區分這項產出,會部署在哪臺 server,以及對應的版本。

說到這裡,那要如何將自己寫好的程式產出,打包成映像檔呢?下一篇會介紹 Dockerfile,一步步撰寫製作的步驟。


今日文章到此結束!
最後推廣一下自己的部落格,我是「新手工程師的程式教室」的作者,請多指教/images/emoticon/emoticon41.gif


上一篇
【Docker】透過 Volume 來處理掛載(以 MySQL 為例)
下一篇
【Docker】撰寫 Dockerfile 製作映像檔(以 Spring Boot 為例)
系列文
救救我啊我救我!CRUD 工程師的惡補日記50
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
yanpu
iT邦新手 5 級 ‧ 2024-09-03 10:21:10

請問一下大大**docker image push {帳號}/{映像檔名稱}:{tag}中的{帳號}**是不是應該填入Repositories的名稱,因為一開始我輸入自己的帳號名稱系統會提示說找不到image,後來改成Repositories的名稱才會過,希望大大能幫忙解惑,謝謝大大

Chikuwa iT邦新手 2 級 ‧ 2024-09-06 00:58:12 檢舉

嗨嗨!
Repository 名稱正是由「帳號」和「映像檔名稱」組成,所以假設你在上傳 image 時,可能就會輸入如下的指令:

docker image push yanpu/mysql-demo:1.0.0

此時 Repository 名稱就是「yanpu/mysql-demo」了

yanpu iT邦新手 5 級 ‧ 2024-09-10 13:15:40 檢舉

感謝大大的回覆,後來上傳完有發現repository的組成是由帳號+映像檔名稱組成,想了一下我的問題應該是是否要再上傳前建立好repository才對XD

我要留言

立即登入留言