docker从入门到入坟

文章目录

一、容器生态系统介绍

1.Docker核心技术

容器核心技术是指能够让Container在host运行起来的技术

1.1 容器规范

runtime spec
image format spec

OCI
容器不光是Docker,还有其他容器如CoreOS的rkt,为了保证容器生态的健康发展,保证不同的容器之间能够兼容,包含Docker,CoreOS,Google在内的若干公司共同成立了一个叫Open Container Initiative的组织,其目的是制定开放的容器规范

1.2 容器runtime

runtime是容器真正运行的地方,runtime需要跟操作系统kernel紧密协作,为容器提供运行环境

  • lxc
    Linux老牌的容器runtime,Docker最初以lxc作为runtime
  • runc
    Docker公司自己开发的容器runtime
  • rkt
    CoreOS的容器
1.3 容器管理工具

光有runtime还不够,用户得有工具来管理容器。容器管理工具对内与runtime交互,对外为用户提供interface

  • lxd
    lxc对应管理工具
  • docker engine
    runc的管理工具
  • rkt cli
    rkt的管理工具
1.4 容器定义工具

容器定义工具允许用户定义容器的内容和属性,这样容器就能够被保存、共享和重建。

  • Docker image
    docker image是docker容器的模板,runtime依据docker image来构建容器

    ​ centos_minimal

  • dockerfile
    dockerfil是包含若干命令的文本文件,可以通过这些命令来创建出docker image

    ​ Dickerfile对镜像再次定义的格式

  • ACI
    与docker image类似,coreos开发的rkt容器格式

1.5 Registry

容器是通过image创建的,需要有一个仓库来统一存放image,这个仓库就叫做registry

  • Docker Registry
    企业也可以用docker registry来构建私有registry
  • Docker Hub
    docker公司为公众提供托管Registry,类似github
  • Quay.io
    另一个公共托管Registry,类似docker hub
1.6 容器OS

容器OS是专门运行容器的操作系统,与常规OS相比,容器OS通常体积更小,启动更快,优化更好,容器运行效率更高

  • coreos

在这里插入图片描述

  • atomic

在这里插入图片描述

  • ubuntu core

在这里插入图片描述

2.Docker支持技术

2.1 容器网络

​ docker network
​ flannel
​ weave
​ calico

2.2 服务发现

​ etcd
​ consul
​ zookeeper

2.3 监控

​ docker ps/tpo/stats
​ docker stats API
​ sysdig
​ cAdvisor/Heapster
​ Weave Scope

2.4 数据管理

​ Rex-Ray

2.5 日志管理

​ docker logs
​ logspout

​ ELK

2.6 容器安全

​ OpenSCAP

3.Docker平台技术

3.1 容器编排引擎

​ docker swarm
​ kubernetes(google app engine 、 borg)
​ mesos+marathon

3.2 容器管理平台

​ Rancher
​ ContainerShip

3.3 基于容器的PaaS

​ Deis
​ Flynn
​ Dokku

二、容器核心知识概述

在这里插入图片描述

Docker是基于容器技术的轻量级虚拟化,省去了Hypervisor层的开销

虚拟化技术是基于内核的Cgroup和Namespace技术

在通信上,Docker不会直接和内核交互,通过一个更底层的工具Libcontainer与内核交互

Libcontainer是真正意义上的容器引擎

1.What

Docker是Docker.Inc公司开源的一个基于LXC技术之上构建的Container容器引擎,源代码托管在GitHub上,基于Go语言并遵循Apache2.0协议开源。

Docker是通过内核虚拟化技术(namespaces及cgroups等)来提供容器的资源隔离与安全保障等。由于Docker通过操作系统层的虚拟化实现隔离,所以Docker容器在运行时,不需要类似虚拟机(VM)格外的操作系统开销,提高资源利用率

1.1 容器什么
  • 一系列隔离运行的进程,提供了一种轻量操作系统层面的虚拟化技术
  • 每个容器拥有自己的PID,User,Network栈namespace等
  • 与传统VM比具有启动快、性能损耗小、更轻量等优点

容器=cgroup+namespace+rootfs+容器引擎(用户态工具)

cgroup:资源控制

namespace:访问隔离

rootfs:文件系统隔离

容器引擎:生命周期控制

1.2 docker与kvm的区别

docker

在这里插入图片描述

kvm

在这里插入图片描述

  • 形象理解
    物理机–豪宅
    虚拟机–公寓楼
    容器–胶囊小旅馆
  • 技术角度
    服务器虚拟化解决的核心问题是资源调配
    容器解决的核心问题是应用开发、测试和部署

在这里插入图片描述

Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。

1.3 docker思想

​ 集装箱
​ 标准化: ①运输方式、②存储方式、 ③API接口
​ 隔离

2.Why

容器使软件具备了超强的可移植能力

2.1 集装箱vs容器

在这里插入图片描述

2.2 容器的优势

​ 对于开发人员
​ Build Once,Run Anywhere
​ 对于运维人员
​ Configure Once,Run Anything

docker启动快速属于秒级别。虚拟机通常需要几分钟去启动。

docker需要的资源更少,docker在操作系统级别进行虚拟化,docker容器和内核交互,几乎没有性能损耗,性能优于通过Hypervisor与内层的虚拟化。

docker更轻量,docker的架构可以共用一个内核与共享应用程序库,所占内存极小。同样的硬件环境,Docker运行的镜像数远多于虚拟机数量,对系统的利用率非常高。

与虚拟机相比,docker隔离性更弱,docker属于进程之间的隔离,虚拟机可实现系统级别隔离。

3.How

3.1 docker架构

在这里插入图片描述

​ docker采用c/s架构,客户端向服务器发送请求,服务器负责构建、运行和分发镜像。客户端和服务器可以运行在同一个Host上,客户端也可以通过socket或RESTAPI与远程服务器通信

Docker Client

