• Docker 数据卷与容器互联


    Docker是基于Go语言实现的开源容器项目,Docker让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何接口,Docker诞生于2013年年初,最初发起者是dotCloud公司.Docker自开源后受到广泛的关注和讨论,目前已有多个相关项目(包括Docker三剑客、Kubernetes等),逐渐形成了围绕Docker容器的生态体系,由于Docker在业界造成的影响力实在太大,dotCloud公司后来也直接改名为Docker Inc,并专注于Docker相关技术和产品的开发.

    Docker持久化处理

    生产环境中使用Docker的过程中,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作,容器管理中主要有两种方式,数据卷(Data Volumes),数据卷容器(Data Volume Containers),本小结将首先介绍如何在容器内创建数据卷,并且把本地的目录或文件挂载到容器内的数据卷中.接下来,会介绍如何使用数据卷容器在容器和主机、容器和容器之间共享数据,并实现数据的备份和恢复.

    ◆数据卷◆

    数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似于Linux中的mount操作.

    数据卷可以提供很多有用的特性,如下所示:

    ● 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效方便.
    ● 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作.
    ● 对数据卷的更新不会影响镜像,解耦了应用和数据.
    ● 卷会一直存在,直到没有容器使用,可以安全地卸载它.

    挂载一个本地目录作为数据卷:

    1.在本地主机创建一个目录,并写入一些数据,来模拟本地数据.

    [root@localhost ~]# mkdir /data
    [root@localhost ~]# echo "hello mkdirs.com" > /data/index.html
    

    2.开启容器,并让容器读取本地的/data目录.

    [root@localhost ~]# docker run -d -p 8080:80 --name MyWeb -v /data:/usr/local/apache2/htdocs httpd:latest
    2882b3edda42fe153a897d3dc21f73835eb57c14019b5e810066c34e0eda4c0c
    
    [参数解释]
    
    	-d     #以守护进程运行
    	-p     #将容器中的80口,映射到本地主机的8080
    	--name #指定一个容器名称
    	-v     #上面指的是,将本地/data目录挂载得到容器中的/usr/local目录中.
    	-P     #是将容器服务暴露的端口,是自动映射到本地主机的临时端口.
    
    
    [root@localhost ~]# curl 127.0.0.1:8080
    hello mkdirs.com
    

    ◆数据卷容器◆

    如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器.数据卷容器也是一个容器,但是它的目的是专门用来提供数据卷供其他容器挂载.

    1.首先,创建一个数据卷容器dbdata,并在容器中创建一个数据卷/dbdata的目录.

    [root@localhost ~]# docker run -itd -v /usr/local/apache2/htdocs --name dbdata centos:latest
    1bc16a7978db7db83a4a107bf2fe1c4c42c4c7fffa7dd92372a6aacb68ccfdd0
    
    [root@localhost ~]# docker exec -it dbdata /bin/bash
    [root@1bc16a7978db /]# echo "hello mkdirs.com" > /usr/local/apache2/htdocs/index.html
    [root@1bc16a7978db /]# ls -lh /usr/local/apache2/htdocs/index.html
    total 4.0K
    -rw-r--r-- 1 root root 17 Dec 15 11:37 index.html
    
    [root@1bc16a7978db /]# exit
    

    2.然后,可以在其他容器中使用--volumes-from来挂载dbdata容器中的数据卷,例如创建db1和db2两个容器,并从dbdata容器挂载数据卷.

    [root@localhost ~]# docker run -d -p 801:80 --volumes-from dbdata --name db1 httpd:latest
    123e75f38947f3294ac77a08bf4380f311d09cc176b576c61499139d75b35db3
    
    [root@localhost ~]# docker run -d -p 802:80 --volumes-from dbdata --name db2 httpd:latest
    a4e0f8016af6b89e31a637b1482b0849dcea26e4004298def4abce44c84d6dd6
    

    3.分别访问两个不同的端口,会发现网页展现效果是一样的,也就是说,db1和db2共享了dbdata容器里指定文件的内容.

    [root@localhost ~]# netstat -antp |grep 801
    tcp6       0      0 :::801                  :::*                    LISTEN      3998/docker-proxy
    [root@localhost ~]# netstat -antp |grep 802
    tcp6       0      0 :::802                  :::*                    LISTEN      4157/docker-proxy
    
    [root@localhost ~]# curl 127.0.0.1:801
    hello mkdirs.com
    [root@localhost ~]# curl 127.0.0.1:802
    hello mkdirs.com
    

    使用--volumes-from参数所挂载数据卷的容器自身并不需要保持在运行状态,如果删除了挂载的容器(包括dbdata、db1和db2),数据卷并不会被自动删除.如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时显式使用docker rm -v命令来指定同时删除关联的容器.

    ◆容器备份恢复◆

    数据备份: 使用下面的命令来备份dbdata数据卷容器内的数据卷,并把它备份到当前目录下.

    [root@localhost ~]# docker run --volumes-from dbdata -v $(pwd):/backup --name workers centos:latest tar -czvf /backup/backup.tar /usr/local/apache2/htdocs
    
    tar: Removing leading `/' from member names
    /usr/local/apache2/htdocs/
    /usr/local/apache2/htdocs/index.html
    [root@localhost ~]# ls
    backup.tar
    

    这个命令稍微有点复杂,具体分析一下,首先利用centos镜像创建了一个容器workers.使用--volumes-from dbdata参数来让workers容器挂载dbdata容器的数据卷(即dbdata数据卷),使用-v $(pwd):/backup参数来挂载本地的当前目录到workers容器的/backup目录.workers容器启动后,使用了tar -czvf/backup/backup.tar /usr/local/apache2/htdocs命令来将/usr/local/apache2/htdocs下内容备份为容器内的/backup/backup.tar,即宿主主机当前目录下的backup.tar.

    数据恢复: 如果要将数据恢复到一个容器,可以按照下面的步骤操作.

    1.首先创建一个带有数据卷的容器dbdata_backup.

    [root@localhost ~]# docker run -itd -v /usr/local/apache2/htdocs --name dbdata_backup centos:latest /bin/bash
    a207d887bfa07cc0e1737efb197950cac3b2c5647391348b1b8fa8b873c58667
    

    2.然后创建另一个新的容器,挂载dbdata2的容器,并使用untar解压备份文件到所挂载的容器卷中.

    [root@localhost ~]# docker run --volumes-from dbdata_backup -v $(pwd):/backup busybox tar -xzvf /backup/backup.tar
    
    usr/local/apache2/htdocs/
    usr/local/apache2/htdocs/index.html
    

    本小结介绍了通过数据卷和数据卷容器对容器内数据进行共享、备份和恢复等操作,通过这些机制,即使容器在运行中出现故障,用户也不必担心数据发生丢失,只需要快速地重新创建容器即可.

    Docker端口映射

    在实践中,经常会碰到需要多个服务组件容器共同协作的情况,这往往需要多个容器之间有能够互相访问到对方的服务,Docker提供了两个很方便的功能来满足服务访问的基本需求:一个是允许映射容器内应用的服务端口到本地宿主主机,另一个是互联机制实现多个容器间通过容器名来快速访问,下面我们来分别介绍一下吧.

    ◆从外部访问容器应用◆

    随机分配端口: 当容器中运行一些网络应用,要让外部访问这些应用时,可以通过-P-p参数来指定端口映射.当使用-P(大写的)标记时,Docker会随机映射一个49000~49900的端口到内部容器开放的网络端口.

    [root@localhost ~]# docker run -d -P --name myweb httpd:latest
    afb211e832c16c80822632fe0864838781cee2132993f93cde8c915e242f9df5
    
    [root@localhost ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                   NAMES
    afb211e832c1        httpd:latest        "httpd-foreground"   3 seconds ago       Up 2 seconds        0.0.0.0:32768->80/tcp   myweb
    

    指定分配端口: 当我们使用-p(小写的)可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器.

    [root@localhost ~]# docker run -d -p 8080:80 --name myweb1 httpd:latest
    b47f6131dea02c8cd22a75049e97c28cc4bb25bc6bf5cd36645c1ccb4210554e
    
    #上面说明,将容器的80端口,映射到本地的8080
    
    [root@localhost ~]# curl 127.0.0.1.8080
    <html><body><h1>It works!</h1></body></html>
    

    ◆映射所有接口地址◆

    映射指定端口: 格式将容器的80端口映射到本机的80端口.

    [root@localhost ~]# docker run -d -p 80:80 --name myweb2 httpd:latest
    9c3d0f8ad0bbfa75cc6534f93f959192316125a2776a2c909c71dc9dfb5a8b79
    
    [root@localhost ~]# curl 127.0.0.1
    <html><body><h1>It works!</h1></body></html>
    

    映射多个端口: 多次使用-p标记可以绑定多个端口.

    [root@localhost ~]# docker run -d -p 8080:80 -p 1000:21 --name myweb3 httpd:latest
    097ceb68128b58195c990dff720e39ca1717809cc2019d3f31466dee6fd32aec
    
    [root@localhost ~]# netstat -antp |grep "8080"
    tcp6       0      0 :::8080                 :::*                    LISTEN      2306/docker-proxy
    [root@localhost ~]# netstat -antp |grep "1000"
    tcp6       0      0 :::1000                 :::*                    LISTEN      2317/docker-proxy
    

    ◆映射到指定地址◆

    映射到指定地址的指定端口: 将容器中的80端口映射到本地指定IP地址上去.

    [root@localhost ~]# ifconfig ens32:0 192.168.1.10 netmask 255.255.255.0
    [root@localhost ~]# ifconfig ens32:0
    ens32:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.1.10  netmask 255.255.255.0  broadcast 192.168.1.255
            ether 00:0c:29:1e:14:e2  txqueuelen 1000  (Ethernet)
    
    [root@localhost ~]# docker run -d -p 192.168.1.10:8080:80 --name myweb_port httpd:latest
    7385faa5d476cb37dd7d201cd0ec939501c9bdb23ec1c8239245c30d2be9abe7
    
    [root@localhost ~]# netstat -antp |grep "8080"
    tcp        0      0 192.168.1.10:8080       0.0.0.0:*               LISTEN      2585/docker-proxy
    
    [root@localhost ~]# curl 192.168.1.10:8080
    <html><body><h1>It works!</h1></body></html>
    

    映射到指定地址的任意端口: :本地主机会自动分配一个端口,绑定到容器的80口.

    [root@localhost ~]# docker run -d -p 192.168.1.10::80 --name myweb_port1 httpd:latest
    7a5a105ae0827aaff68864a28b5f9b8a9592af3551f7deca564ea2d6d5a249b3
    
    [root@localhost ~]# netstat -antp |grep "80"
    tcp        0      0 192.168.1.10:8080       0.0.0.0:*               LISTEN      2585/docker-proxy
    
    #还可以使用udp标记来指定udp端口
    [root@localhost ~]# docker run -d -p 192.168.1.10:5000:5000/udp --name myweb_udp httpd:latest
    b9cc6333a63109a70a1d2e645b1ff5046988b472dea3bb4f4d010f1478951adf
    
    [root@localhost ~]# netstat -an |grep "5000"
    udp        0      0 192.168.1.10:5000       0.0.0.0:*
    

    ## Docker容器互联

    容器的互联(linking)是一种让多个容器中应用进行快速交互的方式,它会在源和接收容器之间创建连接关系,接收容器可以通过容器名快速访问到源容器,而不用指定具体的IP地址.

    1.使用--link参数可以让容器之间安全地进行交互,下面先创建一个新的MySQL数据库容器.

    [root@localhost ~]# docker run -d --name mysqldb mysql:latest
    c1770a69ed29944466ce013c42ac2a0391651c88381e41be05308eab80458390
    

    2.然后创建一个新的web容器,并将它连接到MySQL容器,使之能够通信.

    [root@localhost ~]# docker run -d -P --name web --link mysqldb:mysqldb httpd:latest
    8b2bfcbbe00f6966c511fdbbbc16e40736ab8d6aa89d229e224f38d12c4643df
    

    此时,mysqldb容器和web容器建立互联关系,--link参数的格式为--link name:alias,其中name是要连接的容器名称,alias是这个连接的别名.

    Docker相当于在两个互联的容器之间创建了一个虚机通道,而且不用映射它们的端口到宿主主机上.在启动mysqldb容器的时候并没有使用-p和-P标记,从而避免了暴露数据库服务端口到外部网络上.

    拓展与实战例子

    ◆Apache◆

    Apache是世界使用排名第一的Web服务器软件,它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一.它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中.

    1.拉取镜像,并在本地创建一个测试页.

    [root@localhost ~]# docker pull httpd:latest
    [root@localhost ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    httpd               latest              2a51bb06dc8b        4 weeks ago         132MB
    
    [root@localhost ~]# mkdir /web
    [root@localhost ~]# echo "hello world" > /web/index.html
    

    2.运行http容器,并访问测试.

    [root@localhost ~]# docker run -d -p 8080:80 --name MyWeb -v /web:/usr/local/apache2/htdocs httpd:latest
    [root@localhost ~]# curl 127.0.0.1:8080
    hello world
    

    ◆GitLab◆

    Gitlab是一款非常强大的开源源码管理系统.它支持基于Git的源码管理、代码评审、issue跟踪、活动管理、wiki页面,持续集成和测试等功能.基于Gitlab,用户可以自己搭建一套类似Github的开发协同平台.

    1.安装并启动postgresql.

    [root@localhost ~]# docker pull sameersbn/postgresql:latest
    [root@localhost ~]# docker images
    REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
    sameersbn/postgresql   latest              3c0142eb3992        5 months ago        204MB
    
    [root@localhost ~]# docker run --name gitlab_postgresql -d 
    --env 'DB_NAME=gitlab' 
    --env 'DB_USER=gitlab' --env 'DB_PASS=gitlab' 
    sameersbn/postgresql:latest
    

    2.安装redis.

    [root@localhost ~]# docker pull sameersbn/redis:latest
    [root@localhost ~]# docker images
    REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
    sameersbn/redis        latest              ad607f019b8c        4 months ago        84.8MB
    sameersbn/postgresql   latest              3c0142eb3992        5 months ago        204MB
    
    [root@localhost ~]# docker run --name gitlab_redis -itd sameersbn/redis:latest
    

    3.安装GitLab.

    [root@localhost ~]# docker pull sameersbn/gitlab:latest
    [root@localhost ~]# docker images
    REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
    sameersbn/gitlab       latest              336fe9c19d92        6 days ago          1.96GB
    sameersbn/redis        latest              ad607f019b8c        4 months ago        84.8MB
    sameersbn/postgresql   latest              3c0142eb3992        5 months ago        204MB
    
    [root@localhost ~]# docker run --name gitlab -d sameersbn/gitlab 
    --link gitlab_postgresql:postgresql --link gitlab_redis:redis 
    --publish 10022:22 --publish 10080:80 
    --env 'GITLAB_PORT=10080' --env 'GITLAB_SSH_PORT=10022' 
    --env 'GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alpha-numeric-string' 
    sameersbn/gitlab:latest
    

    ◆WordPress◆

    WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站.也可以把WordPress当作一个内容管理系统(CMS)来使用,WordPress逐步演化成一款内容管理系统软件,它是使用PHP语言和MySQL数据库开发的.用户可以在支持PHP和MySQL数据库的服务器上使用自己的博客.

    1.首先安装一个MariaDB数据库,并配置好初始密码.

    [root@localhost ~]# docker pull mariadb:latest
    [root@localhost ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    mariadb             latest              b468922dbbd7        3 weeks ago         366MB
    
    [root@localhost ~]# docker run --name MyDataBase --env MYSQL_ROOT_PASSWORD=example -d mariadb:latest
    

    2.拉取WordPress镜像,并运行,将容器内的80口映射到宿主机的8080口上.

    [root@localhost ~]# docker pull wordpress:latest
    [root@localhost ~]# docker run --name MyWordPress --link MyDataBase:MariaDB -p 8080:80 -d wordpress:latest
    

    参考文献:《Docker技术入门与实战》《Docker基础与实战》

  • 相关阅读:
    NodeJs学习历程
    MongoDb学习历程
    递归函数为什么要防止栈溢出
    *args 是可变参数,args 接收的是一个 tuple; **kw 是关键字参数,kw 接收的是一个 dict。
    list和tuple的区别
    python源码阅读
    常用的线程池有哪些?
    备份
    假设你正在爬楼梯,需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶,你有多少种不同的方法可以爬到楼顶呢?
    最后一个单词的长度
  • 原文地址:https://www.cnblogs.com/LyShark/p/10872322.html
Copyright © 2020-2023  润新知