一、了解Docker
1.1 什么是Docker?
Docker 是一个开源的应用容器引擎,(类似于虚拟机技术,但不是虚拟机,它 实现了虚拟机中的资源隔离,它的性能远远高于虚拟机),基于 Go 语言并 遵从Apache2.0协议开源。让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
沙箱和沙箱机制 沙箱是一个虚拟系统程序,沙箱提供的环境相当于每一个运行的程序都是独立的,而且不会对现有的系统产生影响。
1.2 为什么会出现Docker?
当我们开发一款应用时,都具有开发和上线的两种环境。我们经常遇到的一个问题就是:在我的电脑上可以运行,而换了一个环境就不能运行了。其实很多时候应用的版本更新都有可能造成服务不可用。这样一来对运维人员来说就增加了很大的压力。
一款应用,在开发完成后进行的环境配置也是很复杂的。我们需要在每一个机器上都部署环境,例如(Redis集群、MySQL集群……)费时费力。而且之前在一个服务器配置了一个应用的环境,不支持跨平台,也就是说我们在Windows上开发的应用,到最后需要部署到Linux上,就会导致服务不可用。那么我们在考虑发布一个项目的时候能不能连同所有的环境配置(MySQL、JDK、Redis……)一起打包上线呢?
Docker的出现就帮我们解决了这一系列的问题:原来传统的开发,开发人员将程序打包成 jar 包,给运维人员。现在我们可以使用Docker独立完成开发打包部署上线,一套流程全部搞定~~我们可以将环境和产品打包成一个镜像来进行发布。如果以后需要使用这个产品,我们就可以直接下载这个镜像直接启动,完全不用考虑环境带来的困扰
1.3 Docker的基本组成
镜像(Images):
Docker镜像就好比是一个模板,可以通过这个模板来创建容器服务。 例如:
tomcat镜像 -> run -> tomcat容器
通过这个镜像可以创建多个 容器,最终服务运行或项目运行就是在容器中完成的。
容器(Container):
Docker通过容器技术,独立运行一个或一组应用,通过镜像来创建。容器可以进行启动、停止、删除等基本命令。目前可以把这个容器理解为一个简易的Linux系统。
仓库(Repository):
仓库(Docker Hub)是存放所有镜像的地方,仓库相当于GitHub,分为公有仓库和私有仓库。仓库(Docker Hub)默认是国外的,我们需要配置阿里云镜像进行访问。
1.4 安装Docker
首先,我们使用 XShell 连接Linux服务器,按照如下步骤进行操作即可:
卸载旧版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
安装yum相关工具
yum install -y yum-utils
配置 docker 仓库,这里官方默认使用的是国外的仓库,我们改成阿里云的仓库即可 ```shell
官方默认
yum-config-manager \ —add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
使用阿里云镜像
yum-config-manager \ —add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4. 安装 docker 引擎
```shell
yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
安装完成后,启动 docker
systemctl start docker
查看 docker 版本
docker version
运行 hello-world
docker run hello-world
此时运行该命令后会提示如下信息:
表示找不到镜像,现在他会自己去官方拉取最新的镜像,拉取完成后如果输出了Hello form Docker!
那就说明安装成功了!查看一下下载的
hello-world
镜像[root@MiWiFi-R3G-srv /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 7 months ago 13.3kB
二、Docker基础
2.1 Docker的底层原理
2.1.1 docker的运行流程
2.1.2 docker是怎么工作的?
Docker 是一个 Client - Server 结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问,DockerServer 接收到 Docker-Client 的指令,就会运行这个命令
2.1.3 Docker为什么比VM快?
Docker有着比VM更少的抽象层。
- Docker利用的是宿主机的内核,而VM需要的是Guest OS
所以说,新建一个容器的时候,Docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导,虚拟机是加载Guest OS,分钟级别的;而 Docker 是利用了宿主机的操作系统,省略了这个复杂的过程,实现秒级加载。
2.2 Docker的常用命令
docker参考文档:https://docs.docker.com/reference/
2.2.1 帮助命令
docker version # 查看docker的版本信息
docker info # 查看docker的详细信息,包括镜像和容器数量
docker [命令] --help # 查看docker的所有命令,也可以查看docker的具体某个命令的使用
2.2.2 镜像命令
**docker images**
查看所有本地主机上的镜像 ```shell [root@MiWiFi-R3G-srv /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 7 months ago 13.3kB
字段解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATE 镜像的创建时间
SIZE 镜像的大小
可选参数(常用)
-a , -all # 列出所有镜像 -q , -quiet # 只显示镜像的id —help # 查看命令的详细信息,以及所有可选参数
2. `**docker search**`** 搜索镜像**
下面以搜索 mysql 镜像为例,会列举出所有 mysql 相关的镜像(图片未显示所有..)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/12647137/1651112404085-de53dc55-b4ee-4618-bff1-b8a004279b3c.png#clientId=u90c22813-a149-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=208&id=u00212de4&margin=%5Bobject%20Object%5D&name=image.png&originHeight=208&originWidth=1573&originalType=binary&ratio=1&rotation=0&showTitle=false&size=31576&status=done&style=stroke&taskId=u02665702-4131-4a23-a958-f42660c8380&title=&width=1573)<br />可选参数:
```shell
--filter 按条件过滤搜索结果
# 例如过滤STARS为3000以上的镜像
docker search mysql --filter=STARS=3000
**docker pull 镜像名**
拉取镜像
下面以下载 mysql 镜像为例,默认会下载最新版本的镜像
可选参数:
:tag 指定tag下载,可以指定下载的版本(指定的版本需要在官网存在)
# 例如下载mysql5.7版本的镜像
docker pull mysql:5.7
注意: 采用分层下载的方式,如果已存在的模块不会重复下载,可以实现文件复用,极大的节省了内存。这是Linux的联合文件系统。
**docker rmi**
删除镜像
可选参数:
-f , --force # 强制删除镜像
# 删除镜像的时候可以根据镜像的id镜像删除,在命令后面直接跟上id即可,例如:
docker rmi -f 8aa4b5ffb001
可见,删除的时候也是只删除了自己的模块,不会删除之前的所有模块,不影响其他镜像。
删除的时候也可以通过$(...)
携带参数,例如删除所有镜像:
docker rmi -f $(docker images -aq) # 表示将查询到的所有镜像挨个删除
2.2.3 容器命令
启动容器
# 启动容器
docker run [可选参数] 镜像名
可选参数
--name="Name" # 容器名字(用来区分容器)
-d # 后台方式运行
-it # 使用交互方式运行,进入容器查看内容
-p # (小写)指定容器端口
-p ip:主机端口:容器端口
-p 主机端口:容器端口 (常用)
-p 容器端口
-P # (大写)随机指定端口
启动并进入容器,退出容器
# 启动并进入容器
docker run -it centos /bin/bash
# 停止并退出容器
exit
# 退出容器但不停止
ctrl + p + q
查看正在运行的容器
docker ps # 查看正在运行的容器
docker ps -a # 查看历史运行过的容器
删除容器
docker rm 容器id # 删除指定id的容器,不能删除正在运行的容器,可以加上-f表示强制删除
docker rm -f $(docker ps -aq) # 强制删除所有容器
docker ps -a -q|xargs docker rm # 删除所有容器
启动和停止容器
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前正在运行的容器
docker pause 容器id # 暂停容器
docker unpause 容器id # 取消暂停容器
2.2.4 其他命令
**docker run -d 镜像名**
后台启动容器
注意事项:docker容器使用后台运行就必须要有一个前台进程,docker 发现没有应用就会自动停止。
- 查看日志 ```shell docker logs 容器id
可选参数
-tf # 显示日志 —tail number # 显示的条数
3. **查看容器中的进程信息**
```shell
docker ps # 查看正在运行的容器
docker top 容器id # 查看容器的进程信息
查看镜像的元数据
docker inspect 容器id # 会显示出容器的所有详细信息以及配置信息等
进入当前正在运行的容器 ```shell
我们的容器通常都是在后台运行的,有时我们需要进入容器修改一些配置。
命令
docker exec -it 容器id 路径
方式二
docker attach 容器id
区别
docker exec 进入容器后开启一个新的终端,可以直接在里面操作
docker attach 进入正在执行的终端,不会启动新的进程
6. **将容器内的文件拷贝到主机上**
```shell
# 命令
docker cp 容器id:容器内地址 主机上的目标地址
2.2.5 常用命令小结
2.3 部署Nginx
# 首先通过docker search搜索nginx
docker search nginx
# 拉取nginx的镜像
docker pull nginx
# 查看镜像
docker images
# 后台启动nginx,并向外暴露一个端口8899
docker run -d --name nginx01 -p 8899:80 nginx
# 外部测试访问
curl 192.168.31.103:8899
测试成功后,我们也可以进入容器修改nginx的配置文件nginx.conf
补充:暴露端口的概念 如果我们要从外网访问一个Docker容器中的服务,需要经过端口暴露才能访问到,否则会被防火墙拦截从而访问失败。如果我们的服务器是购买的阿里云服务器,那么在外面会再多一层阿里云安全组的保护
2.4 部署Tomcat
# 首先搜索并下载镜像 这里下载9.0版本的
docker search tomcat
docker pull tomcat:9.0
# 查看下载的镜像
docker images
# 以后台方式运行容器,并向外暴露一个端口
docker run -d --name tomcat01 -p 8888:8080 tomcat:9.0
容器启动后,我们可以尝试在浏览器访问
192.168.31.130:8888
。此时会提示404,说明此时tomcat容器已经成功启动,只是我们的webapps下还没有资源所以什么都找不到
我们尝试进入容器一探究竟
# 进入容器
docker exec -it tomcat01 /bin/bash
# 进入webapps目录
cd webapps
此时发现什么内容都没有,为什么呢?
我们发现在容器中Linux命令少了很多不能使用,webapps中没有内容…… 这其实是阿里云镜像的原因:默认是最小的镜像,所以他将不必要的都剔除掉了,保证最小可运行环境
现在我们进入webapp.dist
目录,发现我们的ROOT
等文件夹在存放在这,现在我们只需要将webapps.dist 目录中的内容拷贝到 webapps 中再刷新浏览器即可访问到tomcat主页了
# 拷贝
cp -r ./webapps.dist/* ./webapps
2.5 提交镜像
我们可以将操作后的镜像提交为一个新的镜像,例如tomcat,默认在webapps目录下是没有资源的,那我们将webapps.dist目录中的文件拷贝到webapps目录中之后,我们启动tomcat后就可以看到内容了,我们可以将这个操作提交为一个新的镜像,我们以后启动这个镜像就是我们这个效果了。
# 启动tomcat
docker run -it -p 8888:8080 tomcat:9.0
# 将webapps.dist目录中的内容拷贝到webapps中
cp -r ./webapps.dist/* ./webapps
# 提交镜像
docker commit -m="提交的信息" -a="作者" 镜像id 镜像名:标签(版本)
# 停止当前容器
exit
docker stop 容器id
# 启动我们自己提交的镜像
docker run -d -p 8080:8080 镜像名:标签
三、Docker进阶
3.1 容器数据卷
我们先来了解一下,什么是容器数据卷?
容器数据卷: docker 的理念将运行的环境打包形成容器运行,运行可以伴随容器,但是我们对数据的要求是希望持久化,容器之间可以共享数据,Docker 容器产生的数据,如果不通过docker commit生成新的镜像,使得数据作为容器的一部分保存下来,那么当容器被删除之后,数据也就没了,为了能够保存数据,在docker容器中使用卷
例如:我们在docker中安装了mysql,那么我们在mysql内存储的数据都是在这个镜像中的,如果我们将镜像删除了,那么数据也就没了。删库跑路咯~~ 容器之间有一个数据共享的技术,docker容器中产生的数据,同步到本地,这就是卷技术。
注意:容器的持久化和数据同步,容器之间也是可以数据同步的。
# 命令 直接通过 -v 命令来挂载
docker run -it -v 主机目录:容器内目录
# 测试 我们测试将centos镜像中的 /home 目录与主机上的 /home/test 目录进行映射
docker run -it -v /home/test:/home centos /bin/bash
现在,我们已经将两个目录进行了映射,主机上的该目录和容器内的该目录中的文件都会进行数据同步,我们在目录中新建,删除或修改文件,都会进行自动同步。
3.2 MySQL数据同步
在docker中下载的MySQL镜像,需要进数据和配置文件进行数据同步,这就要使用到数据卷技术。
# 搜索并下载mysql,这里下载MySQL5.7版本
docker pull mysql:5.7
# 以后台方式启动并设置密码,使用数据卷技术对配置和数据进行数据同步
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql --name mysql01 mysql:5.7
我们启动完成后可以使用第三方工具SQLyog连接建立连接
现在,我们成功连接到了docker镜像中的mysql,也可以正常使用,我们已经对数据和配置进行了同步,当docker容器被误删除的时候,我们也能保证数据的稳定。
3.3 具名和匿名挂载
在使用容器数据卷的时候,我们可以给挂载的容器起一个名字,这就是具名挂载,如果我们直接使用-v 容器内路径
这种方式,没有声明容器外路径,也没有起名字这就是匿名挂载。
挂载一般分为三种方式:具名挂载、匿名挂载、指定路径挂载
# 匿名挂载nginx
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看挂载情况
docker volume ls
DRIVER VOLUME NAME
local 0210e6d833f2fcc7eeb70147908e2de9d835aa87fe3d277b01172431ce657318
# 具名挂载nginx
docker run -d -P --name nginx02 -v named_mounted_nginx:/etc/nginx nginx
#现在再来查看一下挂载情况
docker volume ls
DRIVER VOLUME NAME
local 0210e6d833f2fcc7eeb70147908e2de9d835aa87fe3d277b01172431ce657318
local named_mounted_nginx
# 查看卷的挂载信息和具体路径
docker volume inspect named_mounted_nginx
# 可以看到如下信息
[
{
"CreatedAt": "2022-05-01T17:48:17+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/named_mounted_nginx/_data",
"Name": "named_mounted_nginx",
"Options": null,
"Scope": "local"
}
]
拓展
# 在挂载的时候,可以通过ro或rw指定权限
ro # readonly 只读
rw # readwrite 可读可写 默认
# 一旦设置了这个权限,容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx02 -v named_mounted_nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v named_mounted_nginx:/etc/nginx:rw nginx
# 只要设置了ro,那么容器内部就无法对其进行改变了,只能通过宿主机来改变
3.4 数据卷容器
我们可以通过数据卷容器实现容器之间的数据同步。例如,我们可以将一个容器挂载到另一个容器上,从而使得这两个容器之间数据同步,当然,我们还可以挂载更多的容器
# 命令
docker run -it --name docker02 --volume-from docker01 centos
# 上述命令就是代表将docker02这个容器挂载到了docker01上面,此时docker01是父容器。两个容器之间是数据同步的
# 我们也可以在这个docker01容器上面挂载更多的容器。例如:
docker run -it --name docker03 --volume-from docker01 centos
# 此时这三个容器之间的数据都是同步的
3.5 DockerFile
3.5.1 DockerFile介绍
DockerFIle 是用来构建 docker 镜像的构建文件,该文件都是一些脚本命令,我们可以使用 DockerFile 技术来构建一个镜像。
构建步骤:
- 编写一个 DockerFile 文件
docker build
构建为一个镜像docker run
运行镜像docker push
发布镜像,可以发布到 Docker Hub或阿里云镜像仓库3.5.2 DockerFile构建过程
基础知识:
每个保留关键字(指令)都必须是大写字母
- 执行顺序从上到下
#
表示注释- 每一个指令都会创建一个新的镜像层,并提交
Docker 是面向开发的,我们以后要发布项目,做镜像,就要编写 DockerFile 文件,这个文件十分简单,Docker 镜像逐渐成为企业交付的标准,我们以前是需要交付一个
jar
包或war
包,现在就需要进其构建为一个镜像。
DockerFile
:构建文件,制作镜像DockerImages
:通过DockerFile
构建生成的镜像,是最终运行和发布的产品Docker容器
:容器就是镜像运行起来提供服务的