Docker Client,也称为Docker 客户端。它其实就是Docker提供命令行界面(CLI)工具,是许多Docker用户与Docker进行交互的主要方式。客户端可以构建,运行和停止应用程序,还可以远程与Docker_Host进行交互。最常用的Docker客户端就是docker命令,我们可以通过docker命令很方便地在host上构建和运行docker容器。

Docker daemon

Docker daemon是服务器组件,以Linux后台服务的方式运行,是docker最核心的后台进程,我们也把它称为守护进程。它负责响应来自Docker Client的请求,然后将这些请求翻译成系统调用完成容器管理操作。该进程会在后台启动一个API Server,负责接收有Docker Client发送来的请求,接收到的请求通过Docker daemon内部的一个路由分发调度,由具体的函数来执行请求。

将其划分为

Docker Server Engine Job

在这里插入图片描述

Docker Daemon可以认为是通过Docker Server模块接受了Docker Client的请求,并在Engine中处理请求,然后根据请求类型,创建出指定的Job并运行。Docker Daemon运行在Docker host上,负责创建,运行,监控容器,构建,存储镜像。

在这里插入图片描述

3.2 核心组件

​ Docker客户端
​ Docker服务端
​ 镜像(Image)

Docker镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序,库,资源,配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷,环境变量,用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

​ 容器(Container)

和镜像一样,一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

容器=镜像+读写层。

​ 仓库(Regeistry)

在这里插入图片描述

4.docker快速入门

4.1 安装

​ 推荐使用centos7或者ubuntu debian较新版本
​ centos7使用官方yum仓库安装

[root@localhost ~]#yum remove docker docker-common docker-selinux docker-engine
[root@localhost ~]#yum install -y yum-utils device-mapper-persistent-data lvm2
[root@localhost ~]#wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
[root@localhost ~]#sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
[root@localhost ~]#yum makecache fast
[root@localhost ~]#yum install docker-ce -y
[root@localhost ~]#systemctl  start docker

配置

[root@localhost ~]# tee /etc/docker/daemon.json <<-'EOF'
> {
>  "registry-mirrors": ["https://c3dw7mfv.mirror.aliyuncs.com"]
> }
> EOF

这个去阿里云弄一个,注册一个账号就有自己的镜像加速了。。。(但是还是慢啊,建议梯子)
在这里插入图片描述

配置

修改系统配置文件/etc/sysconfig/docker
添加镜像仓库--registry-mirror=http://f2d6cb40.m.daocloud.io
OPTIONS=' --selinux-enabled --log-driver=journald --registry-mirror=http://f2d6cb40.m.daocloud.io'
重启docker服务
service docker restart
4.2 镜像操作

搜索镜像

docker search

获取镜像

docker pull

导出镜像

docker save -o centos.tar centos

导入镜像

docker load --input centos.tar
docker load < centos.tar

查看镜像

[root@localhost ~]# docker images

查看

在这里插入图片描述

删除镜像

docker rmi 镜像ID

时间同步

在这里插入图片描述
其实没啥用,建议修改配置文件,具体上网找找吧。

4.3 容器操作

创建容器
docker run 【option】 镜像名称 执行命令
例:

[root@localhost ~]# docker run centos /bin/echo "hello world"

查看docker运行的进程docker ps -a

在这里插入图片描述

[root@localhost ~]# docker run --name CON_NAME -t -i IMAGE /bin/bash

-t 打开终端
-i 打开标准输入 交互
例:

[root@localhost ~]# docker run -t -i --name mydocker centos /bin/bash

在这里插入图片描述

crtl+P+Q退出

容器运行完后自动删除

[root@localhost ~]# docker run --rm centos /bin/echo "hello world"

运行容器
docker start 容器名称
例:

[root@localhost ~]# docker start mydocker

进入容器
方法一:通过docker attach 容器名(exit容器退出)

在这里插入图片描述

方法二:通过nsenter(推荐,exit容器不会关闭)

[root@localhost ~]# yum install util-linux
[root@localhost ~]# docker inspect -f "{{ .State.Pid }}" mydocker

获取容器的pid

在这里插入图片描述

格式:nsenter -t PID -m -u -i -p -n

[root@localhost ~]# nsenter -t 13014 -m -u -i -p -n

测试

在这里插入图片描述

方法三:在容器中执行其他命令(推荐)
docker exec 容器名称 命令
例:

[root@localhost ~]# docker exec mydocker uname -r  

测试

在这里插入图片描述

进入容器脚本

例:

[root@localhost ~]# docker exec -ti mydocker /bin/bash

测试

在这里插入图片描述

删除容器
docker rm 容器名
docker -f rm 容器名

在这里插入图片描述

4.4 常用命令

在这里插入图片描述

三、Docker镜像管理

1.base镜像

2.第一个Dockerfile

Dockerfile是自动构建docker镜像的配置文件,用户可以使用Dockerfile快速创建自定义的镜像。Dockerfile中命令非常类似于linux下的shell命令。

拉取一个hello-world

在这里插入图片描述
可以看到hello-world镜像非常小1.84kb
运行

在这里插入图片描述

​ FROM ubuntu
RUN apt-get update && apt-get install vim -y

3.镜像分层结构

​ docker history IMAGE

在这里插入图片描述

4.镜像缓存特性

FROM debian
RUN apt-get update && apt-get install vim -y
COPY testfile /

在这里插入图片描述

5.Docker镜像构建

在这里插入图片描述

5.1 手动构建
[root@docker tmp]# docker commit -m "nginx centos" 6c8abeadc503 hehe/nginx:v1
sha256:83dc27549aabafe109840640ead12f8471e072379e97dad7518596b91e674b02

6c8abeadc503为容器ID

5.2 Dockerfile

步骤1:创建dockerfile工作目录

[root@localhost ~]# mkdir -p /opt/dockerfile/nginx

步骤2:在目录中创建Dockerfile文件

