Docker学习——数据管理、使用网络(三)

一、Docker 数据管理

这一章介绍如何在 Docker 内部以及容器之间管理数据,在容器中管理数据主要有两种方式:

  • 数据卷(Volumes)
  • 挂载主机目录 (Bind mounts)
数据卷
数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
1、数据卷 可以在容器之间共享和重用
2、对 数据卷 的修改会立马生效
3、对 数据卷 的更新,不会影响镜像
4、数据卷 默认会一直存在,即使容器被删除
注意: 数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的 数据卷 。

选择 -v 还是 -–mount 参数
Docker 新用户应该选择 --mount 参数,经验丰富的 Docker 使用者对 -v 或者 --volume
已经很熟悉了,但是推荐使用 --mount 参数。

创建一个数据卷
$ docker volume create my-volume
查看所有的 数据卷
$ docker volume ls
DRIVER              VOLUME NAME
local               8fa782a5d4b02bca37b4138d336d5653a46cd04a63b34523869a26e8a8a557a8
local               a7f5bed4ebf53a0a7873ca17ee5d18e97e90b7e9cc3ddda9f31b67a1e1ae2b38
local               b1cd114d2e846cefcb17eab4b0bbfd9eebfc461ed5d6b73c75c0d6fdc1d2aa8b
local               my-volume
在主机里使用以下命令可以查看指定 数据卷 的信息
$ docker volume inspect my-volume
[
    {
        "CreatedAt": "2018-11-05T17:31:07+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-volume/_data",
        "Name": "my-volume",
        "Options": {},
        "Scope": "local"
    }
]

启动一个挂载数据卷的容器
在用 docker run 命令的时候,使用 --mount 标记来将 数据卷 挂载到容器里。在一次docker run 中可以挂载多个 数据卷 。
下面创建一个名为 web 的容器,并加载一个 数据卷 到容器的 /webapp 目录。
$ docker run -d -P \
--name web \
# -v my-volume:/wepapp \
--mount source=my-volvolume,target=/webapp \
training/webapp \
python app.py

