目录
docker出现背景
以前环境配置相当麻烦,换一台机器就要重来一次,费时费力;因此就有人想要从根本上解决问题——软件可以带环境安装(把原始环境一模一样的复制过来,这样开发人员利用docker可以消除协作编码时在自己的机器上可正常工作的问题)
docker的主要目标:通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户app(可以是web应用或数据库应用等)及运行环境做到“一次镜像、处处运行”
理解:linux容器技术的出现解决了这样一个问题,而docker就是在他的基础上发展过来的。他将应用打成镜像,通过镜像成为运行在docker容器上面的实例,而docker容器在任何操作系统上都是一致的,这就实现了跨平台,跨服务器。只需要一次配置好的环境,换到别的机子上就可以一键部署好,大大的简化了操作。
总结:docker是基于go语言实现的云开源项目,其解决了运行环境配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术
docker相关注意事项
- docker并非一个通用的容器工具,它依赖于已经存在并运行的linux内核环境
- docker实质上是在已经运行的linux下制造一个隔离的文件环境,因此他的执行效率几乎等同于所部署的linux主机
- docker必须部署在linux内核的系统上,若其他系统想要部署docker,则必须安装一个虚拟的linux环境
虚拟机与容器的对比
虚拟机
含义:虚拟机就是带环境安装的一种解决方案,传统虚拟机是安装在主操作系统上的,创建虚拟机(虚拟出各种硬件),在虚拟机上安装操作系统,后再虚拟机中的操作系统中安装和部署各种应用。
虚拟机的缺点
- 资源占用多
- 冗余步骤多
- 启动慢
linux容器
含义:linux容器是与系统其他部分隔离的一系列进程,从另一个镜像中运行,并由该镜像提供支持进程所需的全部文件.容器提供的镜像包含了应用的所有依赖项,因而从开发到测试再到生产过程中,他都具有可移植性(可移植的其他操作系统)和一致性(移植后的内容与运行状态一致)
虚拟机与容器不同点
- 传统虚拟机是虚拟出一套硬件后,在其上运行一套完整的操作系统,在该系统上再运行所需要的应用进程
- 容器内的进程直接运行于宿主机的内核中,容器内没有自己的内核且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便
- 每个容器之间相互隔离,每个容器有自己的文件系统,容器之间的进程不会相互影响,能区分计算资源
docker相关网址
docker官网:https://www.docker.com/
docker镜像仓库:https://hub.docker.com/
docker三要素
docker三要素:镜像、容器、仓库
- 镜像:docker 镜像可以看成是磁盘上特殊的文件系统,镜像打包了应用的运行环境以及应用程序。
- 容器:运行docker镜像的载体
- 镜像仓库:存放docker镜像文件的地方
总结:docker镜像就相当于一个root文件系统,把我们能够运行的源代码、配置环境、第三方依赖包打包成一个镜像,通过镜像在docker容器中创建docker实例,而docker镜像可以从docker仓库中获取
docker架构图
理解:
- 我们本地开发的微服务可以通过docker build成一个docker镜像,塞在本地的docker引擎里面
- 若我们想要用的镜像本地没有,那么则会通过docker pull命令从远程来拉取docker镜像
- 这些镜像可以通过docker run命令来开启docker容器(其会先检查本地有没有该镜像,若没有则从仓库中下载后再开启容器)
docker工作原理
docker是一个client-server结构的系统,docker的守护进程运行在主机上,然后通过socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。(容器是一个运行时环境,就类似于集装箱)
docker的安装与卸载
首先确定是Centos7及以上版本
cat /etc/redhat-release
卸载docker旧版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
安装gcc依赖
yum -y install gcc
安装gcc-c++ 语言
yum -y install gcc-c++
安装需要的软件包
yum install -y yum-utils
设置stable镜像仓库(国内仓库)
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
更新yum软件索引
yum makecache fast
安装最新版本的 Docker Engine、containerd 和 Docker Compose
yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
查看docker 版本
docker version
启动docker
systemctl start docker
使用 status查看运行状态
systemctl status docker
停止docker运行
systemctl stop docker
运行hello-world镜像
docker run hello-world
卸载docker
卸载 Docker Engine、CLI、Containerd 和 Docker Compose 软件包
yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin
主机上的映像、容器、卷或自定义配置文件不会自动删除。要删除所有映像、容器和卷
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
docker基础命令
- 启动docker:systemctl start docker
- 关闭docker:systemctl stop docker
- 重启docker:systemctl restart docker
- 查看docker状态:systemctl status docker
- 开机启动docker:systemctl enable docker
- 禁止开机自启docker:systemctl disable docker
- 查看docker概要:docker info
- docker总体帮助文档:docker --help
docker镜像命令
- 列出本地的镜像:docker images(-a:列出本地所有镜像、-q:只显示镜像id)
- 仓库中查询镜像:docker search [--limit n] 镜像名
- 仓库中下载镜像:docker pull 镜像名[:TAG](注意:tag代表版本号)
- 查看镜像/容器/数据卷所占的空间:docker system df
- 删除镜像(镜像容器运行则删除失败):docker rmi 镜像名1/镜像id1 镜像名2/镜像id2
- 强制删除镜像:docker rmi -f 镜像名1/镜像id1 镜像名2/镜像id2
- 强制删除所有docker镜像:docker rmi -f $(docker images -qa)
- 查看镜像文件详情:docker inspect 镜像名
- 查看镜像使用历史:docker history 镜像名
- 当前文件夹下导出镜像文件:docker save 镜像名 | gzip > 镜像名.tar.gz
- 当前文件夹下导入镜像操作:docker load < 镜像名.tar.gz
容器命令
新建并启动容器
命令:docker run [options] 镜像名[:版本号] [command]
注意:如果不写版本号则默认使用最新版本
options属性
- --name=容器的新名字
- -d:后台运行容器并返回容器id
- -i:以交互模式运行容器,通常与-t一起使用
- -t:为容器重新分配一个伪输入终端,通常与-i一起使用
- -p 8080:8081:访问外面的8080端口就会访问docker容器的8081端口
command属性
- /bin/bash(也可以直接写bash):表示进入操作终端
在docker内退出容器
- exit:退出容器后容器停止
- ctrl+p+q:退出容器后容器不停止
列出当前正在运行的容器
命令:docker ps [options]
options属性
- -a:列出当前正在运行的程序和历史上运行过的
- -l:显示最近创建的容器
- -n 3:显示最近创建的3个容器
- -q:静默模式,只显示容器编号
容器的启动与停止
重新启动容器:docker [container] start 容器id的前几位(通常用前3位)
停止运行容器:docker [container] stop 容器id的前几位
强制停止容器:docker kill 容器id的前几位/容器名
注意:可以同时启动或停止多个容器
容器的删除命令
删除不运行的容器:docker [container] rm 容器id1 容器id2
删除容器(包括运行的):docker [container] rm -f 容器id1 容器id2
清理所有终止掉的容器:docker container prune
注意:可以同时删除多个容器
容器的查看命令
查看容器启动运行日志:docker [container] logs 容器id
查看容器内运行的进程:docker top 容器id
查看容器内部细节:docker inspect 容器id
容器的进入命令
前言:exec是在容器中打开新的终端,并且可以启动新的进程,用exit退出不会导致容器的停止
命令:docker exec -it 容器id bash
将docker容器内的文件拷贝到主机
命令:docker cp 容器id:容器内路径 目标主机路径
注意:在主机的环境下执行
导入和导出容器
导出容器到目标主机:docker export 容器id > 文件名.tar(可以是已经停止运行的容器)
从目标主机中导入容器:cat 镜像名.tar | docker import - 镜像名:镜像版本号
docker镜像
含义:其是一种轻量级的,可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码,运行时所需要的库,环境变量和配置文件等),这个打包好的运行环境就是image镜像文件
联合文件系统
含义:其是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同的目录挂载到同一个虚拟文件系统下;联合文件系统是docker镜像的基础。镜像可以通过分层来实现继承,基于基础镜像可以制作各种具体的应用镜像
提交镜像
docker容器内执行
apt-get update(更新包管理工具)
apt-get install net-tools(安装我们需要的net-tools)
ubuntu内安装vim
docker容器内执行
apt-get update(更新包管理工具)
apt-get -y install vim(安装我们需要的vim)
如今,我们的ubuntu镜像已经具备vim与ifconfig命令
提交镜像:docker commit -m="描述信息" -a="作者" 容器id 创建的镜像名:版本号
注意:提交镜像与导出镜像到主机的区别是提交镜像并不会生成压缩文件,只会将镜像提交到本地,其中可以用docker images命令查看本地镜像
本地镜像发布到阿里云
登录:docker login --username=阿里云账号名称 registry.cn-hangzhou.aliyuncs.com
重命名:docker tag 容器id registry.cn-hangzhou.aliyuncs.com/cjcnamespace/发布的镜像名:[镜像版本号]
提交:docker push registry.cn-hangzhou.aliyuncs.com/cjcnamespace/发布的镜像名:[镜像版本号]
将阿里云的镜像下载到本地使用
拉取:docker pull registry.cn-hangzhou.aliyuncs.com/cjcnamespace/镜像名:[镜像版本号]
将本地镜像发布到私有仓库
搭建个人企业版docker hub
拉取registry镜像:docker pull registry
启动registry容器
eg:docker run -d -p 5000:5000 -v /root/myregistry/:/tmp/registry --privileged=true registry
将新镜像改为符合私服规范的tag(就相当于复制加重命名)
docker tag 镜像名:版本号 虚拟机ip:5000/镜像名:版本号
修改配置文件使docker私服库支持http形式的推送
进入:vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://wiowcbi1.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.126.129:5000"]
}
重启docker:systemctl restart docker
将本地制作的镜像推送到私服库
命令:docker push 虚拟机ip:5000/镜像名:版本号
查看镜像仓库
命令:curl -XGET http://虚拟机ip:5000/v2/_catalog
从私有仓库拉取镜像
命令:docker pull 虚拟机ip:5000/镜像名:镜像版本号
docker数据管理
管理数据的两种方式
- 数据卷(Volumes)
- 挂载主机目录 (Bind mounts)
数据卷
概念:卷就是目录或文件,存在于一个或多个容器当中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过联合文件系统提供一些用于持续储存或共享数据的特性
理解:卷设计的目的就是数据的持久化,完全独立于容器的生命周期,因此docker不会再容器删除时删除挂载的数据卷
数据卷的作用:映射目录以后,完成敏感数据的持久化和备份到主机目录
数据卷的特点
- 数据卷可以在容器之间共享和重用数据
- 卷中的更改可以直接实时生效
- 数据卷的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
数据卷基础命令
创建数据卷:docker volume create 数据卷名
查看数据卷:docker volume ls
查看指定数据卷信息:docker volume inspect 数据卷名
[ { "CreatedAt": "2022-10-03T16:28:21+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/datavol/_data", "Name": "datavol", "Options": {}, "Scope": "local" } ]
挂载数据:docker run -it --mount source=数据卷名,target=主机目录 镜像名 bash
挂载数据简写形式:docker run -it -v 数据卷名:主机目录 镜像名 bash
删除容器没有使用的数据卷:docker volume rm 数据卷名
清除所有没有使用的数据卷:docker volume prune
挂载主机目录
例子:docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
注意:
- docker挂载主机目录访问若出现cannot open directory:Permission denied,那么你就在挂载目录后多加一个--privileged=true参数即可
- 挂载主机的目录,若主机目录不存在,则会自动创建对应目录
- 宿主机绝对路径目录下对应的文件可以和容器内目录对应的文件互联互通
- -v可以有多个,一个-v就是绑定一组目录
挂载的ro和rw读写规则
- ro:只读
- rw:读写
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
(默认)等同于
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
注意:这种方式使用容器卷则在对应容器卷内进行修改操作是不被允许的
数据卷之间的继承和共享
命令:docker run -it --volumes-from 父容器名字 --name=容器名字 镜像名
结果:该容器继承了父容器的数据卷的规则
dockerfile镜像制作
含义:其是用来构建docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本
构建镜像的三个步骤
- 编写Dockerfile文件
- docker build命令构建镜像
- docker run依照镜像运行容器实例
dockerfile内容基础知识
- 每条保留字指令都必须为大写字母且后面要跟至少一个参数
- 指令按照从上到下顺序执行
- #表示注释
- 每条指令都会创建一个新的镜像层并对镜像进行提交
Dockerfile的指令
ENTRYPOINT ["java","-jar","/usr/local/包名.jar"]:指定这个容器启动时可追加的命令,可追加命令
注意:Docker Hub中99%的镜像都是从scratch这个基础镜像过来的
CMD和ENTRYPOINT区别
dockerfile1文件
FROM centos
CMD ["ls","-a"]或ENTRYPOINT ["ls","-a"]
构建镜像:docker build -f dockerfile1 -t cmdtest .
执行:docker run cmdtest
结果:用CMD的启动之后就执行ls -a命令,但是在后面加-l(docker run cmdtest -l)就会报错,
用ENTRYPOINT的启动之后就执行ls -a命令,但是在后面加-l就会追加-l(在命令台输入的命令就为cmd命令)
构建dockerfile
需求:为centos加vim与net-tools插件与jdk8
vim Dockerfile1
这里我写的dockerfile名为Dockerfile1
#centos作为基础镜像
FROM centos:7
#书写具体的个人信息
MAINTAINER cjc<1111111111@qq.com>
#配置环境(键值对形式)
ENV MYPATH /usr/local
#配置工作目录,进入容器后就会自动进入该目录
WORKDIR $MYPATH
#基于以上镜像执行命令并提交到新镜像中
RUN yum -y install vim
RUN yum -y install net-tools
#安装java8及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#将源文件复制到目标文件
ADD jdk-8u51-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_51
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH JAVA_HOME/bin:$PATH
#暴露端口80
EXPOSE 80
#执行启动容器时要运行的脚本
CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
构建镜像:docker build -f Dockerfile1 -t centosadd:1.0 .
注意:
- -f:表示构建镜像的dockerfile的名字
- -t:表示新构建镜像的名字
- 最后的“.”必须存在,他表示在当前文件夹下构建
docker全流程
docker网络
虚拟机内输入命令:ip addr
网络模式
- bridge:桥接(默认)
- none:不配置网络
- host:和宿主机共享网路
docker网络测试
启动tomcat1:docker run -d -P --name=tomcat1 tomcat
启动tomcat2:docker run -d -P --name=tomcat2 tomcat
查看容器ip地址:docker inspect 容器名
查看tomcat1容器ip地址:172.17.0.2
查看tomcat2容器ip地址:172.17.0.3
容器外ping 172.17.0.2/172.17.0.3——结果可以ping通
总结:由此观之,linux宿主机可以ping通docker容器
tomcat2内安装ping工具
apt-get update
apt-get install iputils-ping
在tomcat2容器内ping容器tomcat1:ping 172.17.0.2
结果发现可以ping通
本质:tomcat1和tomcat2共用的是同一个路由器,也就是上面看到的docker0;之后所有的容器若不指定网络的情况下,默认都是docker0路由的。
总结:docker内两个容器之间可以互相ping通(默认网络连接为桥接方式)
docker网络连接原理
前言:
- 我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker那么就会有一个网卡(docker0)其网卡用的是桥接模式,所用的技术为evth-pair技术
- evth-pair技术就是一对虚拟设备接口,他们都是成对出现的,正因为有这个特性,evth-pair充当着一个桥梁,连接着各种虚拟网络设备(docker0网卡与容器)
- docker0通过evth-pair技术与容器进行互联,从而可以与容器之间进行通信,只要启动一个容器就会通过docker0网桥
注意:
- docker使用的是linux的桥接,宿主机是一个docker容器的网桥——docker0
- docker中的所有网络接口都是虚拟的(虚拟的转发效率高)
- 只要对应的容器删除,那么对应网桥的一对veth就会消失
docker之--link容器互联
前言:在之前我已经提交了带ping命令的tomcatadd:1.0
启动tomcat1:docker run -d -P --name=tomcat1 tomcatadd:1.0
启动并使tomcat2与tomcat1相联:docker run -d -P --name=tomcat2 --link tomcat1 tomcatadd:1.0
用tomcat2来ping容器tomcat1:docker exec -it tomcat2 ping tomcat1
结果:用tomcat2来ping容器tomcat1能够ping通
用tomcat1来ping容器tomcat2:docker exec -it tomcat1 ping tomcat2
结果:用tomcat1来ping容器tomcat2不能够ping通
总结:
- 通过--link进行容器互联,那么只有正向可以ping通,反向ping不通(但是可以互相绑定)
- --link方式的容器互联允许ping 容器名
- 因为tomcat2的host文件直接将tomcat1当作域名写了进入所以正向ping可以,反向不可
自定义网络
基础命令
查看所有docker网络:docker network ls
查看网络信息:docker inspect 网络id
注意:网络模式若不写,则默认为桥接模式
docker run -d -P --name=tomcat1 --net bridge tomcatadd:1.0
=
docker run -d -P --name=tomcat1 tomcatadd:1.0
创建网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
属性说明
- --driver:网络类型(默认bridge,因此可省略)
- --subnet:子网
- --gateway:网关
创建容器并指定网络
启动tomcat1:docker run -d -P --name=tomcat1 --net mynet tomcatadd:1.0
启动tomcat2:docker run -d -P --name=tomcat2 --net mynet tomcatadd:1.0
结果:两个容器内互相ping可以ping通,也可以实现ping容器名
其他命令
断开网络:docker network disconnect 网络名 容器名
将容器连入网络:docker network connect 网络名 容器名
删除网络:docker network rm 网络id
删除网络的前提:没有容器使用该网络