[root@localhost ~]# cd /opt/dockerfile/nginx
[root@localhost nginx]# vim Dockerfile

步骤3:编辑Dockerfile文件

#This is a docker file for nginxv2

#Base Image 
FROM centos   

#Maintainer
MAINTAINER kuangfengisme 2609405258@qq.com

#Commands
#RUN rpm -ivh https://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
RUN yum install -y nginx
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
ADD index.html /usr/share/nginx/html
EXPOSE 80
CMD nginx

将/usr/share/nginx/html/index.html文件复制到当前目录下

from指定基础镜像
run运行的命令
add添加文件到指定目录
expose暴露端口
cmd 容器启动时运行的命令
workdir 设置工作目录相当于cd
volume 设置数据卷,挂载主机目录
Dockerfile参考官方文档
https://docs.docker.com/engine/reference/builder/#run

步骤4:构建docker镜像

[root@localhost nginx]# docker build -t haha/nginx:v3 .

注意最后的参数为Dockerfile文件所在的路径

测试结果

在这里插入图片描述

查看

在这里插入图片描述

步骤5:基于构建的镜像运行容器

[root@docker ~]# docker run -P -d --name mynginxv3 haha/nginx:v3

查看

在这里插入图片描述

5.3 问题

在这里插入图片描述

添加文件:添加到容器层

读取文件:容器层如没有则docker自上往下依次在各个镜像层中查找文件,一旦找到,就读取文件内容

修改文件:自上往下先找到文件

删除文件:自上往下先找到文件,容器层记录文件被删除的操作

6.Dockerfile常用指令

FROM
指定base镜像(父镜像)

MAINTAINER
设置镜像的作者,可以是任意字符串
COPY
将文件从build context复制到镜像
COPY支持两种形式: COPY src dest与COPY [ “src”,“dst”]
ADD
与COPY类似,不同的是ADD会解压归档文件(gz,tgz,xz,tar等)
ENV
设置环境变量,可以被后面的指令使用
例:ENV VERSION 1.3 RUN apt-get install -y vim=$VERSION
EXPOSE
指定容器中的进程会监听某个端口Docker可以将该端口暴露出来,提供后续-P随机映射
VOLUME
将文件或目录声明为volume
WORKDIR
后面指定的工作目录
RUN
在容器中运行的命令
CMD
容器启动时运行的命令
Dockerfile可以有多个CMD指令,但只有最后一个生效,CMD可以被docker run后面的参数替换
ENTRYPOINT
设置容器启动时运行的命令

命令格式SHELL&EXEC
SHELL
FROM ubuntu
RUN touch /tmp/test
CMD echo "hello world"
ENV name HEHE 
ENTRYPOINT echo "hello $name"

EXEC
FROM ubuntu
RUN ["touch","/tmp/test"]
CMD ["/bin/echo","hello world"]
ENV name HEHE 
ENTRYPOINT ["echo","hello $name"]

7.分发镜像

7.1 镜像命名

repository:tag
如没有指定tag,使用默认latest

注意:当没有指定标签时,Docker会用latest作为默认值,但除此之外,它不具备任何特殊含义。很多仓库会把它作为最新稳定版镜像的别名,但这只是一种惯例,并非规定。你仍需要执行docker pull命令来获取最新版。
当执行docker run或docker pull时,如果指定镜像名称不带标签,那么Docker会使用带latest标签的镜像,若不存在则报错。

标签名称规则:

  • 必须由大小写字母、数字、以及.和-符号组成。
  • 长度必须为1~128个字符
  • 第一个字符不能是.或-符号
7.2 tag版本实战

在这里插入图片描述

命令:
docker tag myimage-v1.9.1 myimage:1
docker tag myimage-v1.9.1 myimage:1.9
docker tag myimage-v1.9.1 myimage:1.9.1
docker tag myimage-v1.9.1 myimage:latest

# myimage:1 始终指向 1 这个分支中最新的镜像。
# myimage:1.9 始终指向 1.9.x 中最新的镜像。
# myimage:latest 始终指向所有版本中最新的镜像。
# 如果想使用特定版本,可以选择 myimage:1.9.1、myimage:1.9.2 或 myimage:2.0.0。


在这里插入图片描述

命令:
docker tag myimage-v1.9.2 myimage:1
docker tag myimage-v1.9.2 myimage:1.9
docker tag myimage-v1.9.2 myimage:1.9.2
docker tag myimage-v1.9.2 myimage:latest

在这里插入图片描述

命令:

docker tag myimage-v2.0.0 myimage:2
docker tag myimage-v2.0.0 myimage:2.0
docker tag myimage-v2.0.0 myimage:2.0.0
docker tag myimage-v2.0.0 myimage:latest

8.Registry

创建

{
  "registry-mirrors": ["https://c3dw7mfv.mirror.aliyuncs.com"]
}
8.1 公共Registry

去官网注册一个账号

docker hub登录

docker login -u USERNAME

在这里插入图片描述

登录

在这里插入图片描述
也可以用docker login 登录,只是比较麻烦,要输入的东西好多。。。

修改镜像repository

docker tag ubuntu:v1 hello/ubuntu:v1

例子

[root@localhost ~]# docker tag centos haha/centos:v1
[root@localhost ~]# docker images

在这里插入图片描述

上传到docker hub

docker  push hehe/ubuntu:v1

访问docker hub测试

在这里插入图片描述
很好,上传不上去,,,,,,

8.2 本地Registry

启动registry容器

docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:2

修改tag与registry匹配

docker tag hehe/ubuntu:v1 127.0.0.1:5000/hehe/ubuntu:v1
repository完整格式:【registry-host】:【port】/username/xxx:tag

上传镜像到本地registry

docker push 127.0.0.1:5000/hehe/ubuntu:v1

在其他主机上下载本地registry镜像

docker pull 127.0.0.1:5000/hehe/ubuntu:v1

四、Docker容器管理

本地容器/var/lib/docker/containers/