查看数据卷的具体信息
在主机里使用以下命令可以查看 web 容器的信息
$ docker inspect web
数据卷 信息在 "Mounts" Key 下面
 "Mounts": [
            {
                "Type": "volume",
                "Name": "my-volvolume",
                "Source": "/var/lib/docker/volumes/my-volvolume/_data",
                "Destination": "/webapp",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],
删除数据卷
$ docker volume rm my-volume
数据卷 是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷 ,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷 。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。

无主的数据卷可能会占据很多空间,要清理请使用以下命令
$ docker volume prune
挂载主机目录
挂载一个主机目录作为数据卷
使用 --mount 标记可以指定挂载一个本地主机的目录到容器中去。
$ docker run -d -P \
--name web \
# -v /src/webapp:/opt/webapp \
--mount type=bind,source=/src/webapp,target=/opt/webapp \
training/webapp \
python app.py
上面的命令加载主机的 /src/webapp 目录到容器的 /opt/webapp 目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。

本地目录的路径必须是绝对路径,以前使用 -v 参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹,现在使用 --mount 参数时如果本地目录不存在,Docker 会报错。
Docker 挂载主机目录的默认权限是 读写 ,用户也可以通过增加 readonly 指定为 只读 。
$ docker run -d -P \
--name web \
--mount type=bind,source=/home,target=/opt/webapp,readonly \
training/webapp \
python app.py
加了 readonly 之后,就挂载为 只读 了。如果你在容器内 /opt/webapp 目录新建文件,会显示如下错误
/opt/webapp # touch new.txt
touch: new.txt: Read-only file system
查看数据卷的具体信息
在主机里使用以下命令可以查看 web 容器的信息

$ docker inspect web
挂载主机目录 的配置信息在 "Mounts" Key 下面
"Mounts": [
{
"Type": "bind",
"Source": "/src/webapp",
"Destination": "/opt/webapp",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
挂载一个本地主机文件作为数据卷
--mount 标记也可以从主机挂载单个文件到容器中
$ docker run --rm -it \
# -v $HOME/.bash_history:/root/.bash_history \
--mount type=bind,source=$HOME/.bash_history,target=/root/.bash_history \
ubuntu:17.10 \
bash
root@2affd44b4667:/# history
1 ls
2 diskutil list
这样就可以记录在容器输入过的命令了。

二、使用网络

外部访问容器
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。

当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。


$ docker run -d -P training/webapp python app.py
$ docker container ls -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bc533791f3f5 training/webapp:latest python app.py 5 seconds ago Up 2 seconds 0.0.0.0:49155->5000/tcp nostalgic_morse
使用 docker container ls 可以看到,本地主机的 49155 被映射到了容器的 5000 端口。此时访问本机的 49155 端口即可访问容器内 web 应用提供的界面。
同样的,可以通过 docker logs 命令来查看应用的信息。
$ docker logs -f nostalgic_morse
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
120.37.155.181 - - [05/Nov/2018 12:09:22] "GET / HTTP/1.1" 200 -
120.37.155.181 - - [05/Nov/2018 12:09:22] "GET /favicon.ico HTTP/1.1" 404 -
-p 则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。
支持的格式有 ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort 。

映射所有接口地址
使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口,可以执行
$ docker run -d -p 5000:5000 training/webapp python app.py
此时默认会绑定本地所有接口上的所有地址。

映射到指定地址的指定端口
可以使用 ip:hostPort:containerPort 格式指定映射使用一个特定地址,比如 localhost 地址127.0.0.1
$ docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py

映射到指定地址的任意端口
使用 ip::containerPort 绑定 localhost 的任意端口到容器的 5000 端口,本地主机会自动分
配一个端口。
$ docker run -d -p 127.0.0.1::5000 training/webapp python app.py
还可以使用 udp 标记来指定 udp 端口
$ docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py

查看映射端口配置
使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址
$ docker port nostalgic_morse 5000
127.0.0.1:49155.
注意:
容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量,Docker还可以有一个可变的网络配置。)
-p 标记可以多次使用来绑定多个端口
例如
$ docker run -d \
-p 5000:5000 \
-p 3000:80 \
training/webapp \
python app.py
容器互联
如果你之前有 Docker 使用经验,你可能已经习惯了使用 --link 参数来使容器互联。
随着 Docker 网络的完善,强烈建议大家将容器加入自定义的 Docker 网络来连接多个容器,而不是使用 --link 参数。

新建网络
下面先创建一个新的 Docker 网络。
$ docker network create -d bridge my-net-wwx
-d 参数指定 Docker 网络类型,有 bridge overlay 。其中 overlay 网络类型用于Swarm mode,在本小节中你可以忽略它。

连接容器
运行一个容器并连接到新建的 my-net 网络
$ docker run -it --rm --name busybox1 --network my-net-wwx busybox sh
打开新的终端,再运行一个容器并加入到 my-net 网络
$ docker run -it --rm --name busybox2 --network my-net-wwx busybox sh
再打开一个新的终端查看容器信息
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b47060aca56b busybox "sh" 11 minutes ago Up 11 minutes busybox2
8720575823ec busybox "sh" 16 minutes ago Up 16 minutes busybox1
下面通过 ping 来证明 busybox1 容器和 busybox2 容器建立了互联关系。
在 busybox1 容器输入以下命令
/ # ping busybox2
PING busybox2 (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.072 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.118 ms
用 ping 来测试连接 busybox2 容器,它会解析成 172.19.0.3 。
同理在 busybox2 容器执行 ping busybox1 ,也会成功连接到。
/ # ping busybox1
PING busybox1 (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.064 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.143 ms
这样, busybox1 容器和 busybox2 容器建立了互联关系。

Docker Compose
如果你有多个容器之间需要互相连接,推荐使用 Docker Compose。
配置 DNS
如何自定义配置容器的主机名和 DNS 呢?秘诀就是 Docker 利用虚拟文件来挂载容器的 3 个相关配置文件。
在容器中使用 mount 命令可以看到挂载信息:
$ mount
/dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ...
/dev/disk/by-uuid/1fec...ebdf on /etc/hosts type ext4 ...
tmpfs on /etc/resolv.conf type tmpfs ...
这种机制可以让宿主主机 DNS 信息发生更新后,所有 Docker 容器的 DNS 配置通过
/etc/resolv.conf 文件立刻得到更新。

配置全部容器的 DNS ,也可以在 /etc/docker/daemon.json 文件中增加以下内容来设置。
{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}
这样每次启动的容器 DNS 自动配置为 114.114.114.114 和 8.8.8.8 。使用以下命令来证明其已经生效。
$ docker run -it --rm ubuntu:17.10 cat etc/resolv.conf
nameserver 114.114.114.114
nameserver 8.8.8.8
如果用户想要手动指定容器的配置,可以在使用 docker run 命令启动容器时加入如下参数:
-h HOSTNAME 或者 --hostname=HOSTNAME 设定容器的主机名,它会被写到容器内的/etc/hostname 和 /etc/hosts 。但它在容器外部看不到,既不会在 docker container ls 中显示,也不会在其他的容器的 /etc/hosts 看到。
--dns=IP_ADDRESS 添加 DNS 服务器到容器的 /etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。

--dns-search=DOMAIN 设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的主机时,DNS 不仅搜索 host,还会搜索 host.example.com 。
注意:如果在容器启动时没有指定最后两个参数,Docker 会默认用主机上的/etc/resolv.conf 来配置容器。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏草根专栏

Docker & ASP.NET Core (1):把代码连接到容器

这样做的好处就是可以节省硬盘空间,也利于复用等等。因为Docker基于镜像创建容器的时候,其镜像是共享的;而且镜像里面的层如果已存在,也无需再下载。

13920
来自专栏纯洁的微笑

Docker(四):Docker 三剑客之 Docker Compose

前两篇文章我们介绍了 Dockerfile 的使用Docker(二):Dockerfile 使用介绍,我们知道使用一个 Dockerfile 模板文件可以定义一...

44230
来自专栏分布式系统和大数据处理

基于Docker的持续集成方案(安装docker) - Part.2

Docker是近几年非常流行的一项技术,我也花了一点时间研究了一下。这篇文章简单地记录一下如何在Linux(CentOS 7)系统上安装Docker,并概述了最...

17840
来自专栏遊俠扎彪

Windows下使用pyinstaller制作exe(py2exe)

配置python环境变量,一般从http://www.python.org/下载完python的编译解释器,只要正常安装成功,会自动配好。

238100
来自专栏IT笔记

Docker学习之搭建JavaWeb环境进阶篇

上一篇文章中,简单了学习了一下在Docker环境中搭建JavaWeb环境,其实这时候已经是一个全新的镜像了,就是我们的Ghost系统一样,装配了各式各样的软件一...

35770
来自专栏散尽浮华

CentOS7下安装Docker-Compose操作记录

Docker-Compose是一个部署多个容器的简单但是非常必要的工具.安装Docker-Compose之前,请先安装 python-pip

11020
来自专栏python爬虫实战之路

docker配置redis集群和scrapyd服务

Redis集群的配置方式我们上一篇已经介绍过了,而且使用Dockerfile配置文件我们也介绍了,不过介绍的并不详细,可能有些人看不明白,这篇我们再介绍一些Do...

16530
来自专栏编程坑太多

跟我一起学docker(七)--网络

18760
来自专栏古时的风筝

Docker:镜像操作和容器操作

镜像操作 列出镜像: $ sudo docker images REPOSITORY TAG IMAGE ID...

235100
来自专栏编程坑太多

『中级篇』构建自己的Docker镜像(16)

PS:为啥推荐用Dockerfile的方式,因为文件可以随便编辑,如果你用容器的话,你发给别人如何发麻烦不?还是单文件方便吧。

21460

扫码关注云+社区

领取腾讯云代金券