使用 Docker 時,容器(Container)會自動建立一個資料捲(Data Volume)來單獨儲存資料。資料捲有獨立的本地目錄,不跟著容器走,你在不同地方使用同一個容器,資料是不一樣的。自動建立的資料捲不便於管理,Docker 官方建議我們用 Named Volume 來負責容器的資料持久化,Named Volume 就是自己取名字手動建立一個資料捲。
本文使用 MySQL 資料庫做例子。資料捲對資料庫容器來說是非常重要的。
建立資料捲
這裡我們隨便取個資料捲名字叫 my-data
吧。建立命令很簡單:
docker volume create --name my-data
建立共享網路
容器在建立時,除了自動建立資料捲外,也會自動建立它的專用網路(Network)。這個網路我們也要用自己建立的(Defined Network),自己建立的方便管理。這裡給網路取名叫 my-network
:
docker network create my-network
為什麼建立這個網路呢?是為了在容器間共享網路,看下去就會明白。
建立 MySQL 容器
現在利用前面建立的資料捲和網路建立一個 MySQL 容器:
docker run -d --rm --name mysql-a -v my-data:/var/lib/mysql --network my-network -p 33061:3306 -e MYSQL_ROOT_PASSWORD=abcd1234 mysql:latest
詳細解釋一下各引數:
- 容器命名為
mysql-a
。 - MySQL 預設的埠是
3306
,你可以換一個以免和本地的衝突。這個例子中我對映到33061
。 -d
是後臺執行。--rm
是讓容器在停止執行時自動刪除。資料在外部的捲裡,可以放心刪。-v
就是使用資料捲。/var/lib/mysql
是 MySQL 存放資料的目錄,現在我們要把裡面的東西都對映到資料捲裡:-v my-data:/var/lib/mysql
--network my-network
使用我們剛才建立的網路。-e
設定 MySQL 的環境變數。在這裡我們設定 root 密碼為abcd1234
- 最後
mysql:latest
是映像(Image)。具體 tag 可看 Docker Hub: MySQL
建立 PhpMyAdmin 容器
管理 MySQL 資料庫的客戶端有很多,其中 PhpMyAdmin 是比較常見的一種。所以現在我們要建立 PhpMyAdmin 的容器,然後去管理 MySQL 容器,也就是連線兩種容器。
如何連線?以前可以用 --link
的方式,但官方已經不推薦了,未來版本會棄用的,這裡就不寫了。官方推薦的是 Defined Network,之前建立 my-network
就是為了用在這裡。如果你不用 PhpMyAdmin 管理,那麼 Network 也可以不單獨建立。
建立容器:
docker run -d --rm --name my-pma --network my-network -p 8080:80 -e PMA_HOST=mysql-a phpmyadmin/phpmyadmin
引數中 PMA_HOST=mysql-a
指定了 MySQL 容器。埠隨便映射了一個 8080
。建立好後,PhpMyAdmin 容器和 MySQL 容器就在同一個網路裡了,然後 PhpMyAdmin 就可以管理 MySQL 資料庫了。
現在開啟瀏覽器,進 http://localhost:8080
,輸入 root 賬戶密碼就可以進去管理了——如果你的 MySQL 版本 >= 5.7,那可能登入不進去,需要改一下 MySQL 賬號所用的密碼外掛(identified with mysql_native_password
)。
資料捲的備份
使用資料捲的一大好處,是可以在不同機器和環境中使用同一套資料。因此,必須掌握如何備份和還原資料捲。
備份的操作思路:
- 建立一個新容器,這個容器有一個資料捲和 MySQL 容器是一樣的。
- 再掛載一個非 Named Volume 資料捲(本地目錄),用來對映本地備份目錄。
- 將 MySQL 容器資料捲打包,然後存在備份目錄裡。
- 在本地目錄獲取資料捲打包檔案。
命令列操作:
docker run --rm --volumes-from mysql-a -v $(pwd):/backup busybox tar cvf /backup/mysql-backup.tar /var/lib/mysql
引數說明:
- 用了
--volumes-from mysql-a
,就是從mysql-a
直接拿它的資料捲(my-data
)過來用。 -v $(pwd):/backup
:將本地當前目錄作為資料捲目錄對映到容器系統的/backup
目錄,$(pwd)
就是輸出當前目錄,註意在 PowerShell 裡是${pwd}
。你用別的目錄也可以。busybox
是用到的 Image,它的容量很小,但重要工具基本都有。tar cvf /backup/mysql-backup.tar /var/lib/mysql
是在容器裡執行的備份命令:將/var/lib/mysql
(mysql-a
資料捲內容)打包到/backup
目錄下的 mysql-backup.tar 中。由於本地當前目錄和/backup
有對映關係,所以本地當前目錄下也會有 mysql-backup.tar 檔案。
mysql-backup.tar 就是我們建立的資料捲備份檔案,你可以帶著它到處跑了。有些人會做一個專門存放各種資料捲的容器作為備份,我感覺有點麻煩和多餘。
資料捲的還原
還原的思路和備份一樣,也是先要搞一個臨時容器,然後執行一些命令去解壓 tar 檔案。
假設我們在別的地方建立了一個新的 MySQL 容器 mysql-b
,我們該怎麼把 my-data
資料捲的資料還原到它裡面去呢?
先把 mysql-backup.tar 複製到當前目錄。然後:
docker run --rm --volumes-from mysql-b -v $(pwd):/backup centos bash -c "cd /var/lib && rm -rf mysql/* && tar xvf /backup/mysql-backup.tar --strip 2"
這裡重點解釋一下在容器 bash 裡執行的命令:
cd /var/lib
: 進入/var/lib
目錄。rm -rf mysql/*
: 刪除目錄 mysql 下的所有檔案,為的是等會將資料捲的備份檔案放進去。刪除再解壓進去比直接改寫更乾凈穩妥一些。tar xvf /backup/mysql-backup.tar --strip
2
: 將 mysql-backup.tar 檔案中 mysql 的檔案解壓到/var/lib/mysql
目錄中去,因為我們在/var/lib
中,而打包檔案包括了/var/lib/mysql
多層目錄,所以加了引數--strip 2
。關於打包解壓目錄這種事你可以自己規劃,只要確保mysql
裡的檔案能正確的備份和還原就行。
檔案解壓完後,重啟當前的 MySQL 容器:
docker restart mysql-b
還原工作到此結束,現在 mysql-b
的資料和 mysql-a
是一樣的了。
總結
資料捲對資料庫容器非常重要。Named Volume 可以使我們管理資料捲更為方便,應多加利用。其他資料庫的檔案結構和 MySQL 可能不一樣,但只要掌握了 MySQL 資料捲備份還原的原理之後,其他資料庫應該也不難操作。