1.创建容器

  • docker run 【option】 镜像名称 执行命令

例:

docker run centos /bin/echo "hello world"

查看docker运行的进程docker ps -a

  • docker run --name CON_NAME -t -i IMAGE /bin/bash
    -t 打开终端
    -i 打开标准输入

例:

docker run -t -i --name mydocker centos /bin/bash
  • 容器运行完后自动删除
docker run --rm centos /bin/echo "hello world"

2.运行容器

docker start 容器名称
例:

docker start mydocker

3.停止容器

  • docker stop
    SIGTERM
  • docker kill
    SIGKILL

4.暂停容器

​ docker pause
​ docker unpause

5.进入容器

5.1 方法一:

通过docker attach 容器名(exit容器退出)

5.2 方法二:

通过nsenter(推荐,exit容器不会关闭)

yum install util-linux
docker inspect -f "{{ .State.Pid }}" mydocker

获取容器的pid

nsenter -t PID -m -u -i -p -n

进入容器脚本

#!/bin/bash
CID=$1
CPID=`docker inspect -f "{{ .State.Pid }}" $CID`
nsenter -t $CPID -m -u -i -p -n

5.3 方法三:

通过docker exec(推荐)
docker exec 容器名称 命令
例:

docker exec mydocker uname -r  

例:

docker exec -ti mydocker /bin/bash

6.删除容器

删除容器

docker rm 容器名/ID

强制删除

docker -f rm 容器名/ID

显示多个exited容器

docker rm -v `docker ps -aq -f status=exited`

7.容器状态机

在这里插入图片描述

8.容器资源限制

8.1 内存限额

-m
内存限额

docker run -m 200M --memory-swap=300M ubuntu

—memory-sawp
内存+swap限额,默认为2倍-m大小

docker run -it  -m 200M --memory-swap=300M progrium/stress --vm 1  --vm-bytes 280M
docker run -it  -m 200M --memory-swap=300M progrium/stress --vm 1  --vm-bytes 310M
8.2 cpu限额

-c | --cpu-share
cpu资源的权重,默认为1024
–cpu
设置工作线程的数量

docker run -it --name cputestA -c 1024 progrium/stress --cpu 1
docker run -it --name cputestB -c 512 progrium/stress --cpu 1

top查看cpu使用

8.3 block IO限额

–blkio-weight
io权重,默认500

bps 每秒读写的数据量

—device-read-bps
–device-write-bps

每秒IO的次数

—device-read-iops
–device-write-iops

1

docker run -it --device-write-bps /dev/sda:30MB ubuntu
time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct

2

docker run -it ubuntu 
time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct

关于DirectIO参考资料
https://www.ibm.com/developerworks/cn/linux/l-cn-directio/#major1
https://book.douban.com/subject/1896753/

9.容器底层技术分析

9.1 cgroup

控制组,主要是做资源控制,其原理是将一组进程放在一个控制组里,通过给这个控制组分配指定的可用资源,达到控制这一组进程可用资源目的

Control Group,用于控制cpu,内存和IO资源的限额

限制进程组能够访问的资源上限

实例

docker run -it --name cputestA -c 1024 progrium/stress --cpu 1
cat /sys/fs/cgroup/cpu/docker/52fccca17a676b4a804fcd92af831bb3f900e20207df47c8f6e2228584e4055e/cpu.shares  # 替换容器ID
cat /sys/fs/cgroup/memory/docker
cat /sys/fs/cgroup/blkio/docker

资源控制

在这里插入图片描述

1.cpuset子系统

2.cpu子系统

3.cpuacct子系统

4.blkio子系统

5.devices子系统

9.2 namespace

又称命名空间名主要做访问隔离,原理是针对一类资源进行抽象,并将其封装在一起提供给一个容器使用。

实现容器间资源隔离(文件系统、网络等)
6种namespace
1.Mount
让容器看上去拥有整个文件文件系统
2.UTS
让容器拥有自己的hostname

​ (因为主机名可以用代替IP地址)

​ 可以通过docker run -h 指定

3.IPC
​ 让容器拥有自己的共享内存和信号量来实现进程间通信,与其他容器IPC隔离
4.PID
​ ps axf

在这里插入图片描述

5.Network
​ 让容器拥有自己独立的网卡、IP、路由等资源
6.User
​ 让容器能够管理自己的用户,host不能看到容器中创建的用户

在这里插入图片描述

五、Docker网络访问

在这里插入图片描述

1.单host网络

docker netowork list

1.1 none网络

只包含环回口的容器,用于封闭场景
例子

[root@localhost ~]# docker run -it --network=none busybox

查看

在这里插入图片描述

1.2 host网络

连接到host网络的容器共享host的网络栈,容器的配置与host完全一样

容器有完整的权限可以操纵主机的协议栈、路由表和防火墙,所以不安全

例子

[root@localhost ~]# docker run -it --network=host busybox

查看

在这里插入图片描述

1.3 bridge网络

在这里插入图片描述

docker安装时会创建docker0的桥接网卡,默认容器会挂到docker0上

查看容器bridge网络配置信息

[root@localhost ~]# docker network inspect bridge

veth pair
参考链接:https://www.fir3net.com/Networking/Terms-and-Concepts/virtual-networking-devices-tun-tap-and-veth-pairs-explained.htmlexplained.html

创建容器

[root@localhost ~]# docker run -it busybox

查看

在这里插入图片描述

再开一个终端去查看

在这里插入图片描述

测试两台

两台

第一台终端

在这里插入图片描述

第二台终端

在这里插入图片描述

第三台终端

在这里插入图片描述

1.4 user-defined网络

bridge

创建

[root@localhost ~]# docker network create --driver bridge my_brnet

查看

在这里插入图片描述

创建虚拟网桥

–subnet 172.16.10.0/24
–gateway 172.16.10.1

查看

[root@localhost ~]# docker network inspect my_brnet 

查看网桥

