zoukankan      html  css  js  c++  java
  • 18、docker的持久化存储和数据共享

    docker volume

    18.1 Data Volume

    Docker持久化数据方案

    • 基于本地文件系统的Volume

      可以在执行docker create或者docker run的时候,通过-v参数将主机的目录作为容器的数据卷。这部分功能便是基于本地文件系统的Volume管理。

    • 基于plugin的Volume

      支持第三方的存储方案,比如NAS、AWS等。

    Data Volume 类型

    • 受管理的data volume,由docker后台自动创建
    • 绑定挂载的volume,具体挂载位置可以由用户指定

    通过例子来查看

      以MySQL为例,可以查看官方的Dockerfile,当中用到了Volume。

    # 查看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目录下。

      再创建一个mysql2的容器:

    [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 ~]# 
    

      删除这两个容器:

    [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设置别名来方便我们使用。

    给volume起别名

      重新创建mysql1容器,在启动的时候给volume设置别名

    [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容器,创建一个数据库

    [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搭建一个与生产环境统一的开发环境

  • 相关阅读:
    aspnet自定义控件Treeview基本用法
    .net4 wpf App 使用log4net 错误:The type or namespace name 'log4net' could not be found (are you missing a using directive or an assembly reference?)
    asp_UpdatePanel PostBack返回后执行Javascript
    JqueryUI dialog model和asp_UpdatePanel 例子
    Asp.net中使用mshtml
    Windows 2008 R2使用WLAN
    AJAXToolkit_ ModalPopupExtender弹出窗中 使用分页方法
    Ajax.BeginForm MVC3 使用
    WPF错误 Set connectionId threw an exception
    高亮显示当前行
  • 原文地址:https://www.cnblogs.com/jie-fang/p/10279773.html
Copyright © 2011-2022 走看看