Java開發人員的9個Docker食譜中的食譜之一是将MySQL容器與WildFly結合使用。 Docker容器是臨時性的,是以終止和删除它們後,存儲在其中的任何狀态都将消失。 是以,即使可以按照本食譜中的說明使用MySQL容器,也可以使用DDL / DML指令來持久化資料,但是在終止和删除容器之後,該狀态将丢失,或者至少不可通路。
該部落格展示了Docker MySQL Persistence的不同方法-跨容器重新開機并可以從多個容器通路。
MySQL Docker容器的預設資料位置
讓我們檢視MySQL Docker容器存儲資料的預設位置。
以以下方式啟動MySQL容器:
docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -d mysql
并檢查為:
docker inspect -f {{.Volumes}} <CONTAINER_ID>
然後顯示匿名卷:
map[/var/lib/mysql:/mnt/sda1/var/lib/docker/vfs/dir/78f079dae09bf052cf900951b6d71a611fcf7c72f3460a2013e6f4d941a2b256]
如果使用的是Boot2Docker,則
/mnt/sda1
目錄用于存儲映像,容器和資料。 該目錄來自Boot2Docker虛拟機檔案系統。 Docker文檔中也對此做了澄清,值得在這裡重複:
注意:如果使用的是Boot2Docker,則Docker守護程式僅對OSX / Windows檔案系統具有有限的通路權限。 Boot2Docker嘗試自動共享您的(OSX)或
/Users
(Windows)目錄,是以您可以使用
C:\Users
挂載檔案或目錄
docker run -v /Users/<path>:/<container path> ...
(OSX)或
docker run -v /Users/<path>:/<container path> ...
(Windows)。 所有其他路徑都來自Boot2Docker虛拟機的檔案系統。
docker run -v /c/Users/<path>:/<container path ...
您可以通過以下方式登入到VM,進而在Boot2Docker上檢視此已安裝目錄:
boot2docker ssh
然後檢視目錄清單為:
[email protected]:~$ ls -la /mnt/sda1/var/lib/docker/
total 72
drwxr-xr-x 11 root root 4096 Apr 9 19:45 ./
drwxr-xr-x 4 root root 4096 Mar 27 13:58 ../
drwxr-xr-x 5 root root 4096 Mar 27 13:59 aufs/
drwx------ 10 root root 4096 Apr 9 19:45 containers/
drwx------ 3 root root 4096 Mar 27 13:59 execdriver/
drwx------ 128 root root 20480 Apr 9 19:45 graph/
drwx------ 2 root root 4096 Apr 7 23:34 init/
-rw-r--r-- 1 root root 7168 Apr 9 19:45 linkgraph.db
-rw------- 1 root root 2229 Apr 9 19:45 repositories-aufs
drwx------ 2 root root 4096 Apr 9 19:14 tmp/
drwx------ 2 root root 4096 Mar 27 17:56 trust/
drwx------ 3 root root 4096 Apr 9 19:45 vfs/
drwx------ 4 root root 4096 Apr 9 19:45 volumes/
跨容器重新開機的MySQL資料–匿名卷
匿名卷(即,由容器建立且未顯式安裝的卷)是特定于容器的。 除非使用
docker remove -v
指令明确删除它們,否則它們會一直存在。 這意味着即使可能不會删除先前的卷,也會為新容器安裝新的匿名卷。 即使在終止并删除容器後,該卷仍駐留在Docker主機上。 一個MySQL容器建立的匿名卷不能被另一個MySQL容器通路。 這意味着不能在不同的資料容器之間共享資料。
讓我們使用代碼來了解這一點。
以以下方式啟動MySQL容器:
docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -it -p 3306:3306 mysql
登入到容器:
docker exec -it <CONTAINER_ID> bash
連接配接到MySQL執行個體,并建立一個表,如下所示:
[email protected]:/# mysql --user=mysql --password=mysql
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.6.24 MySQL Community Server (GPL)
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| sample |
+--------------------+
2 rows in set (0.00 sec)
mysql> connect sample;
Connection id: 3
Current database: sample
mysql> show tables;
Empty set (0.00 sec)
mysql> create table user(name varchar(50));
Query OK, 0 rows affected (0.00 sec)
mysql> show tables;
+------------------+
| Tables_in_sample |
+------------------+
| user |
+------------------+
1 row in set (0.00 sec)
停止容器:
docker stop <CONTAINER_ID>
重新啟動容器:
docker start <CONTAINER_ID>
現在,當您連接配接到MySQL容器時,資料庫表将正确顯示。 這表明匿名卷可以在容器重新啟動後保持狀态。
檢查容器:
~> docker inspect -f {{.Volumes}} ea7b1eff9714
map[/var/lib/mysql:/mnt/sda1/var/lib/docker/vfs/dir/78f079dae09bf052cf900951b6d71a611fcf7c72f3460a2013e6f4d941a2b256]
并且它可以正确顯示
/mnt/sda1
目錄中的相同匿名卷。
現在,讓我們删除該容器,然後啟動一個新的MySQL容器。 首先取出容器:
docker rm -f <CONTAINER_ID>
并使用與先前相同的指令啟動新容器:
docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -it -p 3306:3306 mysql
現在,當您嘗試檢視表清單時,其顯示為空:
mysql> connect sample;
Connection id: 3
Current database: sample
mysql> show tables;
Empty set (0.00 sec)
這是因為匿名卷在容器重新啟動時可見,但對其他容器不可見。 将安裝新卷以用于容器的新運作。 還可以通過再次檢查容器來驗證:
~> docker inspect -f {{.Volumes}} bde73c930275
map[/var/lib/mysql:/mnt/sda1/var/lib/docker/vfs/dir/4d0ab6d1412bfbe79541b2d87d632cf12e70044201665f859a6a678132fb323f]
使用另一個目錄來裝入匿名卷。
如此有效地,由一個容器存儲在MySQL資料庫中的任何資料都不可用于另一個MySQL容器。
用于存儲MySQL資料的Docker卷
在不同的MySQL容器之間共享資料的一種選擇是在運作Docker映像時使用
-v
開關将Docker主機上的目錄作為卷裝入容器中。 如果使用的是Boot2Docker,則有兩種選擇:
- 從Boot2Docker VM檔案系統挂載目錄。 如果該目錄不存在,則需要建立。
- 從Mac主機挂載目錄。 為了友善起見,此目錄必須存在于
或您對應的目錄中。/Users/arungupta
第一種方法與特定的Boot2Docker VM映像相關,第二種方法與特定的Mac主機相關。 稍後我們将讨論如何解決此問題。
我們僅在這裡讨論第一種方法。 以以下方式啟動MySQL容器:
docker run --name mysqldb -v /mnt/sda1/var/mysql_data:/var/lib/mysql -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -it -p 3306:3306 mysql
/var/lib/mysql
是MySQL容器寫入其檔案的預設目錄。 Boot2Docker重新開機後,該目錄不會保留。 是以,建議的選項是在
/mnt/sda1
建立一個目錄并映射該目錄。 確定像上面一樣建立目錄
/mnt/sda1/var/mysql_data
。
現在檢查容器為:
~> docker inspect -f {{.Volumes}} cd7deacc9d18
map[/var/lib/mysql:/mnt/sda1/var/mysql_data]
現在,容器的所有其他運作都可以安裝相同的卷,并且可以通路資料。
請記住,多個MySQL容器不能一起通路此共享安裝,而是會出現錯誤:
2015-04-10 02:35:58 1 [ERROR] InnoDB: Unable to lock ./ibdata1, error: 11
2015-04-10 02:35:58 1 [Note] InnoDB: Check that you do not already have another mysqld process using the same InnoDB data or log files.
2015-04-10 02:35:58 1 [Note] InnoDB: Retrying to lock the first data file
是以,您需要確定停止現有的MySQL容器,使用相同的卷啟動新的MySQL容器,并且仍然可以通路資料。
這可以使用主/從配置進行配置,其中主伺服器和從伺服器可以通路相同的卷。 如果嘗試過該配置的人可以共享該配方,那将是很好的。
但是如前所述,這種方法是以主機為中心的。 它将MySQL限制為特定的Boot2Docker VM映像。 這意味着,您再次失去了Docker提供的可移植性的巨大好處。
認識Docker僅資料容器!
Docker僅資料容器
Docker很好地遵循了單一職責原則(SRP)。 Docker僅資料容器是NoOp容器,它們執行的指令實際上并不相關,而是裝載用于存儲資料的卷。 這些容器甚至不需要啟動或運作,是以該指令實際上是無關緊要的,僅建立它們就足夠了。
建立容器為:
docker create --name mysql_data -v /var/lib/mysql mysql
如果計劃以後使用MySQL容器,建議使用
mysql
映像來節省帶寬和空間,以免下載下傳另一個随機映像。 您可以針對所使用的任何資料庫容器調整此指令。
如果打算使用MySQL,則可以将以下僅資料容器建立為:
docker create --name mysql_data arungupta/mysql-data-container
該容器的Dockerfile非常簡單,可用于您選擇的資料庫伺服器。
由于此容器未運作,是以僅在
docker ps
中将不可見。 相反,您需要使用
docker ps -a
檢視容器:
~> docker ps -a | grep mysql
ec48ddda196e mysql:5 "/entrypoint.sh mysq 2 days ago mysql_data
Docker允許使用運作容器時指定的
--volumes-from
開關從其他容器安裝或拉入卷。
讓我們啟動MySQL容器以将此純資料容器用作:
docker run --name mysqldb --volumes-from mysql_data -v /var/lib/mysql:/var/lib/mysql -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -it -p 3306:3306 mysql
Boot2Docker VM現在已填充
/var/lib/mysql
目錄:
total 110596
drwxrwxrwx 5 999 999 180 Apr 10 05:05 ./
drwxrwxr-x 4 root staff 120 Apr 9 21:11 ../
-rw-rw---- 1 999 999 56 Apr 10 00:57 auto.cnf
-rw-rw---- 1 999 999 50331648 Apr 10 05:05 ib_logfile0
-rw-rw---- 1 999 999 50331648 Apr 10 00:57 ib_logfile1
-rw-rw---- 1 999 999 12582912 Apr 10 05:05 ibdata1
drwx------ 2 999 999 1620 Apr 10 00:57 mysql/
drwx------ 2 999 999 1100 Apr 10 00:57 performance_schema/
drwx------ 2 999 999 100 Apr 10 01:18 sample/
如果停止此容器,然後運作另一個容器,則可以在那裡通路資料。
在一個簡單的場景中,應用程式伺服器,資料庫和僅資料容器都可以位于同一主機上。 另外,應用程式伺服器可以駐留在單獨的主機上,而資料庫伺服器和僅資料容器可以駐留在同一主機上。
希望當Docker卷可以跨多個主機工作時,它會更加廣泛。
如果所有這些操作(即建立僅資料容器并啟動使用僅資料容器中的卷的MySQL容器)都可以使用Docker Compose輕松完成,那将是很好的。 #1284應該解決此問題。
通常的
mysqldump
和
mysql
指令可用于從卷備份和還原。 這可以通過使用CLI為連接配接到MySQL實作這裡解釋 。
- 您還可以檢視docker-volumes來管理主機上的卷。
- 您還可以在#6496上閱讀有關将來可能發展的卷的更多資訊。
請享用!
翻譯自: https://www.javacodegeeks.com/2015/04/docker-mysql-persistence.html