1.概述
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了。
应用场景
- Web 应用的自动化打包和发布。
- 自动化测试和持续集成、发布。
- 在服务型环境中部署和调整数据库或其他的后台应用。
- 从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。
优点
1、快速,一致地交付您的应用程序
Docker 允许开发人员使用您提供的应用程序或服务的本地容器在标准化环境中工作,从而简化了开发的生命周期。
容器非常适合持续集成和持续交付(CI / CD)工作流程,请考虑以下示例方案:
- 您的开发人员在本地编写代码,并使用 Docker 容器与同事共享他们的工作。
- 他们使用 Docker 将其应用程序推送到测试环境中,并执行自动或手动测试。
- 当开发人员发现错误时,他们可以在开发环境中对其进行修复,然后将其重新部署到测试环境中,以进行测试和验证。
- 测试完成后,将修补程序推送给生产环境,就像将更新的镜像推送到生产环境一样简单。
2、响应式部署和扩展
Docker 是基于容器的平台,允许高度可移植的工作负载。Docker 容器可以在开发人员的本机上,数据中心的物理或虚拟机上,云服务上或混合环境中运行。
Docker 的可移植性和轻量级的特性,还可以使您轻松地完成动态管理的工作负担,并根据业务需求指示,实时扩展或拆除应用程序和服务。
3、在同一硬件上运行更多工作负载
Docker 轻巧快速。它为基于虚拟机管理程序的虚拟机提供了可行、经济、高效的替代方案,因此您可以利用更多的计算能力来实现业务目标。Docker 非常适合于高密度环境以及中小型部署,而您可以用更少的资源做更多的事情。
2.架构
Docker 包括三个基本概念:
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
Docker 容器通过 Docker 镜像来创建。
容器与镜像的关系类似于面向对象编程中的对象与类。
Docker | 面向对象 |
---|---|
容器 | 对象 |
镜像 | 类 |
概念 | 说明 |
---|---|
Docker 镜像(Images) | Docker 镜像是用于创建 Docker 容器的模板,比如 Ubuntu 系统。 |
Docker 容器(Container) | 容器是独立运行的一个或一组应用,是镜像运行时的实体。 |
Docker 客户端(Client) | Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。 |
Docker 主机(Host) | 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。 |
Docker Registry | Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。 |
Docker Machine | Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。 |
3.安装
# 卸载旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 需要的安装包
yum install -y yum-utils
# 设置镜像的仓库
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo #默认是国外,很慢
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# 阿里云
sudo yum-config-manager \
--add-repo \
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo#清华
# 更新yum软件包索引
yum makecache fast
# 安装docker相关的内容 docker-ce社区版 ee版是企业版
sudo yum install docker-ce docker-ce-cli containerd.io
# 启动docker
systemctl start docker
# 查看版本
docker version
# hello-world程序启动
docker run hello-world
# 查看下载的hello-world镜像
docker images
4.卸载docker
sudo yum remove docker-ce docker-ce-cli containerd.io
sudo rm -rf /var/lib/docker
5. 阿里云镜像加速
首先找到容器镜像服务
找到镜像加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://285bx8r3.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
6.docker的run流程
7.底层原理
Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过socket从客户端访问
DockerServer接收到Docker-Client的指令,就会执行这个指令
Docker为什么比虚拟机快?
Docker有比虚拟机更少的抽象层
Docker利用的是宿主机的内核,虚拟机需要的是GuestOS
所以说新建一个容器的时候,docker不需要像虚拟机一样重新加载操作系统内核,避免引导。虚拟机加载GuestOS,分钟级别的,而docker是利用宿主机的操作系统,省略了这个复杂过程,秒级.
8.Docker常用命令
8.1.帮助命令
docker version #查看docker基本信息
docker info #显示docker更加详细的信息
docker 命令 --help #获取一个命令的帮助信息
帮助文档地址:https://docs.docker.com/reference/
8.2.镜像命令
docker images #查看所有本地的主机上的镜像
-a #列出所有镜像
-q #只显示镜像id
docker search 参数 #搜索镜像
-f #通过收藏数例来过滤
docker search mysql -f=STARS=3000 #搜索出来的镜像就是STARS大于3000的
docker pull 镜像名[:tag] #下载镜像为tag的版本 如果不写tag就是最新版
#下载的时候是分层下载,Digest是签名个,docker.io...真实地址
docker pull mysql:5.7 #指定版本 需要在dockerhub上存在
docker rmi -f 镜像id #删除镜像
docker rmi -f $(docker images -qa) #递归删除小括号中的所有镜像
8.3.容器命令
有了镜像才能创建容器
docker pull centos
新建容器并启动
docker run [可选参数] image
#参数说明
--name="Name" 容器名字
-d 后台方式运行
-it 使用命令行方式运行
-p 指定容器端口
-p 主机端口:容器端口*
-p 容器端口
容器端口
-P 随机指定端口
docker run -it centos /bin/bash #启动并进入容器
exit #停止并退出容器
ctrl + p + q #容器不停止退出
docker ps#列出所有正在运行的容器
-a #列出所有运行过的容器
-n=? #显示n个运行过的容器
-q #只显示容器编号
docker rm 容器id #删除容器 不能删除正在运行的容器
docker rm -f $(docker ps -ap) #删除所有容器 能删除正在运行的容器
docker ps -a -q|xargs docker rm #删除所有容器
docker start 容器id #启动一个容器
docker restart 容器id #重启一个容器
docker stop 容器id #停止容器
docker kill 容器id #强制停止容器
8.4.其他命令
docker run -d 镜像 #启动镜像
#上面这个命令执行之后发现centos停止了 容器使用后台运行就必须要有一个前台进程,docker发现没有应用,就会自动停止
docker logs 容器id #查看日志
#后台运行并执行命令
docker run -d centos /bin/sh -c "while true;do echo hty;sleep 1;done"
#查看容器进程
docker top 容器id
#查看容器内部信息
docker inspect 容器id
#进入当前正在运行的容器
docker exec -it 容器id /bin/bash #进入容器后开启一个新的终端
docker attach 容器id #进入容器正在执行的终端 不会启动新的进程
#从容器中拷贝内容到宿主机
docker cp 容器id:容器内路径 目的主机路径
8.5.安装nginx
docker pull nginx #安装
docker run -d --name nginx01 -p 3344:80 nginx # 启动
curl localhost:3344 #测试
docker exec -it 容器id # 进入容器
8.6.安装tomcat
docker pull tomcat:9.0 # 下载
docker run --name=tomcat01 -it -p 8080:8080 tomcat # 启动tomcat
# 启动后发现webapps文件夹下没有任何内容
8.7.安装es+kibana
# 下载启动es
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.17.6
# 启动es之后会非常的卡 es会十分消耗内存
docker stats #查看cpu状态
#增加内存限制
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.17.6
8.8.可视化portainer
可视化分为
-
portainer
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
-
Rancher
安装portainer完成之后在外网的8088端口进行测试
9.镜像
获取镜像的方式
- 从远程仓库下载
- 朋友拷贝
- 自己制作
UnionFS(联合文件系统)
联合文件系统(Union File System):2004年由纽约州立大学石溪分校开发,它可以把多个目录(也叫分支)内容联合挂载到同一个目录下,而目录的物理位置是分开的。UnionFS允许只读和可读写目录并存,就是说可同时删除和增加内容。UnionFS应用的地方很多,比如在多个磁盘分区上合并不同文件系统的主目录,或把几张CD光盘合并成一个统一的光盘目录(归档)。另外,具有写时复制(copy-on-write)功能UnionFS可以把只读和可读写文件系统合并在一起,虚拟上允许只读文件系统的修改可以保存到可写文件系统当中。
docker镜像加载原理
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS(联合文件系统)。
分为两个部分:
bootfs(boot file system):主要包含bootloader和kernel(Linux内核),bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,而在Docker镜像的最底层也是bootfs这一层,这与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后,整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
即:系统启动时需要的引导加载,这个过程会需要一定时间。就是黑屏到开机之间的这么一个过程。电脑、虚拟机、Docker容器启动都需要的过程。在说回镜像,所以这一部分,无论是什么镜像都是公用的。
rootfs(root file system):rootfs在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
即:镜像启动之后的一个小的底层系统,这就是我们之前所说的,容器就是一个小的虚拟机环境,比如Ubuntu,Centos等,这个小的虚拟机环境就相当于rootfs。
10.commit镜像
docker commit # 提交容器称为一个新的副本
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
#启动一个默认的tomcat 发现这个默认的tomcat是没有webapps应用,现在将webapps.dist中的内容拷贝到webapps中
docker commit -a="hty" -m="add webapps app" 55795432d03e tomcat02:1.0
11.容器数据卷
docker将应用和环境打包成一个镜像,如果数据都在容器中,那么我们删除容器,数据就会丢失,我们现在需要将容器持久化,容器之间可以有一个数据共享的技术,Docker容器中产生的数据同步到本地,这就是卷技术->目录的挂在,将容器内的目录挂载在linux中
11.1.使用数据卷
docker run -it -v 主机目录地址/容器内目录
#案例 将centos中的home目录同步到主机的home的ceshi文件夹中
docker run -it -v /home/ceshi:/home centos /bin/bash
就算docker容器关闭了,也会继续同步的
有了这个技术,我们就可以在不进入容器的情况下,对我们的配置文件进行修改
11.2.部署Mysql+同步数据
# 安装mysql
docker pull mysql:5.7
# 持久化数据 启动mysql需要配置密码
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# -e就是设置环境 MYSQL_ROOT_PASSWORD参数表示的就是root的密码
#使用docker ps查看容器
# 现在如果删除镜像 本机同步的data文件夹仍然不会被删除
11.3.具名挂载和匿名挂载
#匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
#查看所有的卷的情况
docker volume ls
#具名挂载 -v 卷名:容器内路径
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
#使用docker volume ls命令查看卷就会发现此时带有了自己的命名
所有docker容器内的卷,没有指定目录的情况下,都是在/var/lib/docker/volumes/xxxx/_data
拓展
# 通过-v容器内路径:ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 可读可写
docker run .... -v xxx:/xxx/xxx:ro xxx
docker run .... -v xxx:/xxx/xxx:rw xxx
# 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作
11.4.Dockerfile
dockerfile就是构建docker镜像的构建文件,其实就是一段命令脚本,通过这段脚本就可以生成镜像
FORM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash
docker build -f ./dockerfile1 -t hty/centos . #生成
#使用docker images就可以看到制作好的镜像了
#启动自己制作的镜像
docker run -it 镜像id /bin/bash
11.5.同步数据卷
首先启动三个容器
docker run -it --name docker01 hty/centos # 第一个容器
docker run -it --name docker02 --volumes-from docker01 hty/centos #第二个容器双向绑定的是第一个容器
docker run -it --name docker03 --volumes-from docker01 hty/centos #第三个容器双向绑定的也是第一个容器
容器之间配置信息传递,数据卷容器的生命周期一直持续到没有容器使用位置,但是一旦持久化到了本地,这个时候,本地的数据是不会删除的
12.DockerFile
dockerfile是用来构建docker镜像的文件,命令参数脚本
构建步骤:
- 编写一个dockerfile文件
- docker build构建称为一个镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub、阿里云镜像仓库)
12.1.基础知识
- 每个指令都必须是大写
- 指令是从上到下顺序执行
#
表示注释- 每一个指令都会创建提交一个新的镜像层,并提交
dockerfile是面向开发的,以后做项目就要做镜像,就需要编写dockerfile文件,这个文件十分简单
12.2.指令
FROM 镜像 #基础镜像 一切从这里开始构建
MAINTAINER #镜像是谁写的 姓名+邮箱
RUN #镜像构建的时候需要运行的命令
ADD #步骤:包含tomcat镜像,需要tomcat的压缩包
WORKDIR #镜像的工作目录
VOLUME #挂载的目录
EXPOSE #暴露端口
CMD #指定这个容器启动的时候要运行的命令 只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器启动的时候要运行的命令 可以追加命令
ONBUILD #当构建一个被继承DockerFile这个时候就会运行
COPY #类似ADD,将文件拷贝到镜像中
ENV #构建的时候设置环境变量
12.3.构建自己的DockerFile
DockerHub中99%镜像都是从scratch
镜像过来的
编写dockerfile文件
FROM centos:7
MAINTAINER hty<1156388927@qq.com>
ENV MYPATH /user/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "-----end-----"
CMD /bin/bash
构建镜像 注意最后的点不能省略
docker build -f mydockerfile-centos -t mycentos:0.1 .
使用一下命令个查看一个镜像的历史版本
docker history 容器id
12.4.CMD和ENTRYPOINT区别
CMD
#编写dockerfile
FROM centos:7
CMD ["ls","-a"]
#构建
docker build -f dockerfile-cmd-test -t cmdtest .
#运行
docker run 8a74f9ea7d67
#结果
.
..
.dockerenv
anaconda-post.log
bin
dev
etc
home
lib
# 另一个测试 追加一个命令 -l 展示列表详细信息
docker run 8a74f9ea7d67 -l
#报错
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
#CMD的情况下,替换了CMD的["ls","-a"]命令,所以报错
ENTRYPOINT
#可以直接在后面追加命令
docker run b94a89dd14d3 -l
结果
total 64
drwxr-xr-x 1 root root 4096 Aug 29 14:20 .
drwxr-xr-x 1 root root 4096 Aug 29 14:20 ..
-rwxr-xr-x 1 root root 0 Aug 29 14:20 .dockerenv
-rw-r--r-- 1 root root 12114 Nov 13 2020 anaconda-post.log
lrwxrwxrwx 1 root root 7 Nov 13 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 Aug 29 14:20 devdrwxr-xr-x 1 root root 4096 Aug 29 14:20 etc
drwxr-xr-x 2 root root 4096 Apr 11 2018 home
lrwxrwxrwx 1 root root 7 Nov 13 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 13 2020 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Apr 11 2018 media
drwxr-xr-x 2 root root 4096 Apr 11 2018 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2018 opt
dr-xr-xr-x 162 root root 0 Aug 29 14:20 proc
dr-xr-x--- 2 root root 4096 Nov 13 2020 root
drwxr-xr-x 11 root root 4096 Nov 13 2020 run
lrwxrwxrwx 1 root root 8 Nov 13 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Apr 11 2018 srv
dr-xr-xr-x 13 root root 0 Aug 29 09:31 sys
drwxrwxrwt 7 root root 4096 Nov 13 2020 tmp
drwxr-xr-x 13 root root 4096 Nov 13 2020 usr
drwxr-xr-x 18 root root 4096 Nov 13 2020 var
12.5.制作tomcat镜像
- 准备镜像文件,tomcat压缩包,jdk压缩包
- 编写dockerfile,官方命名
Dockerfile
,build会自动寻找这个文件,就不需要-f指定了
FROM centos:7
MAINTAINER hty<1156388927@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u181-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.73.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.73
ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.73
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-8.5.73/bin/startup.sh && tail -F /url/local/apache-tomcat-8.5.73/bin/logs/catalina.out
- 构建
docker build -t diytomcat .
- 启动自制tomcat
docker run -d -p 8080:8080 -v /home/hty/build/tomcat/test:/usr/local/apache-tomcat-8.5.73/webapps/test -v /home/hty/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-8.5.73/logs diytomcat
- 我们做了卷挂载,直接在本机发布项目,就会自动同步到docker中
12.6.发布到dockerhub上
首先需要注册账号
#登陆dockerhub
docker login -u 用户名 -p 密码
# push
docker push 作者/镜像:版本
12.7.发布到阿里云
登陆阿里云,找到容器镜像服务,创建命名空间,创建容器镜像
13.Docker网络
使用ip addr
查看网卡,发现有一个docker0网卡
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:6c:0d:d0:ff brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:6cff:fe0d:d0ff/64 scope link
valid_lft forever preferred_lft forever
我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker ,就会有一个网卡,docker0桥接模式,使用的结束时evth-pair技术
启动了一个容器之后就会多出来一个网卡
我们发现容器带来的网卡是成对出现的,evth-pair就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连,正因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备的
结论:容器和容器之间是可以互相ping
所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们容器分配一个默认的可用的IP,255.255.0.1/16
Docker中所有的网络接口都是虚拟的,虚拟的转发效率高(内网传递文件)
14.容器互联-link
我们新建两个容器,两个容器之间相互ping
我们发现是ping
不通的
解决方法:在启动容器的时候进行链接
docker run -d -P --name tomcat03 --link tomcat02 tomcat
测试tomcat03
就可以ping
通tomcat02
的网络了
原理就是tomcat03在本地配置了tomcat02的映射,在/etc/hosts
文件中
docker0的问题:不支持容器名连接访问
15.自定义网络(容器互联)
网络模式:
- bridge:桥接
- none:不配置网络
- host:和宿主机共享网络
- container:容器内网络连通(用过的少)
测试
# 我们直接启动的命令 --net bridge 而这个就是我们的docker0
docker run -d -P --name tomcat01 --net bridge tomcat
# docker0特点:域名不能访问,--link可以打通连接
#自定义网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
#我们再次ping之后发现不使用--link也可以ping通并且可以使用名称来ping
我们自定义的网络docker都已经帮我们维护好了对应关系,推荐我们平时这样使用网络