1 docker 基本命令

1
2
3
4
5
6
7
8
9
docker run -it -d -p -e -v --network container_name
docker ps -a
docker rm container_name
docker rmi image_name
docker inpect container_name
docker log container_name
docker pull <image_name>
docker images # 展示所有镜像
docker stop container_name
  • 关于docker run 命令
    • 应当把run命令当做运行一个任务或者进程,完成了一个任务就会自动结束(保留下来算是任务执行过程的痕迹)
    • 直接执行的时候,docker 运行的容器其实没有attach 到当前的命令行窗口中,无法读取 input 并且利用 Terminal 输出 需要加入 it 选项进行交互(否则只会输出一个最终结果?)
    • detach 完全进入后台运行
    • 我希望将docker host 的一个端口映射给容器的某个端口,完成网络访问,可以使用 p 选项, 一定是外 对 内(内就是 container)
    • 有的时候,不想总是改容器镜像中的脚本(其实是拷贝出来一份)所以把容易变化的当做环境变量,在脚本里面读取,在运行的时候设置,使用 -e
    • 不希望容器内的数据随着容器的销毁而消失,所以会想要把数据卷挂载到容器某个路径下,这样容器写这个路径,就相当于向着外部数据卷进行写入,使用 -v volume(不过这是老式的写法)
    • 新版的挂载数据卷的方式:docker run –mount type=bind,source=/data/mysql,target=/var/ilb/mysql container_name
    • 指定所在的网络就用 –network 具体在网络部分展开
  • 想要查看所有正在运行或者停止运行的所有容器:使用 -a 选项 ,docker ps
  • 删除容器用 rm 表示remove, 删除镜像使用 rmi 表示 remove image
  • 已经停止运行的容器可以 探测其中的配置和相关改动,用 inspect ?
  • 正在运行的容器使用 log 探查日志输出
  • 想要拉取镜像?使用 pull 就好(当然像私有库推送镜像使用 push)但是记者这个每次只能写入一个镜像名,否则会报错
  • 想要停止容器运行就使用 stop 吧

2 docker 制作镜像

Dockerfile 基本命令
1
2
3
4
5
6
RUN
CMD
ENTRYPOINT
COPY
WORKDIR
FROM
  • ENTRYPOINT 和 CMD 是配合使用的
    • 如果 没有 ENTRYPOINT 并且没有命令行指定命令,那么默认CMD是启动时要执行的命令
      • 此时可采用JSON 格式或者直接写空格分隔的命令两种形式
    • 如果命令行里有指定命令,那么使用命令行中的命令
    • 如果ENTRYPOINT 有指定(就是确定了要执行哪个程序)
      • CMD只能使用 JSON 格式,表示默认的这个程序执行时的参数
      • 命令行可以覆盖CMD中的默认参数
      • 如果命令行参数不够,默认会使用 JSON 格式指明的 CMD 中的参数append ?
  • FROM 基础镜像
  • RUN 执行一系列命令来构成镜像新的一层
  • COPY 拷贝外部文件到镜像的一层内
  • WORKDIR 指定容器运行的工作目录 ?
构建镜像
1
docker build Dockerfile -t image_name 

3 docker-compose 使用

  • 把需要成组运行的服务写到一个yaml 文件。
  • 直接使用 docker-compose up 运行
  • 文件结构
1
2
3
4
5
6
7
8
version: 3
services:
web:
image:
port:
database:
image:
port:
  • 分了不同的版本,目前最新版本是版本3
  • 可以指定网络,直接用服务名可以解析出 IP 地址(默认是绑定到网络 docker0)
  • 可以指定数据卷、端口等

4 docker 底层原理

  • 使用分层文件系统 路径在 /var/lib/docker
    • aufs(表示的是这个文件系, 常见系统还有 ZFS, BTRFS等)
    • container
    • image
    • volumes 默认的数据卷都在这个路径下
    • 相关的文件都存储在对应的文件夹下面
  • 镜像
    • 都是分层的文件,利用Dockerfile 文件各个命令作为一层进行制作
    • 制作完成之后内容只读
  • 容器
    • 在镜像的基础上,加上一层可读可写层,如果要修改镜像中的内容,会拷贝一份进行修改 (由分层文件系统完成)
    • 但是这一层只在容器存在的时候存在
  • docker 运行结构
    • 分为三层
      • Docker CLI 与用户命令交互的命令行终端
      • REST API Server 程序与守护进程交互的一系列接口
      • Docker Daemon 后台守护者进程,管理所有镜像、容器等对象
    • 在各个部分区分了命令空间,使得各个容器运行互相不干扰
      • 进程ID
      • Network
      • InterProcess communication
      • Mount
      • Unix Time Sharing
  • 使用 cgroups 可以进行资源控制 【control groups】

5 docker 网络

补充知识:
私有 IP 如: 192.168.x.x、 10.x.x.x、 172.16.x.x ~ 172.31.x.x 不可被互联网直接访问
默认网关指的是:当前网络中,负责转发不在本地子网内的数据包的下一跳 IP 地址,它不一定能访问公网,但必须能连接到“外面”;
基本上发送到默认网关 MAC 地址的数据包,都是“要发到外部网络”的
关于网桥(只能看到MAC,看不到 IP ):
会学习每个 MAC 是从哪个接口来的(MAC 学习表);
如果它知道目标 MAC → 只发到对应接口;
如果它不知道目标 MAC → 广播到所有接口(Flood)。

  • 如果是网桥模式:
    • 每个容器将分配一个子网 IP ,如 172.17.0.2/16 ,如果它想要发送请求到 公网 ip 8.8.8.8 ,首先,它得找到本子网段的网关对应的mac 地址,以便于它知道自己的下一跳是哪里。于是它广播了一个 ARP 请求,询问网关的MAC
    • 内核网关 docker0 以 172.16.0.1 的身份接收到请求后,发送了自己的MAC地址,于是该容器记录了这个MAC地址,发送了目的IP 是 8.8.8.8 的请求。
    • 网关 docker0 接收到请求后,将请求发送到网络 “外部”,这个请求将注入宿主机协议栈,宿主机物理网卡就是中间的一跳,如果发现目标 ip 不在当前子网中,就会发送给当前网段的默认网关,即路由器,路由器将请求发送出去。
  • 使用 host 模式后:
    • 容器就像是“宿主机的一个进程”一样参与网络;
    • 它直接在宿主机所在局域网中;
    • 也直接使用宿主机的默认网关;
    • 但也失去了容器间网络隔离的优势。
  • container 模式:
    • 两台容器公用统一IP 和端口
  • none 模式:
    • 只允许容器自己给自己发消息
  • 自定义网络模式:
    • 相比于直接的桥接模式,自定义网络本身就建立了主机名和ip 的映射关系,不管是ping 主机名还是 ping IP 都能 ping 通
  • docker0 网络内部存在DNS服务器 172.12.0.11 , 可以把容器名解析到对应的局域网IP
自定义网络
1
docker network create --driver bridge --subnet 182.18.0.0/16  custom_network_name
  • 如果直接inspect 能发现网关、IPAddress、MacAddress 等网络字段

6 Docker 集群

  • 可以使用 Docker Swarm
  • 但是使用 Kubernets 更方便