【Docker】將容器打包為映像檔與人分享


https://unsplash.com/photos/dyu466BfWj8

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

此篇內容轉載自本人在 iThome 的文章


一、事前準備

本文將以 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。首先要請讀者註冊該平台的帳號。

註冊後,可透過指令在 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 image push {帳號}/{映像檔名稱}:{tag}。範例指令如下:

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

稍等一段時間,最後就可以在 Docker Hub 看到上傳完成的映像檔了。

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

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,一步步撰寫製作的步驟。


上一篇:【Docker】透過 Volume 來處理掛載(以 MySQL 為例)

下一篇:【Docker】撰寫 Dockerfile 製作映像檔(以 Spring Boot 為例)

留言