安装Docker
- 系统版本:CentOS 7 64bit
- 内核版本:3.10.0-229.el7.x86_64
- Docker版本:docker-1.8.2-10.el7.centos.x86_64
安装Docker1
2
3
4$> yum install docker
$> docker -v
Docker version 1.8.2-el7.centos, build a01dc02/1.8.2
基础概念
镜像(image)
- 镜像(image)是容器(container)运行时的只读模板,一个镜像(image)由多个只读层(read-only layer)组成。(可借用Photoshop的图层概念方便理解)
- Docker使用统一文件系统(union file system)将多个只读层(read-only layer)整合成一个独立的文件系统。
- 镜像(image)是Docker的构造部分。
图片来源
容器(container)
- Docker利用容器(container)来运行应用,容器(container)包含应用运行时所需的所有环境。
- 容器(container)是在镜像(image)的基础上创建而来,不同容器(container)间是相互隔离的。
- 容器(container) = 镜像(image) + 可读写层(read-write layer)
可读写层位于镜像的上层,是Docker的最上层 - 容器(container)中应用的进程对文件进行的创建、修改和删除等操作都是作用于可读写层(read-write layer)
- 容器(container)可运行、开始、停止、移动、删除。
- 容器(container)是Docker的运行部分。
仓库(repository)
- 仓库(repository)为存放镜像(image)的地方。
- 仓库(repository)分公有仓库和私有仓库。目前最大的公有仓库为Docker Hub
- 仓库(repository)是Docker的分发部分。
Namespace
Namespace是Linux Kernel提供的一种内核级别的资源隔离机制。Linux的地址空间分为user space和kernel space,每个进程在user space中独立拥有自己的地址空间且进程间互相隔离不可知。当进程需要使用到kernel相关的资源时都是通过调用kernel api进入kernel space使用kernel提供的服务(从用户态切换到内核态)。进程在user space中是相互独立隔离的,但在kernel space则是共享内核资源的,内核中有许多全局共享使用的资源,如IP、路由表、hostname、init进程、PID和GID等等。为了在kernel space中对内核全局资源(IP、PID等)实现隔离,Linux Kernel提供了Namespace机制。
mount namespace是最早出现的namespace,于2002年开始产生,用于隔离文件系统相关资源。随着container的产生与发展,截止kernel 3.8
已存在6
个不同类型的namespace,用于隔离不同的内核全局资源。
- UTS Namespace
UTS Namespace(UNIX Time-sharing System),用于隔离hostname和domain name。Docker容器拥有独立的UTS Namespace,默认使用CONTAINER ID作为hostname。 - Mount Namespace
Mount Namespace通过隔离文件系统挂载点实现隔离文件系统,不同Mount Namespace中的文件结构发生变化互不影响。在创建Mount Namespace时会将当前文件结构复制给新的Mount Namespace,新的Mount Namespace中的所有mount操作仅对此Mount Namespace起作用。 - IPC Namespace
IPC Namespace(Inter-Process Communication),IPC是Linux进程间通信的一种方式,IPC有共享内存、命名管道等方法实现进程间的相互通信。隔离IPC后,只有在同一个IPC Namespace下的进程才能直接通信。 - PID Namespace
PID Namespace,主要就用于隔离PID。每个PID Namespace的第一个进程为PID=1
,功能和init进程一样,比如接管孤儿进程等。
Namespace允许嵌套,每个Namespace只能影响自身Namespace和子Namespace。 - Network Namespace
Network Namespace,用于网络资源的隔离,如:网络设备、IP、路由表、iptables和端口(socket)等等。 - User Namespace
User Namespace,用于隔离UID、GID和秘钥等资源。
CGroups
CGroups是Linux Kernel提供的一种限制、记录资源的机制,所限制的资源包括CPU、Memory、IO等等。
CGroups通过VFS和上层进行交互,CGroups自定义伪文件系统并定义用于限制各资源的文件。CGroups通过挂载伪文件系统,设置、读取用于限制各资源的文件来限制任务对资源的使用。
CGroups提供4
个主要功能:
- Resource Limitation(资源限制):例如限制某程序最多能使用的内存空间、只能使用CPU的哪些核心等等。
- Prioritization(优先级分配):设置优先级,优先级越高能获得越多的资源。
- Accounting(资源统计):统计资源使用量,主要目的用于计费。
- Control(进程控制):能对进程组执行挂起、恢复等操作。
CGroups基础概念:
- task(任务):表示一个系统进程。每个子系统目录下会有
tasks
文件(例如memory子系统:/sys/fs/cgroup/memory/tasks
),文件内容为限制的进程PID。 - control group(控制组):CGroups对资源的限制以control group(控制组)为单位进行。一个任务加入某control group,表示任务需要按照此control group的限制规则来使用资源。
- subsystem(子系统):subsystem(子系统)既资源控制器。不同subsystem(子系统)对不同资源进行限制,目前CGroups有以下subsystem(子系统)
/sys/fs/cgroup/
:- blkio:限制块设备(磁盘、SSD、光盘)的IO。
- cpu:控制task(任务)对CPU的使用。
- cpuacct:自动生成task(任务)使用cpu的报告。
- cpuset:为task(任务)分配独立cpu(多核)和内存。
- devices:控制task(任务)是否允许访问设备。
- memory:控制task(任务)能使用多少内存并自动生成使用报告。
- freezer:挂起或恢复task(任务)
- net_cls:使用classid标记网络数据包
- hugetlb:对HugeTLB系统进行限制
- perf_event:运行task(任务)进行统一性能测试
- hierarchy(层级树):hierarchy由control group以树状目录结构,每个hierarchy通过绑定对应的subsystem进行资源调度。一个系统可存在多个hierarchy。
关系图如下
整个灰色框是一个hierarchy
/cpu_mem_cg
包含cpu
和memory
的两个subsystem(表明一个hierarchy可包含多个subsystem)
/cg1
、/cg2
是不同的control group
/cg1
、/cg2
目录下会有一个tasks
文件,里面存放属于此control group的task(tasks文件内容为PID)
图片来源
AUFS
上面在镜像(image)中提到Docker使用统一文件系统(union file system)将多个只读层(read-only layer)整合成独立的文件系统。更加具体来说Docker是使用一种名为AUFS(Advance union file system)的union file system。UFS有很多种,比如:aufs、btrfs、vfs和devicemapper等等。简单而言,UFS就是将不同路径的目录联合挂载到同一个目录下。
AUFS特性:
- 联合
可将多个目录联合挂载到同一个目录下。只显示联合目录内容并不改变源目录。
mount
挂载时,越写在前面的目录优先级越高(若多目录中存在相同名称的文件则挂载优先级高目录下的文件)。默认第一个目录权限为rw
,之后的目录权限都为ro
。 - branch
各个需要被联合(union)的子目录,Docker中也可理解为层(layer)。 - copy on write
若需要对联合目录下的内容做修改时,查找已union的branch中是否存在此文件,若存在则选择可写(rw)且优先级最高的branch并将文件copy到此branch后再修改。 - whiteout
用于隐藏下层branch文件。在上层目录创建.wh.,可隐藏下层的 文件。
通过具体实例了解AUFS:
由于CentOS 7默认并不支持AUFS而且要安装也比较麻烦(CentOS系列实现分层镜像用的是DeviceMapper技术,Ubuntu使用AUFS实现),所以实验环境在Ubuntu 14.04上进行,Ubuntu默认没安装AUFS,需要先安装1
$> sudo apt-get install aufs-tools
先创建4
个目录:ro_a
、ro_b
、rw_c
和union
。创建2
个文件:ro_a/a.txt
、ro_b/b.txt
1 | $> tree |
将目录rw_c
、ro_a
和ro_b
union mount到union
目录。第一个branch为rw_c
(可读写),第二、三分别为ro_a
、ro_b
(只读)
成功union mount后在union
目录可看到其余目录的文件。1
2
3
4
5
6
7
8
9
10
11
12
13$> sudo mount -t aufs -o br=rw_c=rw:ro_a=ro:ro_b=ro none union
$> tree
.
├── ro_a
│ └── a.txt
├── ro_b
│ └── b.txt
├── rw_c
└── union
├── a.txt
└── b.txt
4 directories, 4 files
对union mount后的文件union/b.txt
进行修改。AUFS会查找优先级高且可读写的branch进行操作(rw_c
),而且由于copy on write特性会将源文件ro_b/b.txt
文件copy到rw_c
目录下再做修改。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23$> echo 'aufs test' >> union/b.txt
$> tree
.
├── ro_a
│ └── a.txt
├── ro_b
│ └── b.txt
├── rw_c
│ └── b.txt
└── union
├── a.txt
└── b.txt
4 directories, 5 files
#源branch保持不变
$> cat ro_b/b.txt
ro_b b.txt
#复制ro_b/b.txt到rw_c/b.txt并修改
$> cat rw_c/b.txt
ro_b b.txt
aufs test
在rw_c
目录创建.wh.a.txt
文件用于屏蔽ro_a/a.txt
源目录文件ro_a/a.txt
并不会受到任何影响,但在union mount的目录union
下会无法看见union/a.txt
文件1
2
3
4
5
6
7
8
9
10
11
12$> touch rw_c/.wh.a.txt
$> tree
.
├── ro_a
│ └── a.txt
├── ro_b
│ └── b.txt
├── rw_c
│ └── b.txt
└── union
└── b.txt
4 directories, 4 files
DeviceMapper
Docker最开始是使用AUFS实现分层镜像,但由于AUFS并没有被接纳入Linux内核主干(被linus拒绝接纳多次),仅有Ubuntu对AUFS支持导致兼容性差。对于非Ubuntu的系统为了解决此问题,使用了DeviceMapper代替AUFS实现分层镜像。
DeviceMapper有三个重要的基础概念:Mapped Device——>Mapping Table——>Target Device
- Mapped Device
映射出的逻辑设备。Mapped Device通过Mapping Table中的映射关系和Target Device建立映射。 - Mapping Table
保存Mapped Device逻辑地址的起始及范围、Target Device物理设备的地址偏移量及类型等信息。 - Target Device
底层设备。Target Device可以是实际的物理块设备,也可以是映射后的Mapped Device设备。
DeviceMapper在内核中通过模块化的 Target Driver 插件实现对 IO 请求的过滤或者重新定向等工作,当前已经实现的插件包括软Raid、加密、多路径、镜像、快照等。其中Thin Provisioning Snapshot是Docker使用的重要模块。
Thin Provisioning
Docker使用Thin Provisioning的Snapshot技术实现分层镜像,从而解决非Ubuntu系列Linux不原生支持AUFS的问题。
由于DeviceMapper的Thin Provisioning Snapshot挺复杂且还处于实验阶段,待我再研究清楚后补上。可参考此篇文章做详细了解。
Docker 镜像(images)
镜像(image)是Docker的重要构成部分,Docker运行容器(container)时需要本地存在相应的镜像(image)。镜像(image)可自己制作,也可从仓库(repository)中下载。
获取镜像
从Docker Hub上获取CentOS 7
的镜像1
2
3
4
5
6
7
8
9# 启动Docker进程
$> systemctl start docker.service / service docker start
# 查看公有仓库中的镜像
$> docker search centos / docker search ubuntu
# 下载镜像
$> docker pull docker.io/centos
$> docker pull ubuntu
删除镜像
1 | # 查看镜像 |
修改tag
1 | $> docker tag af88597ec24b ubuntu:14.04 |
修改/更新镜像
在ubuntu14.04
镜像上安装vim
启动容器(container)
1
$> docker run -ti ubuntu:14.04
安装vim
48febfe7fbd7
容器(container)ID,之后commit
更新需要用到1
root@48febfe7fbd7:/# apt-get install vim
使用commit更新镜像
1
2$> docker commit -m 'install vim' -a 'mogl' 48febfe7fbd7 ubuntu:14.04.vim
eb39a2d496eda77331a6f6efb041473125d40d3f7f51077b100604be3e3cdf39-m
:提交信息-a
:更新的用户信息48febfe7fbd7
:容器(container)ID。ID为容器(container)ID而并非镜像(image)ID
ubuntu:14.04.vim
:tag名称
查看修改结果
1
2
3
4
5$> docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 14.04.vim eb39a2d496ed 30 seconds ago 231 MB
docker.io/ubuntu latest af88597ec24b 3 days ago 187.9 MB
ubuntu 14.04 af88597ec24b 3 days ago 187.9 MB使用新镜像
1
$> docker run -it ubuntu:14.04.vim
导出镜像
将已有的镜像导出到本地1
$> docker save -o ubuntu14.04.vim.tar ubuntu:14.04.vim
导入镜像
导入使用docker save
导出的镜像1
$> docker load < ubuntu14.04.vim.tar
Dockerfile 创建镜像
使用Dockerfile创建镜像
Dockerfile一般包含四部分:
- 基础镜像
- 维护者信息
- 镜像操作指令
- 容器启动执行命令
Dockerfile指令:
- FROM
指定基础镜像,若本地缺少镜像则自动从公有库下载镜像
FROM
指定必须是Dockerfile的非注释第一个指令
若FROM
没有指定tag
,默认使用last
- MAINTAINER
维护者信息 - RUN
RUN
会在FROM
指定的镜像中执行命令,执行完后提交(commit)。docker run image
——>RUN command
——>docker commit container_id
后续RUN
都在之前RUN
已提交(commit)的镜像基础上进行。
RUN
的书写格式分两种:RUN command
(此方式运行在/bin/sh -c
的shell中)RUN ["command", "param1", "param2"]
- CMD
在容器(container)启动时添加一个默认命令。
一个Dockerfile只能有一个CMD
,若出现多个CMD
则只有最后一个生效。
若用户启动容器(container)时指定了运行的命令,则会覆盖掉 CMD 指定的命令。
CMD
和RUN
区别:
CMD
只在容器(container)启动时执行,在使用docker build
创建镜像时并不会执行。
RUN
只在docker build
创建镜像时执行,一旦创建完镜像,一切与RUN
无关。 - EXPOSE
对外映射端口 - ENV
设置环境变量 - ADD
ADD src dest
复制src
文件到容器dest
。src
可指定远程文件URLS。 - COPY
和ADD
作用相同,但src
不能指定远程文件。 - ENTRYPOINT
指定容器(container)启动后执行的命令,并且不可被docker run
提供的参数覆盖(CMD
可被覆盖) - VOLUME
创建挂载点 - USER
指定容器(container)运行时的用户/UID(CMD
、RUN
、ENTRYPOINT
使用USER
指定的用户运行) - WORKDIR
指定CMD
、RUN
、ENTRYPOINT
的工作目录 - ONBUILD
1 | $> mkdir centos7_nginx && cd centos7_nginx |
Docker 容器(container)
容器(container)是应用及应用运行时所需的环境。
创建并启动容器
使用docker run
创建并启动容器。1
2$> docker run -ti ubuntu:14.04 /bin/bash
root@f4bbade713e0:/#
创建并启动容器(container),启动Bash终端并运行用户进行交互
-t
:分配伪终端-i
:容器标准输入保持打开f4bbade713e0
:容器ID
docker run
其实是docker create
和docker start
的组合,即docker run = docker create + docker start
。这一点类似与Git中git pull
和git fetch
、git merge
的关系。
docker run
内部流程:
- 检查指定的镜像(images)是否存在本地,不存在则
docker pull
从公有库中下载镜像(images) docker create
使用镜像(images)创建容器(container),在镜像(images)的只读层(read-only layer)上(镜像栈顶部)添加一层可读写层(read-write layer)- 从宿主机接口桥接虚拟接口到容器(container)中并从地址池分配IP给容器(container)
docker start
启动应用进程
启动已停止容器
当用docker run
创建并启动容器(container)后,退出容器(container)则容器处于Existed
状态。可用docker start
来启动此容器。
查看退出容器(container)
注意STATUS,此时为Existed状态1
2
3$> docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4bbade713e0 ubuntu:14.04.vim "/bin/bash" 46 seconds ago Exited (0) 2 seconds ago high_brattain启动已停止容器(container)
1
2
3
4
5
6$> docker start f4bbade713e0
f4bbade713e0
$> docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4bbade713e0 ubuntu:14.04.vim "/bin/bash" 23 minutes ago Up 24 seconds high_brattain进入启动后的容器(container)
docker attach
使用docker attach
命令进入容器(container),若直接Ctrl + d
退出时容器(container)会自动停止(UP
——>Existed
)。若要退出容器并保持容器运行则需要按Ctrl + p + q
1
2$> docker attach f4bbade713e0
root@f4bbade713e0:/#docker exec
docker exec
命令也可进入容器(container)且直接Ctrl + d
退出后容器不会停止1
2$> docker exec -it f4bbade713e0 /bin/bash
root@f4bbade713e0:/#
导出容器
docker export
1
2
3
4
5
6$> docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4bbade713e0 ubuntu:14.04.vim "/bin/bash" 47 minutes ago Exited (0) 17 minutes ago high_brattain
dfc9ce350449 centos:nginx "/bin/bash" 7 hours ago Exited (0) 49 minutes ago cocky_colden
$> docker export f4bbade713e0 > ubuntu14.04.vim.tar
导入容器
docker import
1
$> cat ubuntu14.04.vim.tar | docker import - ubuntu:14.04.vim.import
删除容器
docker rm
(删除镜像是docker rmi
)1
2
3
4
5
6
7
8
9
10
11$> docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4bbade713e0 ubuntu:14.04.vim "/bin/bash" 47 minutes ago Exited (0) 17 minutes ago high_brattain
dfc9ce350449 centos:nginx "/bin/bash" 7 hours ago Exited (0) 49 minutes ago cocky_colden
$> docker rm f4bbade713e0
f4bbade713e0
$> docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dfc9ce350449 centos:nginx "/bin/bash" 7 hours ago Exited (0) 54 minutes ago cocky_colden
Docker 数据管理
Docker管理数据主要有两种方式:
- 数据卷(Data volume)
- 数据卷容器(Data volume container)
数据卷(Data Volume)
为了能保存和共享容器(container)间的数据,Docker提出数据卷(Data Volume)的概念。
- 可绕过统一文件系统(union file system),数据以文件或目录形式保存在宿主机文件系统上,供多个容器(container)之间共享与重用数据。
- 对数据卷(Data Volume)的修改立即生效
- 更新数据卷(Data Volume)不影响镜像(images)
- 数据卷(Data Volume)只要有容器(container)使用就会一直存在
创建数据卷(Data Volume)
创建数据卷(Data Volume)有两种方式:
在Dockerfile中使用
VOLUME
指定1
VOLUME /path/to/dir
在
docker run
执行时使用-v
参数指定创建数据卷
1
2$> docker run -it -v /data/docker_volume/ ubuntu:14.04 /bin/bash
root@24eb5121c1e4:/#获取数据卷在宿主机上对于的路径
1
2
3
4
5
6
7
8
9
10
11
12
13$> docker inspect 24eb5121c1e4
... ...
"Mounts": [
{
"Name": "ec85ea5ebcf1317001d251030c15d666917862757272fa2998c0b111141917b8",
"Source": "/var/lib/docker/volumes/ec85ea5ebcf1317001d251030c15d666917862757272fa2998c0b111141917b8/_data",
"Destination": "/data/docker_volume",
"Driver": "local",
"Mode": "",
"RW": true
}
],
... ...
挂载宿主目录作为数据卷(Data Volume)
创建数据卷(Data Volume)后还需要用docker inspect
查找对于的宿主目录比较麻烦,直接挂载宿主目录到容器(container)中能方便数据的管理。1
$> docker run -it -v /data/docker_volume:/www ubuntu:14.04 /bin/bash
将宿主机上的/data/docker_volume
目录挂载到容器(container)的/www
目录。
- 宿主目录必须为绝对路径
- 挂载到容器(container)中的目录(
/www
)默认为rw
。可设置挂载为只读-v /data/docker_volume:/www:ro
数据卷容器(Data Volume Container)
数据卷容器(Data Volume Container),即容器(container)创建了数据卷(Data Volume),此数据卷(Data Volume)专提供给其他容器(container)进行挂载,数据卷容器常用于容器(container)间共享持续更新数据。
创建数据卷容器
创建一个数据卷容器(Data Volume Container)并命名为dbdata
。(数据卷容器完全可不运行,避免浪费资源)
1
$> docker run -v /data/dbdata --name dbdata ubuntu:14.04 echo "Data-only container"
-v /data/dbdata
:创建数据卷(Data Volume)--name dbdata
:命名此容器(container)为dbdata
ubuntu:14.04
:指定镜像(image)。一般如果用作数据库的话并不会使用系统镜像或最小化镜像(busybox/scratch),而是直接使用数据库镜像。echo "Data-only container"
:指定容器执行的命令。作用有二:其一是容器执行完命令后自动退出,数据卷容器不运行;其二是当使用docker ps -a
命令查看容器时方便指定容器的用途
共享数据卷容器的数据卷
使用--volumes-from
挂载容器(container)中的数据卷(Data Volume)到自身容器(container)中。
1
2
3
4$> docker run -it -d --volumes-from dbdata --name db1 centos:7 /bin/bash
[root@a29120ba32fa /]# ll /data/
total 0
drwxr-xr-x. 2 root root 36 Jan 12 07:26 dbdata
备份、恢复数据卷
备份数据卷
1
$> docker run --rm --volumes-from dbdata -v $(pwd):/data/backup ubuntu:14.04 tar zcf /data/backup/backup.tar.gz /data/dbdata
docker run --rm
:创建并运行一个新容器(container),--rm
表示执行完命令后自动删除该容器--volumes-from dbdata
:从名为dbdata
的数据卷容器中挂载其数据卷到到新容器上(dbdata
数据卷容器上的数据卷为/data/dbdata
,就是备份此数据卷)-v $(pwd):/data/backup
:将宿主机上的当前目录$(pwd)
挂载到新容器的/data/backup
目录ubuntu:14.04
:新容器是基于ubuntu:14.04
镜像创建的tar zcf /data/backup/backup.tar.gz /data/dbdata
:将新容器中/data/dbdata
数据卷目录进行打包压缩备份成/data/backup/backup.tar.gz
恢复数据卷
创建一个带数据卷的新容器,并将备份的数据卷数据恢复1
2$> docker run -it -d -v /data/dbdata --name recover_db ubuntu:14.04 /bin/bash
$> docker run --rm --volumes-from recover_db -v $(pwd):/data/backup ubuntu:14.04 tar zxf /data/backup/backup.tar.gz -C /
删除数据卷
数据卷只要有容器使用便会一直存在,而且在将用到某数据卷的所有容器删除后数据卷并不会自动被删除。若要彻底删除数据卷必须在删除最后一个还挂载着它的容器时使用docker rm -v
命令来指定同时删除关联的容器。
docker run --rm
在执行完命令后会自动删除容器,另外也会取消该容器和数据卷的关系。
Docker 网络配置
容器互联
Docker允许容器(container)间相互连接以交换信息。容器互联需要用到容器名称,所以在启动容器时需要使用–name参数为容器自定义容器名。
容器互联使用--link
参数建立连接。
创建数据库容器
使用数据库镜像创建数据库容器,将新容器命名为db
1
$> docker run -d --name db docker.io/mysql
创建web应用容器并建立连接
--link
参数的格式为--link name:alias
,name
是要连接容器的名称,alias
是此连接的别名。1
$> docker run -d -P --name web --link db:web_to_db ubuntu:14.04
Docker 网络模式
容器(container)有4种网络模式,可在启动容器时通过--net
参数指定:docker run --net=network_mode
- host模式:
docker run --net=host
- container模式:
docker run --net=container:container_name/container_id
- bridge模式:
docker run
/docker run --net=bridge
,bridge模式为默认模式 - none模式:
docker run --net=none
host 模式
host模式,在容器启动时并不会独立创建Network Namespace给容器而是和宿主机共用一个Network Namespace。简单来说就是容器并没有一个隔离的网络环境而是使用宿主机的网络环境。host模式中除了网络外其余的资源都是实现隔离的。
container 模式
container模式,指定新建的容器和已存在的容器共享一个Network Namespace,新建的容器没有自身的网卡和IP而是和指定的容器共享IP和端口范围。container模式中除了网络外其余的资源也是隔离的,两个容器间的进程可通过lo
设备通信。
none 模式
none模式,容器拥有独立的Network Namespace但没有进行任何的网络设置,容器内只有lookback
设备,没有网卡、IP和路由等信息。用户可根据需求进行添加和配置。
bridge 模式
bridge模式,此模式为容器的默认模式。
当Docker启动时,Docker会在宿主机上创建docker0
虚拟接口,并会随机分配一个本地未被占用的私有IP地址(常见地址172.17.42.1/16
)。
当容器(container)启动时,会创建一个veth pair
设备,veth pair
是一对虚拟接口。从一个veth
接口发出的数据必会直接到达此接口的peer veth
。由于此特性,veth pair
常用于连接两个网络接口,两个接口设备之间会形成虚拟链路用于完成数据的进出。Docker创建的veth pair
,一端为容器(container)内的网络接口,通常是eth0
,eth0
的IP与docker0
的IP属于同一网段确保通信正常;另一端则在宿主机上并被挂载到docker0
设备上,通常为vethxxxxxxx
。
Docker网络设备关系如下图所示,图片来源
启动两个容器(container)后宿主机上网络设备情况:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16$> ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.42.1 netmask 255.255.0.0 broadcast 0.0.0.0
... ...
enp1s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.2.222 netmask 255.255.255.0 broadcast 10.0.2.255
... ...
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
... ...
veth273d670: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::d81b:1aff:fe8c:2850 prefixlen 64 scopeid 0x20<link>
... ...
veth490482d: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::f880:ebff:fe8c:e5bc prefixlen 64 scopeid 0x20<link>
... ...
通过brctl show
命令查看挂载在docker0
上的veth
的设备情况1
2
3
4$> brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242809a1ff9 no veth273d670
veth490482d
端口映射
端口映射用在bridge模式
随机端口映射
为了使外部能访问到容器(container)内,需要在宿主机和容器中做端口映射。
可在启动容器(container)时使用-P
参数进行端口映射,-P
参数能让Docker随机映射宿主机的49000~49900
的某个端口到容器(container)内部开放的端口。1
$> docker run -d -P ubuntu:14.04 python app.py
指定端口映射
-p
参数默认映射TCP
,若想映射UDP
则需指定-p 80:5225/udp
格式:-p hostPort:containerPort
、-p ip:hostPort:containerPort
1
2
3
4$> docker run --name nginx -it -d -p 80:5225 centos:nginx
$> docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5107099c0d1a centos:nginx "/bin/bash" 49 minutes ago Up 1 seconds 80/tcp, 0.0.0.0:80->5225/tcp nginx