在这里插入图片描述

将容器加入到创建的网络

[root@localhost ~]# docker run --network=my_brnet -it busybox 

查看

在这里插入图片描述

去另一台终端查看

在这里插入图片描述

将指定容器加入到网络

[root@localhost ~]# docker  network connect my_brnet mydocker

已经运行了的容器

查看

在这里插入图片描述

跨主机通信
overlay
macvlan

1.5 容器间通信
  • IP通信

    如上所述

  • Docker DNS Server

在创建容器时指定–name,并加入到自定义网络中才能使用内嵌的dns服务

[root@localhost ~]# docker run -it --network=my_brnet --name=bbox1 busybox
[root@localhost ~]# docker run -it --network=my_brnet --name=bbox2 busybox

测试: 在bbox2中ping bbox1

一台

在这里插入图片描述

(好像要先升级内核才行)
这里我就直接在/etc/hosts文件里写,

在这里插入图片描述

这下就可以直接ping通了,就不试了。

二台

在这里插入图片描述

  • joined容器

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

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

查看

在这里插入图片描述

进去busybox容器中查看网络信息

ifconfig #网卡信息是否一致

在这里插入图片描述

查看web1网络状况

[root@docker ~]# docker inspect network web1


在这里插入图片描述

1.6 外部访问容器
  • 随机映射

docker -P
例:

[root@localhost ~]# docker run -P -d --name nginx nginx
docker logs 6c8abeadc503 #查看容器日志

查看

在这里插入图片描述

去网页访问

在这里插入图片描述

  • 指定映射

docker -p
ip:hostPort:containerPort
例:

[root@localhost ~]# docker run -d -p 192.168.217.141:8000:80 --name nginxkf nginx

hostPort:containerPort
ip::containerPort
containerPort

在这里插入图片描述

  • 查看映射
[root@localhost ~]# netstat -tulnp
[root@localhost ~]# iptables -t nat -vnL
[root@localhost ~]# port nginx

查看

在这里插入图片描述

2.多host网络

libnetwork是容器网络库,其核心内容是其定义的Container Network Model,这个模型对容器网络进行了抽象,由三个组件组成

在这里插入图片描述

2.1 Sandbox

容器的网络栈,包含容器的interfaces、路由表和DNS设置,Network Namespace是Sandbox的标准实现,Sandbox可以包含来自不通网络的Endpoint

linux network namespace实战

操作network namespace命令:ip netns

2.1.1 ip netns add xx

创建一个 namespace

[root@docker ~]#  ip netns add net1
[root@docker ~]#  ip netns ls
net1
[root@docker ~]# ip netns add net0
[root@docker ~]# ip netns ls
net0
net1
2.2.2 ip netns exec xx yy

在新 namespace xx 中执行 yy 命令

[root@docker ~]# ip netns exec net1 ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[root@docker ~]# ip netns exec net1 bash // 在 net1 中打开一个shell终端
[root@docker ~]# ip addr // 在net1中的shell终端
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[root@docker ~]# exit // 退出net1
exit
2.2.3 network namespace 之间的通信

新创建的 namespace 默认不能和主机网络,以及其他 namespace 通信,可以使用 Linux 提供的 veth pair 来完成通信。

在这里插入图片描述

  • ip link add type veth 创建 veth pair
[root@docker ~]# ip link add type veth
[root@docker ~]# ip link
或ip link add xxx type veth peer name yyy

查看

在这里插入图片描述

  • ip link set xx netns yy 将 veth xx 加入到 namespace yy 中
[root@docker ~]# ip link set veth0 netns net0
[root@docker ~]# ip link set veth1 netns net1
[root@docker ~]# ip netns exec net0 ip addr

查看

在这里插入图片描述

  • 给 veth pair 配上 ip 地址
[root@docker ~]# ip netns exec net0 ip link set veth0 up
[root@docker ~]# ip netns exec net0 ip addr
[root@docker ~]# ip netns exec net0 ip addr add 10.1.1.1/24 dev veth0
[root@docker ~]# ip netns exec net0 ip route
[root@docker ~]# ip netns exec net1 ip link set veth1 up
[root@docker ~]# ip netns exec net1 ip addr add 10.1.1.2/24 dev veth1
[root@docker ~]# ip netns exec net1 ip route

查看

在这里插入图片描述

  • ping 测试两个 namespace 的连通性
[root@docker ~]# ip netns exec net0 ping 10.1.1.2

查看

在这里插入图片描述

2.2.4 多个不同 namespace 之间的通信

2 个 namespace 之间通信可以借助 veth pair ,多个 namespace 之间的通信则可以使用 bridge 来转接,不然每两个 namespace 都去配 veth pair 将会是一件麻烦的事。

在这里插入图片描述

  • 使用 ip link 和 brctl 创建 bridge
[root@docker ~]# ip link add br0 type bridge
[root@docker ~]# ip link set dev br0 up
[root@docker ~]# ip a

查看

在这里插入图片描述

  • 创建 veth pair

创建 3 个 veth pair

[root@docker ~]# ip link add type veth
[root@docker ~]# ip link add type veth
[root@docker ~]# ip link add type veth
  • 将 veth pair 的一头挂到 namespace 中,一头挂到 bridge 上,并设 IP 地址
// (1)配置第 1 个 net0
[root@docker ~]# ip link set dev veth1 netns net0
[root@docker ~]# ip netns exec net0 ip link set dev veth1 name eth0
[root@docker ~]# ip netns exec net0 ip addr add 10.0.1.1/24 dev eth0
[root@docker ~]# ip netns exec net0 ip link set dev eth0 up
[root@docker ~]# ip link set dev veth0 master br0
[root@docker ~]# ip link set dev veth0 up

