docker笔记


docker

开源项目:诞生于2013年,dotCloud公司内部的业余项目,Go语言实现

集装箱:目标是实现轻量级的操作系统虚拟化方案,让用户不需要通过关心容器的管理,使得操作更加简便

docker和虚拟机/传统虚拟化的区别:

  • 传统的虚拟机:在硬件层实现虚拟化的
  • docker:在操作系统层面实现虚拟化,直接复用本地主机的操作系统

为什么要使用docker?

与传统虚拟化方式相比容器相比具有众多的优势

  • docker容器启动在秒级
  • docker对系统的利用率高,一台主机可以同时运行数千个docker容器
  • docker基本不消耗系统资源,使得运行在docker里面的应用的性能很高

其他优势

更快速的支付和部署,开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码

更高效的虚拟化,dicker容器的运行不需要额外的支持,它是内核级的虚拟化,因此可以实现更高的性能

更轻松的迁移和扩展:docker几乎可以在任意平台运行,比如物理机,虚拟机,公有云,私有云,个人电脑,服务器等

更简单的管理:使用docker只需要简单的修改,就可以替代以往大量的更新工作,所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理

特性              容器                        虚拟机
启动              秒级                        分钟级
硬盘的使用         一般MB                      一般GB
性能              接近原生                     弱于
系统支持量        单机支持若干上千个容器        一般几十个

docker中的基本概念:

  • 镜像(images):只读的模板,镜像可以用来创建容器
  • 容器(container):是使用镜像创建并运行的实例,可以简单的将容器看做是启动了的简化版的操作系统(可以看作是操作系统是因为里面包含root用户权限,进程空间,用户空间和网络空间,还包括运行在里面的应用程序)
  • 仓库(repository):集中存放镜像文件的地方,分为公有仓库和私有仓库

 

 

yum

yum provides ifconfig                            //查询ifconfig这个命令来自哪个服务(压缩包)

docker:

拉取镜像
docker pull images-name

查看当前系统中存在的镜像
docker images

docker命令选项

  • -i:可以交互输入
  • -t:打开伪终端
  • -d:后台运行

启动/停止容器运行
docker start/stop container-ID

导出已有的镜像到本地
docker save -o centos.tar centos

导入已有的镜像
docker load --input centos.tar

删除容器
docker rm container-ID

删除多个容器
docker rm -f container-ID container-ID

删除所有容器
docker rm $(docker ps -a -q)

删除镜像
docker rmi images-name

搜索公共镜像
docker search images-name

进入正在运行的容器
docker attach container-ID

更改镜像名称
docker tag container-ID 新的名称:标签

指定名称
docker run -it --name 名称 centos /bin/bash

create:创建容器,

run:运行容器

pause:挂机/暂停容器

unpause:取消暂停,继续运行容器

stop:发送sigterm停止容器

kill:发送sigkill快速停止容器

exec:在容器中启动新进程,通常需要使用“-it”参数

logs:显示容器启动进程的控制台输出,使用“-f”持续打印

rm:从磁盘删除容器

 

创建容器

1、通过基础镜像创建镜像,然后添加功能生成镜像

docker commit -m net-tools -a Shuai dbd37da37fed net-tools/centos:v2

  • -m:指定提交的描述信息
  • -a:指定镜像作者
  • dbd37da37fed:用来创建镜像的容器ID
  • net-tools/centos:指定要创建的目标镜像名
  • v2:指定镜像的TAG
