1八、docker的持久化存儲和數據共享

docker volume

18.1 Data Volume

Docker持久化數據方案

  • 基於本地文件系統的Volume

  能夠在執行docker create或者docker run的時候,經過-v參數將主機的目錄做爲容器的數據卷。這部分功能即是基於本地文件系統的Volume管理。html

  • 基於plugin的Volume

  支持第三方的存儲方案,好比NAS、AWS等。mysql

Data Volume 類型

  • 受管理的data volume,由docker後臺自動建立
  • 綁定掛載的volume,具體掛載位置能夠由用戶指定

經過例子來查看

  以MySQL爲例,能夠查看官方的Dockerfile,當中用到了Volume。nginx

# 查看volume
[root@docker ~]# docker volume ls
[root@docker ~]# 
# 建立一個MySQL的容器
[root@docker ~]# docker run -d --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql

# 查看MySQL容器跑起來以後的volume
[root@docker ~]# docker volume ls
DRIVER              VOLUME NAME
local               e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac
[root@docker ~]# 
# 查看這個volume的想象信息
[root@docker ~]# docker volume inspect e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac
[
    {
        "CreatedAt": "2018-06-07T09:13:24Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac/_data",
        "Name": "e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac",
        "Options": null,
        "Scope": "local"
    }
]
[root@docker ~]#

  能夠看到,這個volume並不在容器當中,而是掛載到了宿主機的/var/lib/docker/volumes/e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac/_data目錄下。git

  再建立一個mysql2的容器:github

[root@docker ~]# docker run -d --name mysql2 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql

[root@docker ~]# docker volume ls
DRIVER              VOLUME NAME
local               a3c730f24ca254cabbd328b4c5a6e7fa1822d7e1b2e54c9ac9104839295e5225
local               e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac
[root@docker ~]# docker volume inspect a3c730f24ca254cabbd328b4c5a6e7fa1822d7e1b2e54c9ac9104839295e5225
[
    {
        "CreatedAt": "2018-06-07T09:22:18Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/a3c730f24ca254cabbd328b4c5a6e7fa1822d7e1b2e54c9ac9104839295e5225/_data",
        "Name": "a3c730f24ca254cabbd328b4c5a6e7fa1822d7e1b2e54c9ac9104839295e5225",
        "Options": null,
        "Scope": "local"
    }
]
[root@docker ~]#

  刪除這兩個容器:web

[root@docker ~]# docker stop mysql1 mysql2
[root@docker ~]# docker rm mysql1 mysql2
[root@docker ~]# docker volume ls
DRIVER              VOLUME NAME
local               a3c730f24ca254cabbd328b4c5a6e7fa1822d7e1b2e54c9ac9104839295e5225
local               e3c54bb7b620d86524b6cebc4c28568a2a81a104871a5baf41e22c02bd8d7bac
[root@docker ~]#

  能夠發現,volume在容器刪除以後也不會被刪除,能夠防止容器刪除以後數據也不存在了的問題。可是volume的名字很是不友好,不方便咱們使用,可是咱們能夠在建立或者啓動容器的時候給volume設置別名來方便咱們使用。sql

給volume起別名

  從新建立mysql1容器,在啓動的時候給volume設置別名docker

[root@docker ~]# sudo docker run -d -v mysql:/var/lib/mysql --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
[root@docker ~]# docker volume ls
DRIVER              VOLUME NAME
local               mysql
[root@docker ~]# docker volume inspect mysql
[
    {
        "CreatedAt": "2018-06-07T09:30:33Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/mysql/_data",
        "Name": "mysql",
        "Options": null,
        "Scope": "local"
    }
]
[root@docker ~]#

  驗證一下這個mysql的volume是否已經被使用:進入mysql1容器,建立一個數據庫shell

[root@docker ~]# docker exec -it mysql1 /bin/bash
root@5aa496b309cc:/# mysql -uroot
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.11 MySQL Community Server - GPL

Copyright (c) 2000, 2018, 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 |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)