// (2)配置第 2 个 net1
[root@docker ~]# ip link set dev veth3 netns net1
[root@docker ~]# ip netns exec net1 ip link set dev veth3 name eth0
[root@docker ~]# ip netns exec net1 ip addr add 10.0.1.2/24 dev eth0
[root@docker ~]# ip netns exec net1 ip link set dev eth0 up
[root@docker ~]# ip link set dev veth2 master br0
[root@docker ~]# ip link set dev veth2 up
[root@docker ~]# ip link set dev veth5 netns net2

// (3)配置第 3 个 net2
[root@docker ~]# ip link set dev veth5 netns net2
[root@docker ~]# ip netns exec net2 ip link set dev veth5 name eth0
[root@docker ~]# ip netns exec net2 ip addr add 10.0.1.3/24 dev eth0
[root@docker ~]# ip netns exec net2 ip link set dev eth0 up
[root@docker ~]# ip link set dev veth4 master br0
[root@docker ~]# ip link set dev veth4 up

结果

在这里插入图片描述

  • 测试,网络不通
[root@docker ~]# ip netns exec net0 ping -c 2 10.0.1.2
[root@docker ~]# ip netns exec net0 ping -c 2 10.0.1.3

测试结果

在这里插入图片描述

解决方法

[root@docker ~]# echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables
[root@docker ~]# iptables -A FORWARD -i br0 -j ACCEP1.T

1.关闭系统bridge的iptables功能,这样数据包转发就不受iptables影响了:echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables

2.为br0添加一条iptables规则,让经过br0的包能被forward:iptables -A FORWARD -i br0 -j ACCEPT

2.2 Endpoint

Endpoint的作用是将Sandbox介入Network,Endbox的典型实现是veth pair。一个Endpoint只能属于一个网络,也只能属于一个Sandbox
在这里插入图片描述

正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备,典型的例子像“两个 namespace 之间的连接”,“Bridge、OVS 之间的连接”,“Docker 容器之间的连接” 等等,以此构建出非常复杂的虚拟网络结构,比如 OpenStack Neutron。

2.3 Network

包含一组Endpoint,同一Network的Endpoint可以直接通信。Network的实现driver可以是Linux Bridge,VxLAN等。

实现driver
在这里插入图片描述

2.3.1 bridge

在这里插入图片描述

  • 两个 Network:默认网络 “bridge” 和自定义网络 “my_net2”。实现方式是 Linux Bridge:“docker0” 和 “br-5d863e9f78b6”。
  • 三个 Enpoint,由 veth pair 实现,一端(vethxxx)挂在 Linux Bridge 上,另一端(eth0)挂在容器内。
  • 三个 Sandbox,由 Network Namespace 实现,每个容器有自己的 Sanbox。

可以用路由解决两个network的通信

2.3.2 overlay

用于可以创建基于VxLAN的overlay网络。VxLAN可以将二层数据封装到UDP进行传输,相比VLAN拥有更强的扩展性和灵活性。

  • 什么是 VxLAN?

Virtual eXtensible Local Area Network

  • 优势

支持更多的二层网段vlan (由vlan id区分)

能更好地利用已有的网络路径(STP 防环)

避免物理交换机 MAC 表耗尽

  • VXLAN 封装和包格式

VXLAN 是将二层建立在三层上的网络。
通过将二层数据封装到 UDP 的方式来扩展数据中心的二层网段数量。
VXLAN 是一种在现有物理网络设施中支持大规模多租户网络环境的解决方案。
VXLAN 的传输协议是 IP + UDP

在这里插入图片描述

    • VXLAN 引入了 8-byte VXLAN header,其中 VNI 占 24-bit。
    • VXLAN 和原始的 L2 frame 被封装到 UDP 包中。
    • 24-bit 的 VNI 用于标示不同的二层网段,能够支持 16777216 个 LAN。
  • VTEP(VXLAN Tunnel Endpoint)

在这里插入图片描述

    • VXLAN 使用 VXLAN tunnel endpoint (VTEP) 设备处理 VXLAN 的封装和解封。
    • 每个 VTEP 有一个 IP interface,配置了一个 IP 地址。VTEP 使用该 IP 封装 Layer 2 frame,
    • 并通过该 IP interface 传输和接收封装后的 VXLAN 数据包。
  • key-value 数据库

Docerk overlay 网络需要一个 key-value 数据库用于保存网络状态信息,包括 Network、Endpoint、IP 等。Consul、Etcd 和 ZooKeeper 都是 Docker 支持的 key-vlaue 软件,我们这里使用 Consul。

  • overlay环境准备

1.部署consul组件

[root@docker ~]# docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap

通过http://IP:8500 访问consul

192.168.217.141:8500

在这里插入图片描述

2.修改 host1 和 host2 的 docker daemon配置

host1

在/lib/systemd/system/docker.service

ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock --cluster-store consul://192.168.217.141:8500 --cluster-advertise 192.168.217.142:2376

–cluster-store 指定 consul 的地址。

–cluster-advertise 告知 consul 自己的连接地址。

在这里插入图片描述

3.重启docker

# 加载新service配置文件
[root@host1 ~]# systemctl daemon-reload
# 重启docker服务
[root@host1 ~]# systemctl restart docker

host2主机和host1同理

4.查看consule的key/value信息

在这里插入图片描述

  • 在overlay中运行容器

1.在host1上创建overlay网络

创建

[root@host1 ~]# docker network create -d overlay ov_net1 

在host1和host2上都能看到

host1

在这里插入图片描述

host2

在这里插入图片描述

查看详细信息

[root@host1 ~]# docker network inspect ov_net1 

host1

在这里插入图片描述

2.创建容器运行加入overlay网络

在host1上创建bbox1容器并指定ov_net1网络

[root@host1 ~]# docker run -itd --name bbox1 --net ov_net1 busybox

在host2上创建bbox2容器并指定ov_net1网络

[root@host2 ~]# docker run -itd --name bbox2 --net ov_net1 busybox

3.测试联通性

在host1上

[root@host1 ~]# docker exec -it bbox3 sh
/ # ping bbox4
ping: bad address 'bbox4'
/ # ping 10.0.0.5

