一、容器数据管理

docker管理数据的方式有两种:

  • 数据卷
  • 数据卷容器

    8.1 数据卷

    数据卷是一个或多个容器专门指定绕过Union File System的目录,为持续性或共享数据提供一些有用的功能:

  • 数据卷可以在容器间共享和重用

  • 数据卷数据改变是直接修改的
  • 数据卷数据改变不会被包括在容器中
  • 数据卷是持续性的,直到没有容器使用它们

    添加一个数据卷

    你可以使用-v选项添加一个数据卷,或者可以使用多次-v选项为一个 docker 容器运行挂载多个数据卷。

    1. $ sudo docker run --name data -v /data -t -i ubuntu:14.04 /bin/bash # 创建数据卷绑定到到新建容器,新建容器中会创建 /data 数据卷 bash-4.1# ls -ld /data/
    2. drwxr-xr-x 2 root root 4096 Jul 23 06:59 /data/
    3. bash-4.1# df -Th
    4. Filesystem Type Size Used Avail Use% Mounted on
    5. ... ...
    6. ext4 91G 4.6G 82G 6% /data

    创建的数据卷可以通过docker inspect获取宿主机对应路径

    $ sudo docker inspect data
    ... ... "Volumes": { "/data": "/var/lib/docker/vfs/dir/151de401d268226f96d824fdf444e77a4500aed74c495de5980c807a2ffb7ea9" }, # 可以看到创建的数据卷宿主机路径 ... ...
    

    或者直接指定获取

    $ sudo docker inspect --format="{{ .Volumes }}" data
    map[/data: /var/lib/docker/vfs/dir/151de401d268226f96d824fdf444e77a4500aed74c495de5980c807a2ffb7ea9]
    

    挂载宿主机目录为一个数据卷

    -v 选项除了可以创建卷,也可以挂载当前主机的一个目录到容器中。

    $ sudo docker run --name web -v /source/:/web -t -i ubuntu:14.04 /bin/bash
    bash-4.1# ls -ld /web/
    drwxr-xr-x 2 root root 4096 Jul 23 06:59 /web/
    bash-4.1# df -Th
    ... ...
                ext4     91G  4.6G   82G   6% /web
    bash-4.1# exit
    

    默认挂载卷是可读写的,可以在挂载时指定只读

    $ sudo docker run --rm --name test -v /source/:/test:ro -t -i ubuntu:14.04 /bin/bash
    

    8.2 创建和挂载一个数据卷容器

    如果你有一些持久性的数据并且想在容器间共享,或者想用在非持久性的容器上,最好的方法是创建一个数据卷容器,然后从此容器上挂载数据。
    创建数据卷容器

    $ sudo docker run -t -i -d -v /test --name test ubuntu:14.04 echo hello
    

    使用—volumes-from选项在另一个容器中挂载 /test 卷。不管 test 容器是否运行,其它容器都可以挂载该容器数据卷,当然如果只是单独的数据卷是没必要运行容器的。

    $ sudo docker run -t -i -d --volumes-from test --name test1 ubuntu:14.04 /bin/bash
    

    添加另一个容器

    $ sudo docker run -t -i -d --volumes-from test --name test2 ubuntu:14.04 /bin/bash
    

    也可以继承其它挂载有 /test 卷的容器

    $ sudo docker run -t -i -d --volumes-from test1 --name test3 ubuntu:14.04 /bin/bash
    

    Docker学习笔记:容器数据管理,链接容器,构建私有库 - 图1

    8.3 备份、恢复或迁移数据卷

    备份

    $ sudo docker run --rm --volumes-from test -v $(pwd):/backup ubuntu:14.04 tar cvf /backup/test.tar /test
    tar: Removing leading `/' from member names
    /test/
    /test/b
    /test/d
    /test/c
    /test/a
    

    启动一个新的容器并且从test容器中挂载卷,然后挂载当前目录到容器中为 backup,并备份 test 卷中所有的数据为 test.tar,执行完成之后删除容器—rm,此时备份就在当前的目录下,名为test.tar。

    $ ls # 宿主机当前目录下产生了 test 卷的备份文件 test.tar test.tar
    

    恢复

    你可以恢复给同一个容器或者另外的容器,新建容器并解压备份文件到新的容器数据卷

    $ sudo docker run -t -i -d -v /test --name test4 ubuntu:14.04  /bin/bash $ sudo docker run --rm --volumes-from test4 -v $(pwd):/backup ubuntu:14.04 tar xvf /backup/test.tar -C / # 恢复之前的文件到新建卷中,执行完后自动删除容器 test/ test/b test/d test/c test/a
    

    8.4 删除 Volumes

    Volume 只有在下列情况下才能被删除:

  • docker rm -v删除容器时添加了-v选项

  • docker run —rm运行容器时添加了—rm选项

否则,会在/var/lib/docker/vfs/dir目录中遗留很多不明目录。
参考文档:

  • Managing Data in Containers
  • 深入理解Docker Volume(一)
  • 深入理解Docker Volume(二)

    二、链接容器

    docker 允许把多个容器连接在一起,相互交互信息。docker 链接会创建一种容器父子级别的关系,其中父容器可以看到其子容器提供的信息。

    9.1 容器命名

    在创建容器时,如果不指定容器的名字,则默认会自动创建一个名字,这里推荐给容器命名:

  • 1、给容器命名方便记忆,如命名运行 web 应用的容器为 web

  • 2、为 docker 容器提供一个参考,允许方便其他容器调用,如把容器 web 链接到容器 db

可以通过—name选项给容器自定义命名:

$ sudo docker run -d -t -i --name test ubuntu:14.04 bash              
$ sudo docker  inspect --format="{{ .Nmae }}" test
/test

注:容器名称必须唯一,即你只能命名一个叫test的容器。如果你想复用容器名,则必须在创建新的容器前通过docker rm删除旧的容器或者创建容器时添加—rm选项。

9.2 链接容器

链接允许容器间安全通信,使用—link选项创建链接。

$ sudo docker run -d --name db training/postgres

基于 training/postgres 镜像创建一个名为 db 的容器,然后下面创建一个叫做 web 的容器,并且将它与 db 相互连接在一起

$ sudo docker run -d -P --name web --link db:db training/webapp python app.py

—link :alias选项指定链接到的容器。
查看 web 容器的链接关系:

$ sudo docker inspect -f "{{ .HostConfig.Links }}" web
[/db:/web/db]

可以看到 web 容器被链接到 db 容器为/web/db,这允许 web 容器访问 db 容器的信息。
容器之间的链接实际做了什么?一个链接允许一个源容器提供信息访问给一个接收容器。在本例中,web 容器作为一个接收者,允许访问源容器 db 的相关服务信息。Docker
创建了一个安全隧道而不需要对外公开任何端口给外部容器,因此不需要在创建容器的时候添加-p或-P指定对外公开的端口,这也是链接容器的最大好处,本例为
PostgreSQL 数据库。
Docker 主要通过以下两个方式提供连接信息给接收容器:

  • 环境变量
  • 更新/etc/hosts文件

    环境变量

    当两个容器链接,Docker 会在目标容器上设置一些环境变量,以获取源容器的相关信息。
    首先,Docker 会在每个通过—link选项指定别名的目标容器上设置一个_NAME环境变量。如果一个名为 web
    的容器通过—link db:webdb被链接到一个名为 db 的数据库容器,那么 web
    容器上会设置一个环境变量为WEBDB_NAME=/web/webdb.
    以之前的为例,Docker 还会设置端口变量:

    $ sudo docker run --rm --name web2 --link db:db training/webapp env
    . . .
    DB_NAME=/web2/db
    DB_PORT=tcp://172.17.0.5:5432           
    DB_PORT_5432_TCP=tcp://172.17.0.5:5432  # <name>_PORT_<port>_<protocol> 协议可以是 TCP 或 UDP
    DB_PORT_5432_TCP_PROTO=tcp
    DB_PORT_5432_TCP_PORT=5432
    DB_PORT_5432_TCP_ADDR=172.17.0.5
    . . .
    

    注:这些环境变量只设置给容器中的第一个进程,类似一些守护进程 (如 sshd ) 当他们派生 shells 时会清除这些变量

    更新/etc/hosts文件

    除了环境变量,Docker 会在目标容器上添加相关主机条目到/etc/hosts中,上例中就是 web 容器。

    $ sudo docker run -t -i --rm --link db:db training/webapp /bin/bash
    root@aed84ee21bde:/opt/webapp# cat /etc/hosts
    172.17.0.7  aed84ee21bde
    . . .
    172.17.0.5  db
    

    /etc/host文件在源容器被重启之后会自动更新 IP 地址,而环境变量中的 IP 地址则不会自动更新的。

    三、构建私有库

    Docker 官方提供了 docker registry 的构建方法 docker-registry

    10.1 快速构建

    快速构建 docker registry 通过以下两步:

  • 安装 docker

  • 运行 registry:docker run -p 5000:5000 registry

这种方法通过 Docker hub 使用官方镜像 official image from the Docker hub

10.2 不使用容器构建 registry

安装必要的软件

$ sudo apt-get install build-essential python-dev libevent-dev python-pip liblzma-dev

配置 docker-registry

sudo pip install docker-registry

或者 使用 github clone 手动安装

$ git clone https://github.com/dotcloud/docker-registry.git
$ cd docker-registry/
$ cp config/config_sample.yml config/config.yml
$ mkdir /data/registry -p
$ pip install .

运行

docker-registry

高级启动方式 [不推荐]

使用gunicorn控制:

gunicorn -c contrib/gunicorn_config.py docker_registry.wsgi:application

或者对外监听开放

gunicorn --access-logfile - --error-logfile - -k gevent -b 0.0.0.0:5000 -w 4 --max-requests 100 docker_registry.wsgi:application

10.3 提交指定容器到私有库

$ docker tag ubuntu:12.04 私有库IP:5000/ubuntu:12.04
$ docker push 私有库IP:5000/ubuntu

容器部署registry

$ sudo docker search  registry
$ sudo docker pull registry
$ sudo docker history registry
$ sudo docker run -itd --name=images -p8222:5000 registry
$ sudo docker tag liqingfei01/nginx.conf 127.0.0.1:8222/liqingfei01/nginx.conf
$ sudo docker push 127.0.0.1:8222/liqingfei01/nginx.conf
$ curl http://127.0.0.1:8222/v2/_catalog -k
{"repositories":["liqingfei01/nginx.conf"]}