为什么使用docker
因为深刻理解到一句话:“这个程序可以在我的电脑运行”,但是就是在其他电脑上运行不上,
Docker为什么会出现
在产品开发过程中,环境的配置是十分麻烦的,比如一个项目(redis,MySQL),在不同的人手上,就要重新配置一遍环境,然后就想打包项目能不能带上环境安装打包
个人感觉docker过程就像一个安卓应用从开发到可以在手机上运行的过程:
在编写安卓应用的时候是用Java或者其他种类的语言来编写,容然后打包成为一个以**.apk结尾的包,发布到应用商店,然后需要使用的人从应用商店下载这个以.apk结尾的安装包,安装就可以使用(Java代码在手机上是不可以运行的,但是通过一系列的打包成为在android环境中可以运行的apk**安装包)
流程:Java – apk – (应用商店)-- 个人下载使用apk – 下载安装就可以使用
所以docker的流程就像这样:
(编写的项目代码 – (env)需要的环境 )-- 打包项目带上环境 (镜像(image))-- push到docker商店 (docker hub) – 下载我们发布的镜像 – 直接运行(容器 container)
就像docker的图标一样,采用隔离的机制,避免了在虚拟机中的端口冲突问题(在docker中可以可以使端口的映射来解决端口的问题)
Docker的历史
2010年,美国的几个it年轻人,成立了一家公司dotcloud,是关于一些虚拟机有关的容器技术,
他们将自己的容器化技术命名为docker,刚开始的时候docker并不出名,2013年通过开源,越来越多的人知道了docker的优点
2014年,docker 1.0 发布,因为十分的轻巧,所以非常火
在容器化技术出现之前,都是使用的虚拟化技术,
在windows中,安装一个vmware,可以虚拟出一个电脑或者多台电脑,但是笨重
vm:linux centos 原生镜像,隔离 需要多个虚拟机 一个虚拟机至少需要几个G,启动时间在分钟级
docker: 隔离,镜像(最核心的环境可能只需要几M的内存,秒级启动)
docker 网址:www.docker.com
在首页的最下面有关于docker的文档 :https://docs.docker.com
docker 仓库:https://hub.docker.com
docker能做什么
比较docker和虚拟机的不同
- 就像在上图中,关于虚拟机的原理,是在内核的基础上虚拟出我们需要的环境。我们需要分配内存,需要配置cpu,在上图中,有多个APP,但是他们的所需要的环境是不一样的,所以在配置环境的时候,将所有的环境配置在共同的lib中,造成了资源的浪费和冗余,以及端口之间的冲突。
- 但是在docker中,docker 相对于虚拟机来说,不是在宿主机上虚拟出一套硬件后在虚拟出一个操作系统,而是在宿主机上直接运行docker容器中的进程,形成相应的容器,在容器之中运行自己的APP,每个容器之间相互隔离,都有一个属于自己的文件系统,互不影响,相对来说,docker的体积会更轻.
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-71tO27vE-1630911834337)(D:\Desktop\work\Docker.assets\image-20210803175247502.png)]
- docker中的镜像是分层的,比如上图中的Ubuntu刚开始是72.7 mb,但是自己可以在这个基础的版本上加入自己想要加入的东西,比如MySQL。
关于docker
image(镜像):
就好像是一个模板,通过这个模板来创建容器,一个镜像可以创建多个容器,(最终的项目代码运行就是在容器中的)
container(容器)
通过镜像来创建,可以看做一合简易的Linux系统,基本操作:启动,停止,删除
(repository)仓库
存放镜像的地方,默认是国外的docker hub
Docker安装
docker网站里面有详细的步骤,推荐使用阿里云的镜像加速。
使用docker version 查看是否安装成功
使用 docker run hello-world 测试
卸载docker
卸载依赖
yum remove docker-ce-cli containerd.io
卸载资源
rm -rf /var/lib/docker docker的默认工作路径
了解一下镜像run hello-world流程
在敲下run命名后,
底层原理
docker是怎么工作的?
docker是一个cs结构的系统,docker的守护进程运行在主机上,通过socket从客户端访问
DockerServer 接收到Docker-client的指令,就会执行这个命令
相比较虚拟机来说,docker的容器少了一个Hypervisor ,少了一个抽象层,所以,新建一个容器的时候,不需要像虚拟机一样重新加载一个操作系统内核,就避免了引导过程(就像以前的老电脑开机时候一行一行的显示状态码一样,这是个很长的过程),docker是利用宿主机的操作系统,
容器内部机制
容器内部的原理就大概像命名空间一样,在Linux操作系统中,有这么一个和命名空间类似的功能,将全局资源共享到进程中,如果将这些资源包装在命名空间中,使得一些资源只对同一命名空间的进程可见。
就比如,我有一块磁盘,放在命名空间为PTD的命名空间中,那么在其他比如PSD的命名空间的进程就不可以查看或者访问我在命名空间为PTD中的磁盘。当然,PTD中的进程也不可以访问PSD 中的资源。为全局资源提供了一种虚拟化和隔离。
Docker,就是这样,每个容器在自己的‘命名空间’中运行,但是和其他容器一起使用操作系统的内核,隔离是因为内核知道根据命名空间分配相应的进程。
Docker的常用命令
帮助命令
docker version 版本信息
docker info 显示docker的系统信息,包括镜像和容器的数量
docker 命令-- help 命令的帮助命令
在 https://docs.docker.com 下面的 reference 有docker的全部命令
镜像命令
docker images 查看本地的所有的镜像,有仓库名,版本信息,镜像ID,创建时间,镜像大小五个属性
docker search 搜索镜像
docker pull 下载镜像
docker rmi 删除镜像
docker rmi -f $(docker images -ap) 删除全部的镜像
容器命令
新建一个容器并启动
docker run [option] image
option 说明
--name='Name' 容器名字 MySQL01 mysql02 用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080 -p 主机端口:容器端口
-P 随机指定端口
docker ps 显示运行的容器
退出容器
exit 直接容器停止并退出
Ctrl + p + q 不停止退出
删除容器
docker rm 容器ID,不能删除正在运行的容器,如果强制删除,rm -f
docker rm -f $(docker ps -aq) 全部删除
启动和停止容器
docker start 容器ID 启动容器
docker restart 容器ID 重启容器
docker stop 容器ID 停止容器
docker kill 容器ID 强制停止容器
常用其他命令
后台启动容器
docker run -d 镜像名
问题:使用docker ps 查看时候,发现容器停止了 ,因为docker使用后台运行,但是必须有一个前台进程,docker发现没有应用,就会自动停止,
查看日志命令
docker logs
查看容器中的进程信息
docker top [容器ID]
查看镜像的元数据
docker inspect [容器ID]
进入当前正在运行的容器
docker exec -it 容器ID 进入容器后开启一个新的终端
docker attach 容器ID 进入容器正在执行的终端,不会启动新的终端
拷贝文件到主机上
docker cp
docker cp 容器名:/容器内文件地址 /主机地址
el: 将容器内部的test.java拷贝到主机上,将容器内部的home目录下的test.java拷贝到主机上的home目录下
首先在进入容器内部创建或者找到拷贝的文件,
docker attach 容器名 进入容器
touch file(test.java)
docker cp 容器ID : / home/test.java /home
拷贝是一个手动过程,以后使用 -v volume卷的技术实现拷贝过程
小结
一些例子
安装使用nginx和tomcat
平时使用nginx和tomcat时候的一些部署问题
首先使用docker search 搜索相应的镜像,或者可以在docker的官网里面找到需要的版本,后根据需要下载
然后使用docker run -d --name nginx03 -p 3344:80 nginx 创建相应的容器之后,暴露主机的3344端口给容器的80 端口
最后使用docker exec -it nginx03 /bin/bash 进入创建的容器,比如在tomcat里面的WebApps里面是没有任何东西的,需要使用webapps.dist里面的ROOT里面的文件来实现相应的界面效果,
使用curl localhost:端口号 或者在浏览器里面输入主机 ip:端口号 测试访问
docker镜像
镜像
images是一种轻量级可执行的独立软件包,打包运行环境和基于运行环境开发的软件,包含某个软件所需要的所有的内容,包括代码,库,环境变量和配置文件。
联合文件系统
是一种分层,轻量级并且高性能的文件系统,支持对文件系统的修改作为一次提交来一层层的叠加,将不同的目录挂载到同一个虚拟文件系统下,镜像可以通过分层来继承,但是没有父镜像一说,更多说的是基础镜像,可以根据一个基础的镜像来制作具体应用的镜像
理解:
所有的镜像都起源于一个基础的镜像,当进行修改或者增加新的镜像时候,就会在当前镜像之上,增加新的镜像层
比如说,基于Linux创建一个新的镜像,这是第一层,然后添加Python包,这就是第二层,就是这样一层一层的增加,在不断的增加新的镜像层时候,最后的镜像始终是当前所有镜像的组合
多个Container可以共享基础Image存储,节省存储空间;快速部署 – 如果要部署多个Container,Base Image可以避免多次拷贝,实现快速部署。因为多个Container共享Image,提高多个Container中的进程命中缓存内容的几率。
容器数据卷
数据,在创建一个容器过程中,如果容器被删除,数据就会丢失。那么实现数据持久化就是一个问题。
方式1:直接使用命令挂载
docker run -it -v 主机目录:容器目录
使用docker inspect 容器id
例子:
使用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
在这一行中
-d 表示后台运行容器
-v 进行容器和宿主机之间的挂载
-p 实现端口的暴露
–name 如果要根据一个镜像启动多个容器,那么可以使用–name 对不同的容器之间进行区分
具名和匿名挂载
三种挂载方式:
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /主机路径:容器内部路径 #指定路径挂载
相应的,在挂载路径后面加上ro或者rw ,表示onlyread和readwrite,只读和可读可写
DockerFile
是用来构建docker镜像的文件,命令参数脚本。
构建步骤:
1、编写一个dockerfile文件
2、docker build构建一个镜像
3、docker run 运行镜像
4、docker push 发布镜像(dockershub 阿里云镜像仓库)
官方的镜像中,很多都是基础版本,所以我们需要自己制作自己的镜像
dockerfile构建过程
基础知识 :
每个关键字都是大写的字母
执行顺从上倒下
井号表示注释
每个指令都会创建提交一个新的镜像层,每一行命令都是一层
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bAxRZzHc-1630911834348)(C:\Users\Hello\AppData\Roaming\Typora\typora-user-images\image-20210707140407788.png)]
dockerfile是面向开发的,发布项目,做镜像,就需要dockerfile文件,
docker镜像成为交付的标准。必须要掌握。
dockerfile:构建文件,定义了一切的步骤,源代码
dockerimage:通过dockerfile构建生成的镜像,最终发布和运行的产品
docker容器:容器就是镜像运行起来提供服务
dockerfile的指令
通过使用这些指令,来写自己 的镜像
例子:创建一个自己的nginx
FROM NGINX
MAINTAINER Rain<daigang344@163.com>
ENV MYPATH /usr/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 dockerfile文件路径 -t 镜像名:[tag]
使用docker history 查看更改历史
提交自己的镜像
使用方法和git一样
1、在hub docker https://hub.docker.com/上面注册自己的账号 在本地使用docker login -u 登录 会要求输入自己的密码
2、使用docker push 镜像名 发送到自己的仓库
提交到阿里云镜像仓库
1、登录阿里云, 创建相应的仓库和命名空间
2、相应的步骤阿里云上有
在上图中,使用dockerfile制作一个镜像,命令是docker build 镜像名
使用docker run 启动一个容器使用docker push 发送到远端仓库,使用start stop restart 启动 停止 重启 容器
使用 docker pull 从远端仓库拉取相应的镜像,使用 docker save -o 压缩镜像,使用 docker load 解压缩镜像,tag是镜像的标签,在发布镜像时候会给镜像加上相应的版本,
使用docker commit 提交新的镜像(假设我们在docker中运行了一个Tomcat容器,我们在tomcat容器中做了一些我们自定义的修改,然后我们这个修改的tomcat容器进行commit,这样我们就形成了一个新的自定义镜像 )命令是docker commit -m=“提交的描述信息” -a=“作者” 容器id 要创建的目标镜像名:[标签名]
关于docker的操作上满这幅图中做了详细的解释
docker 网络
在Linux中,每启动一个docker 容器,都会分配一个IP地址,所有的容器在不指定网络的情况下,都是docker 0路由的,
docker 使用的是Linux的桥接技术,宿主机中是一个docker的容器网桥
容器中的网卡都是成对出现的,evth-pair 就是一对虚拟的设备接口,一端连着协议,一端连着彼此,利用这个特性,连接各种虚拟设备,
port # 查看映射端口对应的容器内部源端口
pause # 暂停容器
ps # 猎户容器列表
pull # 从docker镜像源服务器拉取指定镜像或者库镜像
push # 推送指定镜像或者库镜像至docker源服务器
restart # 重启运行的容器
rm # 移除一个或多个容器
rmi # 移除一个或多个镜像 (无容器使用该镜像才可删除,否则需要删除相关容器才可继续或 -f 强制删除)
run # 创建一个新的容器并运行一个命令
save # 保存一个镜像为一个 tar 包【对应 load】
search # 在 docker hub 中搜索镜像
start # 启动容器
stop # 停止容器
tag # 给源中镜像打标签
top # 查看容器中运行的进程信息
unpause # 取消暂停容器
version # 查看 docker版本号
wait # 截取容器停止时的退出状态值
一些基本的命令。
docker images 查看本地镜像
docker run -d --name 容器名(可以是多个) -p 宿主机端口:容器端口 容器名
sh # 推送指定镜像或者库镜像至docker源服务器
restart # 重启运行的容器
rm # 移除一个或多个容器
rmi # 移除一个或多个镜像 (无容器使用该镜像才可删除,否则需要删除相关容器才可继续或 -f 强制删除)
run # 创建一个新的容器并运行一个命令
save # 保存一个镜像为一个 tar 包【对应 load】
search # 在 docker hub 中搜索镜像
start # 启动容器
stop # 停止容器
tag # 给源中镜像打标签
top # 查看容器中运行的进程信息
unpause # 取消暂停容器
version # 查看 docker版本号
wait # 截取容器停止时的退出状态值
一些基本的命令。
docker images 查看本地镜像
docker run -d --name 容器名(可以是多个) -p 宿主机端口:容器端口 容器名
上一句命令主要是用在部署服务器上面,在一个容器中运行多个服务