结果

在这里插入图片描述

在host2上

[root@host2 ~]# docker exec -it bbox4 sh
/ # ping bbox3
ping: bad address 'bbox3'
/ # ping 10.0.0.4

结果

在这里插入图片描述

2.3.3 macvlan
2.3.4 flannel
2.2.5 weave

3.问题

3.1 不同网络的容器如何通信?

提示:路由,ip_forward,iptables

3.1.1 准备

自定义两个网络network1 (172.19.1.0/24)和network2(172.19.2.0/24)

[root@docker ~]# docker network create network1 --subnet   172.19.1.0/24
fb9b9d3ba518d7bb24fb33156a87fa7e883172f05d56af68560c079da9605d8a
[root@docker ~]# docker network create network2 --subnet   172.19.2.0/24
174272b971d2e8fe52310a5f9ba4e5049fff85cca0e4b4f8974945ec53514671

在这里插入图片描述

在两个网络中,分别生成两个容器

[root@docker ~]# docker run -itd --network network1 --name box1-1 busybox
0a3613a053d30485f9ca5c92671369fd3a27a803418a61d6184c5fd3500c1181
[root@docker ~]# docker run -itd --network network1 --name box1-2 busybox
f540748db7e970eb47d279e0b4c3d0061794a1c009d4f73a01607c0f844a9f29
[root@docker ~]# docker run -itd --network network2 --name box2-1 busybox
6efbb68475ac8ee1979b600e5be97272cd15dfe70fb8fe11a95df61e80bb33b0
[root@docker ~]# docker run -itd --network network2 --name box2-2 busybox
e7631cb49361e144856deba586b68e83d448deab4c4586788bbf4c972079d72c

在这里插入图片描述

查看

默认是bridge模式

在这里插入图片描述

3.1.2 原因

在同一个网络的容器是可以正常通信的

在这里插入图片描述

而不同网络时通信不了的。

在这里插入图片描述

3.1.3 解决办法

方法一:把容器加入另一个网络中

1.把box1-1加入到network2中

2.验证

[root@docker ~]# docker network connect  network2 box1-1
[root@docker ~]# docker exec -it box1-1 ip a
[root@docker ~]# docker exec -it box1-1 ping 172.19.2.2
[root@docker ~]# docker exec -it box1-1 ping 172.19.1.3

在这里插入图片描述

3.把box1-2添加到network2中

# 创建/var/run/netns
[root@docker ~]# mkdir -p /var/run/netns
# 获取容器box1-2的进程号
[root@docker ~]# docker inspect box1-2 | grep Pid
            "Pid": 4106,
            "PidMode": "",
            "PidsLimit": null,
[root@docker ~]# ln -s /proc/4106/ns/net /var/run/netns/box1-2
#查看恢复的netns
[root@docker ~]# ip netns list
box1-2 (id: 3)

4.增加veth-pair并配置网络

#增加veth-pari对设备
[root@docker ~]# ip link add veth_b_1_2 type veth peer name veth_b_1_2_peer
#把一端放入box1-2的netns中
[root@docker ~]# ip link set veth_b_1_2 netns box1-2
#配置IP地址
[root@docker ~]# ip netns exec box1-2 ip addr add 172.17.2.5/24 dev veth_b_1_2
[root@docker ~]# ip netns exec box1-2 ip link set veth_b_1_2  up
[root@docker ~]# docker exec -it box1-2 ip a

查看配置

在这里插入图片描述

找到刚才创建的veth的编号

在这里插入图片描述
再设为172.19.2.1/24master

[root@docker ~]# ip link set dev veth_b_1_2_peer master br-174272b971d2
[root@docker ~]# ip link set veth_b_1_2_peer  up

方法二:把需要通信的容器加入到第三方网络中

如果两个容器想要通信,就把两个容器加入第三方网络中,这样两个容器就能通信了,具体思路就是创建第三网络,使用docker connect 命令把两个需要通信的容器加入到这个网络中,实现通信,如果不想让两个容器通信了,就通过docker disconnect删除。

方法三:修改底层的iptables规则实现两个网络通信

正常情况下,创建好net’ns配置好网络以及路由,同一个宿主机中的不同的bridge之间是可以通信的。iptables规则给阻拦了两个网络的通信。

找到两个网络

在这里插入图片描述

[root@localhost ~]# iptables -I DOCKER-USER -i br-fb9b9d3ba518 -o br-174272b971d2 -j ACCEPT
[root@localhost ~]# iptables -I DOCKER-USER -i br-174272b971d2 -o br-fb9b9d3ba518 -j ACCEPT

六、Docker数据存储

1.两类存储数据的机制

1.1 Storage Driver

在这里插入图片描述

docker info查看

在这里插入图片描述

目前支持的storage driver有aufs、OverlayFS和Brtfs等

aufs

overlay2

应用场景
用于无状态的应用
ping 114.1.1.1

1.2 Data Volume

数据卷本质是host上的文件系统中的目录或文件,能够直接被mount到容器中。

1.2.1 特点

是目录或文件,而非块设备

容器可读写volume中数据

数据可以被永久保存,即使容器销毁

1.2.2 应用场景

database软件 vs database数据

web应用 vs web应用生产的日志

apache vs 静态html文件

无状态vs永久

ps:由于volume可以保存应用的数据在host文件系统中,主要用于有状态的应用。

2.data volume数据卷

host与容器间数据共享

2.1 两种类型
2.1.1 bind mount

bind mount是将host上的已存在的目录或文件mount到容器

  • 语法
docker run -v <host path>:<container path> ID
docker run -v <host path>:<container path>:ro ID # 只读模式
  • 缺点

指定了host文件系统特定路径,容器可移植性差

  • 实例

没有/data/nginx/html目录就先创建mkdir -p /data/nginx/html