[root@localhost ~]# docker commit -m net-tools -a Shuai dbd37da37fed net-tools/centos:v2
sha256:0073383914bf1d80a29c27628aebd09a63dee998ca0c00b0a6ae1224cd5f84ec
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
net-tools/centos v2 0073383914bf 6 seconds ago 300MB
ubuntu latest ea4c82dcd15a 4 weeks ago 85.8MB
centos latest 75835a67d134 5 weeks ago 200MB
[root@localhost ~]# docker run -it 0073383914bf
[root@6cd3891004eb /]# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.4 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:04 txqueuelen 0 (Ethernet)
RX packets 6 bytes 508 (508.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

 

2、通过docker build命令,通过dockfile文件的方式,生成镜像

 

关于镜像

1.分层

最小的镜像:hello-world
FROM scratch
scratch:指定/说明当前镜像搜索从0开始构建的镜像
COPY hello /
复制hello到根目录中
CMD ["/hello"]
执行hello

 

FROM 镜像名称(通常base镜像,基础镜像)
bash镜像:通常就是Linux的不同发行版本,构成用户空间,不依赖其他镜像,其他镜像用它扩展
1、从0开始的镜像,不依赖与其他镜像
2、通常包含Linux不同的发行版本
3、没有其他的软件程序在其中

 

系统各个层级之间的耦合关系:

普通虚拟化和容器虚拟化的区别:
解除耦合:
解耦                                        半解耦

 

docker的核心概念之:namespace
目的是docker有独立的ip,端口,路由等,隔离作用
六项隔离

  1. 主机名和域名:                                            UTS
  2. 信号量,消息列队和共享内存:               IPC
  3. 进程编号:                                                    PID
  4. 网络设备,网络栈,端口等:                   network
  5. 挂载点:                                                        mount
  6. 用户和组:                                                    user

可以直接在文件系统中查看指向不同的namespace号的文件
ls -l /proc/##/ns

Linux内核实现namespace主要目的是为了实现轻量级虚拟化此容器服务,在同一个nameserver下的进程可以彼此感知,而对外界的进程一无所知。在这种情况下,让容器中的进程产生错觉,仿佛自己置身于一个独立的系统环境,以此实现独立和隔离的目的

docker的核心概念之:cgroups
不仅可以将被namespace隔离的资源进行设置权重,计算使用量,操作进程启动停止等
是Linux内核提供的一种机制,可以根据特定的行为,把一系列的系统任务以及子任务整合/分离到按资源划分等级的不同组内,从而为系统资源管理提供一个统一的框架
可以限制,记录,隔离进程组所使用的物理资源(包括CPU,内存,IO等),为容器实现虚拟化提供了基本保证,是构建docker等一系列虚拟化管理工具的基础

cgroups的作用:
实现cgoups的主要目的是为不同用户层面的资源管理,提供一个统一化的接口,从单个进程的资源控制到操作系统层面的虚拟化
提供四大功能:

  1. 资源限制:cgoups可以对进程组使用的资源总额进行限制,比如设置应用运行时内存的上限,超出则发出警告
  2. 优先级分配:通过分配的cpu时间片数量以及硬盘IO带宽大小,实际上就是相当于控制了进程运行的优先级
  3. 资源统计:cgroups可以统计系统资源使用量,比如CPU使用时间,内存使用量等,适用于按量计费

镜像仓库

如何将自己创建的镜像进行共享
Dockerfile,共享该文件:需要传输文件,然后对方自己再次build
将镜像上传到公共的registry,其他主机直接下载
搭建私有的registry,只能给本地的docker host使用

镜像的命名:[images name] = [REPOSITORY] : [TAG]

运行容器:
docker run centos

两种方式进入容器:attach和exec

说明如下:

  • -it 以交互模式打开,执行bash,其结果就是打开了一个bash终端
  • 进入到容器中,容器的hostname 就是其"短ID"
  • 可以像在普通Linux中一样执行命令。ps -elf显示了容器启动进程     while   以及当前的   bash  进程
  • 执行 exit 退出容器,回到docker host。docker exec -it bash|sh 是执行exec最常用的方式

attach 与 exec的主要区别

attach 直接进入容器,启动命令的终端,不会启动新的容器

如果想直接在终端中查看启动命令的输出,用attach;其他情况使用exec

如果只是为了查看启动命令的输出,可以使用docker logs 命令

docker logs -f container-ID

容器运行相关的知识点:

  1. 当CMD 或 docker run命令行指定的命令运行结束时,容器停止
  2. 通过-d参数在后台运行
  3. 通过exec -it 可以进入容器并执行命令

指定容器的三种方式

  1. 短ID
  2. 长ID
  3. 容器名称。可通过  --name   为容器重命名

docker start
容器可能会因某种错误而停止运行,对于服务类容器,我们通常希望在这种情况下容器能够自动重启,启动容器时设置  --restart 就可以达到这个效果。
--restart=always 意味着无论容器因何种原因退出(包括正常退出),就立即重启,该参数的形式还可以是  --restart=on-failure:3   意思是如果启动进程退出代码非0,则重启容器,最多重启3次

内存限额:

容器内存包括两部分:物理内存和swap

在docker中可通过参数控制容器内存的使用量:
-m 或 --memory:设置内存的使用限额
--memory-swap:设置内存+swap的使用限额

<strong><span style="color: #000000;">指定该容器最多使用200M内存和100M的swap</span></strong>
docker run -it -m 200M --memory-swap=300M centos

默认情况下,两组参数值为1。表示对容器的内存和swap不限制

docker run -it -m 200M --memory-swap 300M progrium/stress --vm 1 --vm-bytes 280
vm 1:启动一个内存工作线程
--vm-bytes 280M:每个线程分配内存280M

限制容器使用CPU:

需要通过-c或者--cpu-shares设置容器使用CPU的权重。如果不指定则默认为1024
限制容器使用CPU取决于CPU share占所有容器CPU share总和的比例

限制容器的Block IO

磁盘的读写

docker中可以通过设置权重,限制bps和iops的方式控制容器读写磁盘的带宽

bps:每秒读写的数据量(byte per second)
iops:每秒IO的次数 (io per second )

默认情况下,所有容器都能够平等的读写磁盘。可以通过--blkio-weight参数改变容器blockIO的优先级

  • –-device-read-bps:限制读取某个设备的bps
  • –-device-write-bps:限制写入某个设备的bps
  • –-device-read-iops:限制读取某个设备的iops
  • –-device-write-iops:限制写入某个设备的iops
  • --blkio-weight:优先级,权重值
[root@localhost ~]# docker run -it --name testA --device-write-bps /dev/sda:30MB centos
[root@b0b1e003e11e /]# time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
800+0 records in
800+0 records out
838860800 bytes (839 MB) copied, 26.7244 s, 31.4 MB/s

real 0m26.757s
user 0m0.002s
sys 0m3.482s

对比不限速

[root@localhost ~]# docker run -it --name testB centos
[root@7011f4487e71 /]# time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
800+0 records in
800+0 records out
838860800 bytes (839 MB) copied, 13.0204 s, 64.4 MB/s

real 0m13.024s
user 0m0.014s
sys 0m12.043s

 

cgroup和namespace

cgroup:实现资源限额
namespace:空间隔离

每个容器会认为自己有一块独立的网卡,即使host上只有一块物理网卡。这样让容器看上去更像是一个独立的计算机

  1. 主机名和域名:                                            UTS
  2. 信号量,消息列队和共享内存:               IPC                      //让容器拥有自己的共享和信号量,来实现进程间的通信,而不会与host和其他的容器的ipc混淆
  3. 进程编号:                                                    PID
  4. 网络设备,网络栈,端口等:                   network
  5. 挂载点:                                                        mount
  6. 用户和组:                                                    user

docker run -h myhost -it centos
指定容器的主机名

ps axf
//可以看到所有进程的相关信息,包括container的进程信息

docker run -h myhost -it centos
ps axf              //只能看到容器内,自己本身的进程信息
//容器中拥有自己的一套PID,这就是PID namespace提供的功能

user namespace:让容器可以管理自己的用户,而host是不能看到容器中创建的用户的

 

docker 网络

[root@localhost ~]# docker network ls
NETWORKID         NAME    DRIVER    SCOPE
a12b893f6e9b      bridge   bridge   local
cf3f312b5f34      host     host     local
c7a91b209139      none     null     local

none网络:什么都没有的网络
docker run -it --network=none busybox

该网络只有lo网络内容,是一个封闭网络

作用:封闭意味着隔离,一些对安全性要求很高并且不需要联网的应用,就可以使用none网络。随机码的生成

host网络:连接到host网络的容器共享Dockerhost的网络栈,容器的网络配置与host完全一样。容器中可以看到host的所有网卡,并且hostname也是host的
作用:使用场景
性能好。网络传输效率得到最大的保留,如果容器对网络传输效率有高要求的话,可以选择host网络
缺点:不灵活,需要考虑端口冲突的问题

bridge网络:桥接

/ # ip l
/ # brctl show
/ # ip a
[root@localhost ~]# ifconfig docker0
[root@localhost ~]# docker network inspect bridge

自定义桥接网络

docker提供了三种user-defined网络驱动:bridge,overlay和macvlan
overlay和macvlan用于创建主机网络
通过bridge驱动创建类似默认的bridge网络:

docker network create --driver bridge my_net

brctl show

容器之间的连通

第一步:开启本地路由转发
第二部:设置容器添加新的网络连接
docker network connect container-name/ID container-name/ID
第三部:使用ping测试

查看docker网卡: docker  network  ls

查看docker IP:    ip  a

查看bridge 网卡: brctl  show

查看bridge网卡配置:docker  network  inspect  指定网卡名

创建 bridge网卡: docker  network  create  - - bridge  新建网卡名

(可增添选项 :- -subnet  指定网卡的网段      - -gateway   指定网卡指定的网关址)

删除网卡:docker  network  rm  指定网卡名

指定网卡来创建容器: docker  run  -itd  --network=网卡名  镜像名

(可增添选项 :--ip  指定容器的IP , 要求是:使用的网卡是 - -subnet 创建的)

添加网卡到指定容器中: docker  network  connect  指定的网卡  指定的容器名/id

查看防火墙的信息; iptables-save

 

容器之间的通信方式

三种方式进行通信

IP:容器之间使用同一个网络的网卡,那么他们就可以使用ip进行交互
//不灵活。虽然能够满足通信需求,但是在完成部署前,无法确定IP地址,需要在部署之后才能够指定访问的IP地址

docker DNS server:直接通过容器名称进行通信。有一个要求:必须通过自定义网络才可以相互访问

joined容器:使两个或多个容器共享一个网络栈,共享网卡和配置信息

[root@localhost ~]# docker run -itd --name=web1 httpd
[root@localhost ~]# docker run -it --network=container:web1  --name=web3 busybox

实际使用场景:

  1. 不同容器中的程序需要通过loopback高效快速的通信,比如web-server和app-server
  2. 希望监控其他容器的网络流量,比如运行在独立容器中的网络监控程序。

容器与外部世界的通信:

容器访问外部世界
外部世界访问容器

容器访问外部世界:

容器默认是可以访问外网
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
//如果网桥docker0收到来自127.0.0/16网卡的外出包,把该数据交给MASQUERADE处理,而MASQUERADE的处理方式是将包的原地址替换成host的地址转发出去,即做了一次地址转换

外部世界访问容器:端口映射

docker可以将对外提供服务的端口映射到host的某个端口,外网通过该端口访问容器,容器在启动的时候通过-p提供参数映射端口

docker run -itd -p 80 --name web1 httpd      //通过-p选项映射端口参数
docker ps -a                                                         //查看映射到host的端口
docker port web1                                                //查看映射到host的端口
curl http://

 

docker存储

docker为容器提供了两种存储数据的资源

Data volume:

对于整个镜像/容器环境

  1. 新数据直接存放在最上面的容器层
  2. 修改现有数据,先从镜像层将数据复制到容器层,修改后的数据直接保存在容器层中,而镜像层数据保持不变
  3. 如果多个层中有命名相同的文件,用户只能看到最上面那层中的文件。以上功能的实现,是基于Docker storage driver的存放数据资源方式,管理镜像层和容器层 docker支持多种storage driver:AUFS,Device Mapper,Btrfs,overlayFS,VFS等。他们都可以实现分层的架构,并且各自有不同的特性。docker在安装时会根据当前系统的配置选择默认的driver,而默认driver具有最好的稳定性 Ubuntu:AUFS,extfs redhat/centos:overlay2,xfs SUSE:Btrfs

持久化存储:

Data volume:本质上是Docker Host文件系统中的目录或文件,能够直接被mount到容器的文件系统中。
特点:

  1. Data volume是目录或文件,并不是没有格式化的磁盘(块设备)
  2. 容器可以读写volume中的数据
  3. volume数据可以被永久的保存,即使使用它的容器已经销毁

对于数据层存储和volume都可以用来存储数据,那么对于实际场景,应该如何选择:

  1. Database软件   VS   Database数据
  2. web应用   VS   应用产生的日志
  3. 数据分析软件   VS   input/output数据
  4. Apache server   VS  静态的HTML文件

前面的内容应该放在数据层中:应为这部分的内容是无状态的,应该作为镜像的一部分
后面的内容应该放在Data Volume中,因为这部分是需要持久化的数据,应该与镜像分开存放

在docker中提供了两种volume类型:bind mount 和 docker manged volume

bind mount:将host上已经存在的目录或文件mount到容器。默认挂载到容器中目录,容器对其中的文件是具有可读可写权限的。当然,可以通过设置,让容器对文件只读。

使用bind mount单个文件的场景:只需要向容器添加文件,不希望覆盖整个目录

优点:直观高效,易于理解
缺点:不灵活,限制了容器的可移植性

 

docker manged volume

与bind mount在使用上的区别:不需要指定mount源,直指定mount point即可

 

两种data volume的对比:

相同点:都是host文件系统中的某个路径(与容器进行交互的)
不同点:
                        bind mount             docker manged volume

volume位置              任意指定                /var/lib/docker/volumes/...
对现有mount
point的影响             隐藏并替换为volume       复制原有数据到volume
是否支持单个文件         支持                    不支持,只能是目录
权限控制                可修改                   均为读写权限,无控制
移植性                  移植性弱                 移植性强

容器和容器之间的数据 共享

volume container:给其他容器提供volume容器。并且它提供的卷可以是bind mout,也可以是docker manged volume

使用volume container的特点

与bind mount相比,不需要为每个容器都指定host path,所有路径都在vc当中定义好了,容器只需要与vc关联,实现了容器和host的解耦

使用vc的容器,他们的mount point都是一致的,有利于配置的规范和标准化,当然,也会有一定的局限性

构建镜像

data-pack

 

FROM busybox:latest
ADD htdocs /usr/local/apache2/htdocs                //ADD:将指定的
VOLUME /usr/local/apache2/htdocs

 

容器能够正确的读取volume中的数据,datapacked镜像中内容是自包含的,不依赖host来提供数据,所以具有很强的可移植性,所以,非常适合
只是静态数据的场景,比如:应用的配置信息,web server的静态文件

 

volume:创建,共享,使用
volume:备份,恢复,迁移,销毁

备份:

将镜像文件存放到/images目录中,然后定期备份该目录

恢复:

如果数据发生了损坏,直接将之前备份的数据拷贝到/imagess中就可以了

迁移:

首先停止registry容器,然后启动新版本容器并且mount原来的volume
注意:在启动新容器之间需要确保新版本的默认数据路径是否发生变化

删除/销毁

删除需谨慎。volume删除后的数据,是无法找回的
docker不会销毁bind mount,host负责删除数据的。如果想要删除volume,需要在删除容器是添加-v参数,则会将volume一并删除,前提是没有其他容器使用该volume,为了保证数据的安全

在删除容器同时删除volume:
docker rm -v vc_data         //容器必须停止运行
如果在删除容器时,没有使用-v选项,则会产生volume,那么可以使用命令查看系统中的所有volume
docker volume ls
然后进行删除操作
docker volume rm volume-name
如果确定当前环境中所有volume都没有被使用,可以进行批量删除
docker volume rm $(docker volume ls -q)

关于docker单主机存储总结

  1. docker为容器提供的存储资源:storage volume和data volume
  2. storage volume是用来对镜像层和容器进行管理的
  3. data volume包括:bind mount 和 docker mangeed volume
  4. bind mount实现了容器和host之间,容器和容器之间的数据共享
  5. volume container是就有良好可移植性的容器间的数据共享方式,尤其是镜像化:data-packe volume container
  6. 关于volume的备份,恢复,迁移,销毁

跨主机容器网络

macvlan:linux kernel模块,网卡的 虚拟化技术

跨主机容器访问

网卡的虚拟化技术:macvlan:linux kernel模块。

开启网卡的混杂模式:

[root@localhost ~]# ip link show ens33

2:

ens33: 
<BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000

link/ether 00:0c:29:be:e8:34 brd ff:ff:ff:ff:ff:ff

[root@localhost ~]# ip link set  ens33 promisc on

[root@localhost ~]# ip link show ens33

2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000

link/ether 00:0c:29:be:e8:34 brd ff:ff:ff:ff:ff:ff

两台都进行这个操作:

[root@localhost ~]# docker network create -d macvlan --subnet=172.16.86.0/24 --gateway=172.16.86.1 -o parent=ens33 mac_net1

f9478fb945582b5b022fc35dc241b484417a98fb561b93c0fc80f08ab20cf1a1

两台都进行这个操作,启动容器,另一台名字要变

[root@localhost ~]# docker run -itd --name bbox1 --ip=172.16.86.10 ==network mac_net1 busybox

&nbsp;

Docker network ls

Brctl show

通过以上查看结果发现:macvlan 不依赖linux bridge

在容器中使用ip a

查看网卡信息,会发现,容器eth0就是通过macvlan虚拟出来的与host主机ens33进行连接的。

 

添加(装载)一个模块

[roo t@localhost ~]# modprobe 8021q

[root@localhost ~]# modinfo 8021q

filename:       /lib/modules/3.10.0-514.el7.x86_64/kernel/net/8021q/8021q.ko

version:        1.8

license:        GPL

alias:          rtnl-link-vlan

rhelversion:    7.3

srcversion:     7E3D79395FFBC56AFC109DE

depends:        mrp,garp

intree:         Y

vermagic:       3.10.0-514.el7.x86_64 SMP mod_unload modversions

signer:         CentOS Linux kernel signing key

sig_key:        D4:88:63:A7:C1:6F:CC:27:41:23:E6:29:8F:74:F0:57:AF:19:FC:54

sig_hashalgo:   sha256

 

macvlan:网络的联通和隔离完全依赖VLAN,IP,subnet和路由,docker本身不做任何限制,用户可以像管理传统VLAN网络那样管理macvlan

 

firewall

  1. drop:丢弃所有进入的包,而不会出任何回应
  2. block:拒绝所有外部发起的链接,允许内部发起的链接
  3. public:允许指定的进入链接
  4. external:同public,处理伪装的进入链接,一般用于路由转发
  5. dmz:允许受限制的进入链接
  6. work:允许受信任的计算机被限制的进入链接
  7. home:同work,如果流量和ssh,dhcpv6-clinet等服务相关,则允许
  8. internal:同work,范围针对所有互联网用户
  9. trusted:信任所有链接
Last modification:July 6th, 2020 at 06:00 pm
如果觉得我的文章对你有用,请随意赞赏