docker 复习笔记
安装文档:https://docs.docker.com/engine/install/[官网文档]
docker 心得

所有的技术诞生都是为了解决某一个问题!
docker 的诞生的意义
将目标应用以及其依赖的环境进行统一打包成一个镜像,使得在任何环境下都操作这个镜像即可,不必考虑环境配置等其他问题。
目前常见开发部署流程为:开发环境→测试环境→生产环境,甚至还有其他的环境。以一个java应用为例,依赖某个版本jdk,当开发人员开发完成后,需要部署到测试环境,那么测试环境也需要安装对应版本的jdk,测试完成后,需要部署到生产,生产环境也要先安装对应版本的jdk,那么每当出现一个新环境,那么都需要安装一遍jdk,并且保证版本一致,如果java的应用依赖不止jdk,还有其他应用,例如tomcat、mysql、redis等等,那么每个环境都需要进行相应的部署,并且应用本身以及其依赖的应用版本发生变化时,那么每个环境也要相应的进行调整,这就会导致每个环境都会做重复的事情。所以能不能一次性交付一个完整的应用,包含其所有的依赖,不同环境只需要运行一个应用即可,这样就减少很多重复工作,做到一次打包,多处运行。因此docker出现了,从它的图标也可知晓,一个docker镜像包含很多个集装箱,每个集装箱都相当于是一个环境依赖,一次性将所有的依赖统一打包成一体。

总结下:使用docker之前,各个环境都必须单独的部署或者降级、升级服务,使用docker后,所有的服务都在开发阶段处理并统一打包成docker镜像,不同的环境只需要拉去docker镜像即可。
虚拟化技术

VM(VMware)在宿主机器、宿主机器操作系统的基础上创建虚拟层、虚拟化的操作系统、虚拟化的仓库,然后再安装应用;
Container(Docker容器),在宿主机器、宿主机器操作系统上创建Docker引擎,在引擎的基础上再安装应用。
docker 和虚拟化技术的区别
-
传统虚拟化技术,虚拟化硬件,启动一个完整的系统,然后在这个系统上面安装和运行软件,docker容器则是在宿主机上直接运行,没有自己的内核,也没有虚拟化硬件
-
每个容器间相互隔离,每个容器内都有自己的文件系统,互不影响。
-
VM 占用内存以及磁盘更大,这是因为它完全是虚拟出一个全新的系统
-
VM 启动速度慢,因为它是一个完整的操作系统
-
docker 的集成性优于VM
docker 的目标
-
缩短开发到测试部署,再到上线的周期,应用更快的部署和交付
-
更便捷的升级和扩缩容
-
易于移植
-
易于构建,可随时修改容器中的环境
-
启动快
-
容器之间相互隔离
-
同一台宿主机中可以运行多个容器,并且能充分利用服务器资源
docker 的基本组成

概览
命令流程示意图

-
Images – 镜像相关命令 – rmi 移除镜像 – tag 标签 – history 进行制作历史
-
Host
-
Container
-
Files
-
Dockfile
-
Registry
-
Engine
分层结构