[root@docker ~]# docker run -d -p 80:80 -v /data/nginx/html:/usr/share/nginx/html nginx
c5258f6919780d339b2afdebec72bd7e5cbdc217b3b14ed1df25d2990f2f9dd1

查看

原本/data/nginx/html目录下是没有文件的

在这里插入图片描述
再在/data/nginx/html下创建文件indexhtml

在这里插入图片描述

结论:在本地主机操作,容器也同步变化

2.1.2 docker managed volume

不需要指定mount源,指名mount point即可,会自动在/var/lib/docker/volume创建目录存放容器内文件

  • 实例
docker run -d -p 80:80 -v /usr/share/nginx/html nginx

查看变化

在这里插入图片描述

进入容器查看

[root@docker ~]# ls /var/lib/docker/volumes/ab482dba2b60e7b7208ff52f1481af6cb5da0ea1fd48cf7c8e3c6ba6b9c49e4d/_data/
50x.html  index.html
[root@docker ~]# ls /usr/share/nginx/html/
404.html  en-US  img         nginx-logo.png
50x.html  icons  index.html  poweredby.png
[root@docker ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
9c4694bc971e        nginx               "nginx -g 'daemon of…"   6 minutes ago       Up 6 minutes        0.0.0.0:80->80/tcp   agitated_wing
[root@docker ~]# docker exec -it 9c4 bash
root@9c4694bc971e:/# ls /usr/share/nginx/html/
50x.html  index.html
2.1.3 查看volume信息
  • mount
  • docker inspect -f “{{ .Mounts }}” nginx-volume1 # 查看挂载的目录在物理机中的位置
  • docker volume ls/inspect
2.2 两种例子
2.2.1 docker managed volume

搞了很久才明白,原来是在容器里自动创建一个/data/docker目录,这样本地就会有一个存放容器文件的目录/var/lib/docker/volume/xxxxxxxx/_data/

那接下来我操作一下

[root@docker ~]# docker run -d --name nginx-volume1 -v /data/docker nginx
[root@docker ~]# docker exec -it 11c7e2 bash # 进入容器
root@11c7e2c8bbbf:/# ls
root@11c7e2c8bbbf:/# echo "<h>hello host<\h>" > /data/docker/test1.html
root@11c7e2c8bbbf:/# exit # 退出容器
[root@docker ~]# cat /var/lib/docker/volumes/2601d6b99b20f045256f48b34445605e8759d05cd9c071a38b18a2f855385002/_data/test1.html 

在这里插入图片描述

那在主机上操作,容器会不会变

操作起来

[root@docker ~]# echo "<h>hello container</h>" > /var/lib/docker/volumes/2601d6b99b20f045256f48b34445605e8759d05cd9c071a38b18a2f855385002/_data/test2.html
[root@docker ~]# docker ps
[root@docker ~]# docker exec -it 11c7e bash
root@11c7e2c8bbbf:/# cat /data/docker/test2.html 

结果是会变的,有没有大胆的想法。。。。哈哈哈哈;‘’

在这里插入图片描述

2.2.2 bind mount
[root@docker ~]# docker run -d --name nginx-volume2 -v /data/docker:/data nginx
[root@docker ~]# docker exec -it 692d bash
root@692d8f2c86e6:/# ls /data/
root@692d8f2c86e6:/# exit
[root@docker ~]# ls /data/docker
[root@docker ~]# echo "<h>hello ddddd</h>" > /data/docker/33.html
[root@docker ~]# cat /data/docker/22.html 
[root@docker ~]# docker exec -it 692d bash
root@692d8f2c86e6:/# cat /data/33.html
root@692d8f2c86e6:/# exit

结果

在这里插入图片描述

3.data volume container数据卷容器

容器与容器间数据共享

不同容器之间能够互相共享数据,可以基于bind mount或者docker managed volume

  • 实例
3.1 先创建一个专门存放数据容器
[root@docker ~]# docker create --name vc_data -v /data/nginx/html:/usr/share/nginx/html -v /etc/nginx nginx

查看容器

在这里插入图片描述

详细挂载信息

在这里插入图片描述

3.2 创建三个容器卷属vc_data
[root@docker ~]# docker run --name web11 -d -p 80 --volumes-from vc_data nginx
[root@docker ~]# docker run --name web22 -d -p 80 --volumes-from vc_data nginx
[root@docker ~]# docker run --name web33 -d -p 80 --volumes-from vc_data nginx
3.3 /data/nginx/html/index.html
[root@docker ~]# echo "<h>hello docker </h>" >> /data/nginx/html/index.html
3.4 进入web11容器

在这里插入图片描述

结论:就算容器/usr/share/nginx/html目录里有其他文件也会被覆盖掉

3.5 进入web22容器
[root@docker ~]# docker ps
# 进入web22容器
[root@docker ~]# docker exec -it 56e bash
root@56e62c3bf035:/# echo "<h>hello docker web22</h>" >> /usr/share/nginx/html/web22.html 
root@56e62c3bf035:/# exit
# 查看主机
[root@docker ~]# ls /data/nginx/html/
[root@docker ~]# cat /data/nginx/html/web22.html 
# 进入web11容器
[root@docker ~]# docker exec -it f8dc bash
root@f8dcfb98b406:/# cat /usr/share/nginx/html/web22.html

在这里插入图片描述

当然主存放的vc_data容器也变了。。。。。。

3.6 curl
[root@docker ~]# curl 127.0.0.1:32768
<h>hello docker </h>
[root@docker ~]# curl 127.0.0.1:32769
<h>hello docker </h>
[root@docker ~]# curl 127.0.0.1:32770
<h>hello docker </h>

4.data-packed volume container

通过将数据打包到镜像中,然后通过docker managed volume共享给其他容器

5.data volume生命周期管理

5.1 备份
docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:2
5.2 恢复

使用之前备份的数据

5.3 迁移

docker stop

docker run新版本挂载原有volume

5.4 销毁

docker rm -v

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值