mysql> create database docker;
Query OK, 1 row affected (0.07 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| docker             |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> \q
Bye
root@5aa496b309cc:/# exit
[root@docker ~]# 中止mysql1容器,並刪除mysql1容器
[root@docker ~]# docker stop mysql1
[root@docker ~]# docker rm mysql1
[root@docker ~]# 建立一個新的mysql2的容器,急需使用mysql這個volume
[root@docker ~]# sudo docker run -d -v mysql:/var/lib/mysql --name mysql2 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
[root@docker ~]# 進入mysql2查看是否存在以前的數據
[root@docker ~]# docker exec -it mysql2 /bin/bash
root@cf1cc3ad331e:/# mysql -uroot
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.11 MySQL Community Server - GPL

Copyright (c) 2000, 2018, 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           |
+--------------------+
| docker             |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> \q
Bye
root@cf1cc3ad331e:/# exit

  能夠發現,volume中的數據並不會由於容器的刪除二消失,實現了數據持久化的目標。可是這種方式的volume須要在Dockerfile中使用VOLUME來預先指定容器中的數據存放路徑。數據庫

18.2 Bind Mounting

  Bind Mounting跟上面的方式不同,能夠動態的指定容器內文件存放路徑和宿主機上的數據庫卷目錄。

  構建一個docker-nginx的鏡像:

# Dockerfile
[root@docker docker-nginx]# cat Dockerfile
# this same shows how we can extend/change an existing official image from Docker Hub

FROM nginx:latest
# highly recommend you always pin versions for anything beyond dev/learn

WORKDIR /usr/share/nginx/html
# change working directory to root of nginx webhost
# using WORKDIR is prefered to using 'RUN cd /some/path'

COPY index.html index.html

# I don't have to specify EXPOSE or CMD because they're in my FROM
[root@docker docker-nginx]# cat index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">

  <title>hello</title>

</head>

<body>
  <h1>Hello Docker! </h1>
</body>
</html>
[root@docker docker-nginx]# 構建鏡像
[root@docker docker-nginx]# docker build -t staryjie/docker-nginx .
[root@docker docker-nginx]# 建立容器
[root@docker docker-nginx]# docker run -d -p 80:80 --name web staryjie/docker-nginx
[root@docker docker-nginx]# 本地訪問
[root@docker docker-nginx]# curl 127.0.0.1
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">

  <title>hello</title>

</head>

<body>
  <h1>Hello Docker! </h1>
</body>
</html>
[root@docker docker-nginx]#

  可是index.html文件是沒法更改的,若是要更改必需要從新構建鏡像,這樣很是不便。

[root@docker docker-nginx]# 強制刪除web容器
[root@docker docker-nginx]# docker rm -f web
[root@docker docker-nginx]# 從新建立一個容器,指定宿主機上index.html的目錄到容器中nginx的html目錄
[root@docker docker-nginx]# docker exec -it web1 /bin/bash
root@18af473954f1:/usr/share/nginx/html# ls
Dockerfile  index.html
root@18af473954f1:/usr/share/nginx/html# touch test.txt
root@18af473954f1:/usr/share/nginx/html# exit
[root@docker docker-nginx]# ls
Dockerfile  index.html  test.txt
[root@docker docker-nginx]# curl 127.0.0.1
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">

  <title>hello</title>

</head>

<body>
  <h1>Hello Docker! </h1>
</body>
</html>
[root@docker docker-nginx]# 修改index.html
[root@docker docker-nginx]# cat index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">

  <title>hello</title>

</head>

<body>
  <h1>Hello Docker! </h1>
  <h1>Hello, I have changed this file! </h1>
</body>
</html>
[root@docker docker-nginx]# curl 127.0.0.1
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">

  <title>hello</title>

</head>

<body>
  <h1>Hello Docker! </h1>
  <h1>Hello, I have changed this file! </h1>
</body>
</html>
[root@docker docker-nginx]#

  採用Bind Mounting的方式實現volume的話,容器內外的數據是同步的,只須要修改一個地方,容器內或者容器外都會同步修改,很是的方便快捷。

  採用Bind Mounting的方式,將docker做爲開發環境可使咱們的開發環境和生產環境保持一致,這也是實現DevOps的第一步。(不少開發使用的都是Windows的系統,可是服務器通常都是Linux的,沒法保持環境的一致性,影響開發效率。)

  利用docker搭建一個與生產環境統一的開發環境

相關文章
相關標籤/搜索