docker 常用命令
查看docker基本信息
docker info
查看docker版本信息
docker version
查看docker对应功能的帮助文档
docker 命令 --help
镜像命令
帮助:
docker image --help
查询所有镜像:
docker images
搜索镜像(具体还是去docker hub上查看吧):
docker search mysql
拉取镜像(如果不加版本tag,则默认拉取:latest,如果目标应用没有latest这个版本会报错):
docker pull mysql
docker pull mysql:5.7
docker pull docker.io/library/mysql:latest
删除镜像:
docker rmi --help
docker rmi 容器id
docker rmi REPOSITORY:tag
====容器
命令帮助
docker run --help
新建容器并启动
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
OPTIONS:
-
-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
-
-d: 后台运行容器,并返回容器ID;
-
-i: 以交互模式运行容器,通常与 -t 同时使用;
-
-P: 随机端口映射,容器内部端口随机映射到主机的端口
-
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口
-
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
-
–name=“nginx-lb”: 为容器指定一个名称;
-
–dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
-
–dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
-
-h “mars”: 指定容器的hostname;
-
-e username=“ritchie”: 设置环境变量;
-
–env-file=[]: 从指定文件读入环境变量;
-
–cpuset=“0-2” or –cpuset=“0,1,2”: 绑定容器到指定CPU运行;
-
-m :设置容器使用内存最大值;
-
–net=“bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
-
–link=[]: 添加链接到另一个容器;
-
-expose=[]: 开放一个端口或一组端口;
-
–volume , -v: 绑定一个卷
查看正在运行的容器
docker ps
查看所有运行过的容器
docker ps -a
操作容器状态
docker start/stop/restart/kill [容器id][容器名称]
删除已停止的容器
docker rm [容器id][容器名称]
删除运行中的容器
docker rm -f [容器id][容器名称]
删除所有容器
docker rm -f $(docker ps -aq)
docker ps -a -q | xargs docker rm
查看容器日志
docker logs -f -t --tail 1000 [容器id]
-
1000 表示数量
查看容器中的进程:
docker top [容器id]
查看容器的信息:
docker inspect [容器id]
进入容器:
docker exec -it [容器id] /bin/bash
拷贝容器中的文件
docker cp 容器id:/path/file/ /home/file
-
/path/file:容器中的文件
-
/home/file: 主机中的文件地址
查看容器资源占用情况:
docker stats
常见问题:
-
要使 docker 容器后台运行,一定要在启动时加上 -d 参数。
commit 镜像
将一个使用中的容器打包成新的镜像
docker commit -m="描述" -a="作者" 容器id 目标镜像名:[tag]
可视化web界面
Potainer
docker run -d -p 9000:9000 --name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:2.9.3
注:这里开放端口9000,http访问,官方文档还开放了
-p 8000:8000 -p 9443:9443
,
8000是一个tcp端口,9443,是https访问,根据实际调整。
通过 Portainer 可以在web界面直接操作镜像、容器、数据卷、网络等,实质就是将命令以可视化的形式提供操作。
Rancher CI/CD
镜像原理
UnionFS 联合文件系统
联合文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一虚拟文件系统下。UnionFS 是docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像可以制作出各种具体的应用镜像。
Docker 镜像加载原理
docker 镜像实际上是由一层层文件系统组成,这种层级文件系统就是UnionFS。
bootfs: 主要包含bootloader以及kernel,linux启动时会加载bootfs文件系统,这里牵涉到些linux系统启动过程。主要作用就是将内核加载到内存中,加载完成后,会卸载bootfs。
rootfs: 各种不同操作系统发行版的一些标准目录和文件,例如Ubuntu/Centos发行版中的 /dev、/porc、/bin等等文件。
详见分层结构

注:bootfs 是所有共有的,而rootfs则是具体需要的,所有镜像共有部分都不要,而只关注各种不同的rootfs,一个精简的系统,rootfs是可以很小的,所以当我们查看image的大小时,会发现centos/ubuntu等size都很小,这是因为其中的bootfs都是相似的,并不包含在这个镜像中,底层直接使用了宿主机的bootfs。
这里就可以知道为什么虚拟机启动是分钟级,而容器是秒级的? bootfs由宿主机完成,容器是不需要执行的,所以很快。
理解 Docker 分层
所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。相同的层级可以共用,这样也能理解在pull镜像时,如果底层的镜像层已经存在,那么就不会再去拉取了。

