目录

系统学docker笔记

什么是docker

Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。

Docker 是当前流行的 Linux 容器解决方案,利用 Namespaces 、Cgroups 以及联合文件系统UnionFS 实现了同一主机上容器进程间的相互隔离。

  • NameSpaces:隔离进程,让进程只能访问到本命名空间里的挂载目录、PID、NetWork 等资源
  • Cgroups: 限制进程能使用的计算机系统各项资源的上限,包括 CPU、内存、磁盘、网络带宽等等
  • 联合文件系统UnionFS : 保存一个操作系统的所有文件和目录,在它基础之上添加应用运行依赖的文件。创建容器进程的时候给进程指定Mount Namespace 把镜像文件挂载到容器里,用 chroot 把进程的 Root目录切换到挂载的目录里,从而让容器进程各自拥有独立的操作系统目录。

虚拟化和docker区别

传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。

./虚拟机和docker架构区别.png

docker cs架构

docker是cs结构,Docker桌面版安装包括了Docker Client和Docker Engine。

主要包含:

  • 后台进程(dockerd)
  • rest api server
  • cli接口(docker)

./docker_cs架构.png

Docker的Client和Engine之间的通讯有一下几种方式

  • Unix Socket 这是类unix系统进程间通讯的一种方式,当Client操作本机的Engine是就是使用这种方式。缺省的socket文件是unix:///var/run/docker.sock
  • Systemd socket activation : 这是systemd提供的一种为了服务并行启动设计的socket,
  • TCP : 上面两种都是只能连接本地Engine,需要连接远程Engine,必须在服务端开始TCP连接。此连接为不安全连接,数据通过明文进行传输。缺省端口2375。
  • TCP_TLS : 在TCP的基础之上加上了SSL的安全证书,以保证连接安全。缺省端口2376。

docker 底层技术支持

  • Namespaces:隔离pid,net,ipc,mnt,uts
  • Control groups:做资源限制
  • Union file systems:Conatiner和image的分层

镜像

Dockerfile命令

workdir

workdir等于linux cd命令

workdir /test # 如果没有会自动创建
workdir demo
run pwd # 输出结果为/test/demo

推荐workdir,不要 run cd。尽量使用绝对路径。

ADD COPY

对于目录而言,COPY 和 ADD 命令具有相同的特点:只复制目录中的内容而不包含目录自身。

ADD 命令可以完成 COPY 命令的所有功能,是copy的增强版,并且还可以完成两类超酷的功能:

  1. 解压压缩文件并把它们添加到镜像中
  2. 从 url 拷贝文件到镜像中

当然,这些功能也让 ADD 命令用起来复杂一些,不如 COPY 命令那么直观。 docker 官方建议我们当需要从远程复制文件时,最好使用 curl 或 wget 命令来代替 ADD 命令。原因是,当使用 ADD 命令时,会创建更多的镜像层,当然镜像的 size 也会更大

EXPOSE

expose是对端口的暴露声明,记住是声明,不写也没事。

写了expose后,运行容器时如果加-P参数,就会对expose声明的端口进行和宿主主机端口随机映射。

VOLUME

定义匿名数据卷 valume /test/data 这里会自动生成一个volume,然后/test/data和自动生成的那个目录映射。 docker run的时候如果使用-v,–mount可以覆盖dockerfile里面的这个命令。

CMD

Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。

多个cmd命令会覆盖。 docker run时如果指定入口程序也会覆盖Dcokerfile中的cmd。比如

docker run -it hello /bin/bash
// /bin/bash就会覆盖cmd命令

ENTRYPOINT

ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。

ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 –entrypoint 来指定。

当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:

<ENTRYPOINT> "<CMD>"

docker run -it hello /bin/bashz这个例子中的/bin/bash也会当做entrypoint的参数。

容器

看几个特点:

  • 通过image创建(copy)
  • image是只读的。再image layer之上建立一个container layer(可读写)
  • image和container类比面向对象的类和示例
  • image负责APP的存储和分发,container负责运行APP

image是只读的,那从Dockerfile构建image的过程中,docker build是怎么执行命令修改的呢? 答:构建过程中会生成临时的contailer,其实是在容器上执行的操作,后面再把临时容器删除,又容器commit成image。

数据管理

把写到容器里面的东西写到宿主主机上。 分两种:

  1. volume类型,通过docker volume ls可以看到
  2. bind类型,这种不会不会生成volume

volume类型匿名挂载: docker run -v 容器内路径
DockerFile中volume命令

volume类型具名挂载:
-v 卷名:容器内路径

bind类型
docker run -v /主机路径:容器内路径 # 指定路径挂载 docker –mount type=bind,source=/src/webapp,target=/usr/share/