数据卷
为什么要有数据卷?
容器中的数据,一旦容器销毁,则数据随之销毁,因此,如果需要持久化容器中的数据,那么得将数据存储在宿主机本地,因此则需要数据卷。
例如 mysql中的数据需要持久化,肯定不能随着容器的删除而删除,那么就得将容器中mysql的数据同步到宿主机中,这样即使删除容器,那么其数据也不会丢失。
容器的持久化和同步操作,容器间的数据可以共享。数据卷的挂载方式有如下四种。
方式一:挂载宿主机的目录以及对应容器中的目录
docker run -it -v 主机目录:容器中的目录
方式二:匿名挂载:-v 容器路径
匿名挂载,只需要指定容器中的文件路径,在宿主机中,会由docker默认创建一个目录进行挂载。
其存放位置为
/var/lib/docker/volume/2f50c3744cc2b0ec800669c89bc727efdaf83c59cc56c45b42abff236bfe9a0f
root@wangxiao-docker:/home/mysql/data/test# docker volume ls DRIVER VOLUME NAME local 2f50c3744cc2b0ec800669c89bc727efdaf83c59cc56c45b42abff236bfe9a0f
方式三:具名挂载:-v 名字:容器路径
其存放位置为 /var/lib/docker/volume/nginx-data
DRIVER VOLUME NAME local nginx-data
方式四:创建镜像的时候可以进行挂载
FROM centos
# 只能创建匿名挂载
VOLUME ["volume1", "volume2", "volume3"]
CMD echo "-----end"
CMD /bin/bash
DockerFile 创建自己的镜像
指令列表

基础知识
-
指令必须大写
-
执行从上到下顺序执行
-
#
表示注释 -
每一个指令都会创建提交一个新的镜像层,并提交
-
创建一个镜像需要一个dockerfile文件描述镜像,以及使用
docker build
命令
通过 DockerFile 文件创建镜像
案例,构建自己的centos
root@wangxiao-docker:/home/file# cat mydockerfile
FROM ubuntu
MAINTAINER wanghengzhi<zerothreeoneone@foxmail.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN apt-get update
RUN apt-get -y install vim
RUN apt-get -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "-----end------"
CMD /bin/bash
root@wangxiao-docker:/home/file# docker build -f ./mydockerfile -t wanghengzhi/ubuntu:1.0 .
CMD 命令与 ENTRYPOINT 命令
CMD: 指定这个容器启动时要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT: 指定这个容器启动时要运行的命令,可以追加命令。
# ls -a 会替换掉容器最开始默认的命令 /bin/bash docker run -it wanghengzhi/ubuntu:1.0 ls -a
如果构建的镜像中使用ENTRYPOINT,则会执行原来的命令,并且也执行启动时指定的命令
案例
# docker import和docker load的区别是什么?
发布镜像
将自行构建的镜像发布到仓库中,可以是公有仓库,也可以自己搭建私服。
步骤
-
docker login -u username
-
docker push 镜像名:tag
提交的时候也是按照层级提交的。
docker 全流程

docker 网络
docker0 理解
ip addr

-
启动docker服务后,就会创建一个docker0桥接网络
-
每启动一个docker容器,docker会给容器分配一个ip,通过宿主机是能够ping通的。
-
veth-pair 技术,一对虚拟设备接口,成对出现,充当桥梁,链接各种虚拟网络
-
容器和容器之间也能ping通
容器之间并不是直接连接的,而是通过docker0进行链接的。
link
通过–link在启动容器时指定连接的服务,后面可以直接通过link的服务名,进行ping通,其原理,是内部保存了一个link服务的地址信息,可以通过
docker inspect
查看。但是link的服务不能反向ping通当前服务。
自定义网络
docker network COMMAND
网络模式
-
brigde: 桥接模式,默认模式
-
none: 不配置网络
-
host: 和宿主机共享网络
-
container: 容器网络连通
创建网络
docker network create --driver bridge --subnet 192.168.0.0/24 --gatway 192.168.0.1 mynet
查看网络
docker network inspect mynet
容器指定网络
docker run .... --net mynet ....
在自定义网络中,不需要使用 link 指定,可以直接使用容器名进行ping通。
网络连通
将一个容器连接到另一个网络中,其实质就是将容器加入到网络配置中。
docker network connect mynet tomcat1
后记
docker.service: Failed with result ’exit-code‘
dockerd --debug
查询原因