一、了解Docker

1.1 什么是Docker?

Docker - 图1
Docker 是一个开源的应用容器引擎,(类似于虚拟机技术,但不是虚拟机,它 实现了虚拟机中的资源隔离,它的性能远远高于虚拟机),基于 Go 语言并 遵从Apache2.0协议开源。让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

沙箱和沙箱机制 沙箱是一个虚拟系统程序,沙箱提供的环境相当于每一个运行的程序都是独立的,而且不会对现有的系统产生影响。

文档地址:https://docs.docker.com/ 仓库地址:https://hub.docker.com/

1.2 为什么会出现Docker?

当我们开发一款应用时,都具有开发和上线的两种环境。我们经常遇到的一个问题就是:在我的电脑上可以运行,而换了一个环境就不能运行了。其实很多时候应用的版本更新都有可能造成服务不可用。这样一来对运维人员来说就增加了很大的压力。
一款应用,在开发完成后进行的环境配置也是很复杂的。我们需要在每一个机器上都部署环境,例如(Redis集群、MySQL集群……)费时费力。而且之前在一个服务器配置了一个应用的环境,不支持跨平台,也就是说我们在Windows上开发的应用,到最后需要部署到Linux上,就会导致服务不可用。那么我们在考虑发布一个项目的时候能不能连同所有的环境配置(MySQL、JDK、Redis……)一起打包上线呢?
Docker的出现就帮我们解决了这一系列的问题:原来传统的开发,开发人员将程序打包成 jar 包,给运维人员。现在我们可以使用Docker独立完成开发打包部署上线,一套流程全部搞定~~我们可以将环境和产品打包成一个镜像来进行发布。如果以后需要使用这个产品,我们就可以直接下载这个镜像直接启动,完全不用考虑环境带来的困扰

1.3 Docker的基本组成

docker的基本结构
镜像(Images):

Docker镜像就好比是一个模板,可以通过这个模板来创建容器服务。 例如:tomcat镜像 -> run -> tomcat容器 通过这个镜像可以创建多个 容器,最终服务运行或项目运行就是在容器中完成的。

容器(Container):

Docker通过容器技术,独立运行一个或一组应用,通过镜像来创建。容器可以进行启动、停止、删除等基本命令。目前可以把这个容器理解为一个简易的Linux系统。

仓库(Repository):

仓库(Docker Hub)是存放所有镜像的地方,仓库相当于GitHub,分为公有仓库和私有仓库。仓库(Docker Hub)默认是国外的,我们需要配置阿里云镜像进行访问。

1.4 安装Docker

首先,我们使用 XShell 连接Linux服务器,按照如下步骤进行操作即可:

  1. 卸载旧版本

    1. yum remove docker \
    2. docker-client \
    3. docker-client-latest \
    4. docker-common \
    5. docker-latest \
    6. docker-latest-logrotate \
    7. docker-logrotate \
    8. docker-engine
  2. 安装yum相关工具

    1. yum install -y yum-utils
  3. 配置 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

  1. 4. 安装 docker 引擎
  2. ```shell
  3. yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
  1. 安装完成后,启动 docker

    1. systemctl start docker
  2. 查看 docker 版本

    1. docker version
  3. 运行 hello-world

    1. docker run hello-world

    此时运行该命令后会提示如下信息:
    image.png
    表示找不到镜像,现在他会自己去官方拉取最新的镜像,拉取完成后如果输出了Hello form Docker!
    那就说明安装成功了!

  4. 查看一下下载的hello-world镜像

    1. [root@MiWiFi-R3G-srv /]# docker images
    2. REPOSITORY TAG IMAGE ID CREATED SIZE
    3. hello-world latest feb5d9fea6a5 7 months ago 13.3kB

    二、Docker基础

    2.1 Docker的底层原理

    2.1.1 docker的运行流程

    image.png

    2.1.2 docker是怎么工作的?

    Docker 是一个 Client - Server 结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问,DockerServer 接收到 Docker-Client 的指令,就会运行这个命令
    image.png

    2.1.3 Docker为什么比VM快?

    image.png

  5. Docker有着比VM更少的抽象层。

  6. Docker利用的是宿主机的内核,而VM需要的是Guest OS

所以说,新建一个容器的时候,Docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导,虚拟机是加载Guest OS,分钟级别的;而 Docker 是利用了宿主机的操作系统,省略了这个复杂的过程,实现秒级加载。

2.2 Docker的常用命令

docker参考文档:https://docs.docker.com/reference/

2.2.1 帮助命令

  1. docker version # 查看docker的版本信息
  2. docker info # 查看docker的详细信息,包括镜像和容器数量
  3. docker [命令] --help # 查看docker的所有命令,也可以查看docker的具体某个命令的使用

2.2.2 镜像命令

  1. **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 # 查看命令的详细信息,以及所有可选参数

  1. 2. `**docker search**`** 搜索镜像**
  2. 下面以搜索 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 />可选参数:
  3. ```shell
  4. --filter 按条件过滤搜索结果
  5. # 例如过滤STARS为3000以上的镜像
  6. docker search mysql --filter=STARS=3000
  1. **docker pull 镜像名** 拉取镜像

下面以下载 mysql 镜像为例,默认会下载最新版本的镜像
image.png
可选参数:

  1. :tag 指定tag下载,可以指定下载的版本(指定的版本需要在官网存在)
  2. # 例如下载mysql5.7版本的镜像
  3. docker pull mysql:5.7

image.png

注意: 采用分层下载的方式,如果已存在的模块不会重复下载,可以实现文件复用,极大的节省了内存。这是Linux的联合文件系统。

  1. **docker rmi** 删除镜像

可选参数:

  1. -f , --force # 强制删除镜像
  2. # 删除镜像的时候可以根据镜像的id镜像删除,在命令后面直接跟上id即可,例如:
  3. docker rmi -f 8aa4b5ffb001

image.png
可见,删除的时候也是只删除了自己的模块,不会删除之前的所有模块,不影响其他镜像。
删除的时候也可以通过$(...)携带参数,例如删除所有镜像:

  1. docker rmi -f $(docker images -aq) # 表示将查询到的所有镜像挨个删除

image.png

2.2.3 容器命令

启动容器

  1. # 启动容器
  2. docker run [可选参数] 镜像名

可选参数

  1. --name="Name" # 容器名字(用来区分容器)
  2. -d # 后台方式运行
  3. -it # 使用交互方式运行,进入容器查看内容
  4. -p # (小写)指定容器端口
  5. -p ip:主机端口:容器端口
  6. -p 主机端口:容器端口 (常用)
  7. -p 容器端口
  8. -P # (大写)随机指定端口

启动并进入容器,退出容器

  1. # 启动并进入容器
  2. docker run -it centos /bin/bash
  3. # 停止并退出容器
  4. exit
  5. # 退出容器但不停止
  6. ctrl + p + q

image.png
查看正在运行的容器

  1. docker ps # 查看正在运行的容器
  2. docker ps -a # 查看历史运行过的容器

image.png
删除容器

  1. docker rm 容器id # 删除指定id的容器,不能删除正在运行的容器,可以加上-f表示强制删除
  2. docker rm -f $(docker ps -aq) # 强制删除所有容器
  3. docker ps -a -q|xargs docker rm # 删除所有容器

启动和停止容器

  1. docker start 容器id # 启动容器
  2. docker restart 容器id # 重启容器
  3. docker stop 容器id # 停止当前正在运行的容器
  4. docker kill 容器id # 强制停止当前正在运行的容器
  5. docker pause 容器id # 暂停容器
  6. docker unpause 容器id # 取消暂停容器

2.2.4 其他命令

  1. **docker run -d 镜像名** 后台启动容器

image.png

注意事项:docker容器使用后台运行就必须要有一个前台进程,docker 发现没有应用就会自动停止。

  1. 查看日志 ```shell docker logs 容器id

可选参数

-tf # 显示日志 —tail number # 显示的条数

  1. 3. **查看容器中的进程信息**
  2. ```shell
  3. docker ps # 查看正在运行的容器
  4. docker top 容器id # 查看容器的进程信息

image.png

  1. 查看镜像的元数据

    1. docker inspect 容器id # 会显示出容器的所有详细信息以及配置信息等
  2. 进入当前正在运行的容器 ```shell

    我们的容器通常都是在后台运行的,有时我们需要进入容器修改一些配置。

命令

docker exec -it 容器id 路径

方式二

docker attach 容器id

区别

docker exec 进入容器后开启一个新的终端,可以直接在里面操作

docker attach 进入正在执行的终端,不会启动新的进程

  1. 6. **将容器内的文件拷贝到主机上**
  2. ```shell
  3. # 命令
  4. docker cp 容器id:容器内地址 主机上的目标地址

2.2.5 常用命令小结

image.png

2.3 部署Nginx

  1. # 首先通过docker search搜索nginx
  2. docker search nginx
  3. # 拉取nginx的镜像
  4. docker pull nginx
  5. # 查看镜像
  6. docker images
  7. # 后台启动nginx,并向外暴露一个端口8899
  8. docker run -d --name nginx01 -p 8899:80 nginx
  9. # 外部测试访问
  10. curl 192.168.31.103:8899

测试成功后,我们也可以进入容器修改nginx的配置文件nginx.conf

补充:暴露端口的概念 如果我们要从外网访问一个Docker容器中的服务,需要经过端口暴露才能访问到,否则会被防火墙拦截从而访问失败。如果我们的服务器是购买的阿里云服务器,那么在外面会再多一层阿里云安全组的保护

image.png

2.4 部署Tomcat

  1. # 首先搜索并下载镜像 这里下载9.0版本的
  2. docker search tomcat
  3. docker pull tomcat:9.0
  4. # 查看下载的镜像
  5. docker images
  6. # 以后台方式运行容器,并向外暴露一个端口
  7. docker run -d --name tomcat01 -p 8888:8080 tomcat:9.0

容器启动后,我们可以尝试在浏览器访问192.168.31.130:8888。此时会提示404,说明此时tomcat容器已经成功启动,只是我们的webapps下还没有资源所以什么都找不到

我们尝试进入容器一探究竟

  1. # 进入容器
  2. docker exec -it tomcat01 /bin/bash
  3. # 进入webapps目录
  4. cd webapps
  1. 此时发现什么内容都没有,为什么呢?

我们发现在容器中Linux命令少了很多不能使用,webapps中没有内容…… 这其实是阿里云镜像的原因:默认是最小的镜像,所以他将不必要的都剔除掉了,保证最小可运行环境

现在我们进入webapp.dist目录,发现我们的ROOT等文件夹在存放在这,现在我们只需要将webapps.dist 目录中的内容拷贝到 webapps 中再刷新浏览器即可访问到tomcat主页了

  1. # 拷贝
  2. cp -r ./webapps.dist/* ./webapps

image.png

2.5 提交镜像

我们可以将操作后的镜像提交为一个新的镜像,例如tomcat,默认在webapps目录下是没有资源的,那我们将webapps.dist目录中的文件拷贝到webapps目录中之后,我们启动tomcat后就可以看到内容了,我们可以将这个操作提交为一个新的镜像,我们以后启动这个镜像就是我们这个效果了。

  1. # 启动tomcat
  2. docker run -it -p 8888:8080 tomcat:9.0
  3. # 将webapps.dist目录中的内容拷贝到webapps中
  4. cp -r ./webapps.dist/* ./webapps
  5. # 提交镜像
  6. docker commit -m="提交的信息" -a="作者" 镜像id 镜像名:标签(版本)
  7. # 停止当前容器
  8. exit
  9. docker stop 容器id
  10. # 启动我们自己提交的镜像
  11. docker run -d -p 8080:8080 镜像名:标签

image.png

三、Docker进阶

3.1 容器数据卷

我们先来了解一下,什么是容器数据卷?

容器数据卷: docker 的理念将运行的环境打包形成容器运行,运行可以伴随容器,但是我们对数据的要求是希望持久化,容器之间可以共享数据,Docker 容器产生的数据,如果不通过docker commit生成新的镜像,使得数据作为容器的一部分保存下来,那么当容器被删除之后,数据也就没了,为了能够保存数据,在docker容器中使用卷

例如:我们在docker中安装了mysql,那么我们在mysql内存储的数据都是在这个镜像中的,如果我们将镜像删除了,那么数据也就没了。删库跑路咯~~ 容器之间有一个数据共享的技术,docker容器中产生的数据,同步到本地,这就是卷技术。
image.png

注意:容器的持久化和数据同步,容器之间也是可以数据同步的。

  1. # 命令 直接通过 -v 命令来挂载
  2. docker run -it -v 主机目录:容器内目录
  3. # 测试 我们测试将centos镜像中的 /home 目录与主机上的 /home/test 目录进行映射
  4. docker run -it -v /home/test:/home centos /bin/bash

现在,我们已经将两个目录进行了映射,主机上的该目录和容器内的该目录中的文件都会进行数据同步,我们在目录中新建,删除或修改文件,都会进行自动同步。

3.2 MySQL数据同步

在docker中下载的MySQL镜像,需要进数据和配置文件进行数据同步,这就要使用到数据卷技术。

  1. # 搜索并下载mysql,这里下载MySQL5.7版本
  2. docker pull mysql:5.7
  3. # 以后台方式启动并设置密码,使用数据卷技术对配置和数据进行数据同步
  4. 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连接建立连接
image.png
现在,我们成功连接到了docker镜像中的mysql,也可以正常使用,我们已经对数据和配置进行了同步,当docker容器被误删除的时候,我们也能保证数据的稳定。

3.3 具名和匿名挂载

在使用容器数据卷的时候,我们可以给挂载的容器起一个名字,这就是具名挂载,如果我们直接使用-v 容器内路径这种方式,没有声明容器外路径,也没有起名字这就是匿名挂载。
挂载一般分为三种方式:具名挂载、匿名挂载、指定路径挂载

  1. # 匿名挂载nginx
  2. docker run -d -P --name nginx01 -v /etc/nginx nginx
  3. # 查看挂载情况
  4. docker volume ls
  5. DRIVER VOLUME NAME
  6. local 0210e6d833f2fcc7eeb70147908e2de9d835aa87fe3d277b01172431ce657318
  7. # 具名挂载nginx
  8. docker run -d -P --name nginx02 -v named_mounted_nginx:/etc/nginx nginx
  9. #现在再来查看一下挂载情况
  10. docker volume ls
  11. DRIVER VOLUME NAME
  12. local 0210e6d833f2fcc7eeb70147908e2de9d835aa87fe3d277b01172431ce657318
  13. local named_mounted_nginx
  14. # 查看卷的挂载信息和具体路径
  15. docker volume inspect named_mounted_nginx
  16. # 可以看到如下信息
  17. [
  18. {
  19. "CreatedAt": "2022-05-01T17:48:17+08:00",
  20. "Driver": "local",
  21. "Labels": null,
  22. "Mountpoint": "/var/lib/docker/volumes/named_mounted_nginx/_data",
  23. "Name": "named_mounted_nginx",
  24. "Options": null,
  25. "Scope": "local"
  26. }
  27. ]

拓展

  1. # 在挂载的时候,可以通过ro或rw指定权限
  2. ro # readonly 只读
  3. rw # readwrite 可读可写 默认
  4. # 一旦设置了这个权限,容器对我们挂载出来的内容就有限定了
  5. docker run -d -P --name nginx02 -v named_mounted_nginx:/etc/nginx:ro nginx
  6. docker run -d -P --name nginx02 -v named_mounted_nginx:/etc/nginx:rw nginx
  7. # 只要设置了ro,那么容器内部就无法对其进行改变了,只能通过宿主机来改变

3.4 数据卷容器

我们可以通过数据卷容器实现容器之间的数据同步。例如,我们可以将一个容器挂载到另一个容器上,从而使得这两个容器之间数据同步,当然,我们还可以挂载更多的容器

  1. # 命令
  2. docker run -it --name docker02 --volume-from docker01 centos
  3. # 上述命令就是代表将docker02这个容器挂载到了docker01上面,此时docker01是父容器。两个容器之间是数据同步的
  4. # 我们也可以在这个docker01容器上面挂载更多的容器。例如:
  5. docker run -it --name docker03 --volume-from docker01 centos
  6. # 此时这三个容器之间的数据都是同步的

3.5 DockerFile

3.5.1 DockerFile介绍

DockerFIle 是用来构建 docker 镜像的构建文件,该文件都是一些脚本命令,我们可以使用 DockerFile 技术来构建一个镜像。
构建步骤:

  1. 编写一个 DockerFile 文件
  2. docker build 构建为一个镜像
  3. docker run 运行镜像
  4. docker push 发布镜像,可以发布到 Docker Hub或阿里云镜像仓库

    3.5.2 DockerFile构建过程

    基础知识:

  5. 每个保留关键字(指令)都必须是大写字母

  6. 执行顺序从上到下
  7. #表示注释
  8. 每一个指令都会创建一个新的镜像层,并提交

image.png

Docker 是面向开发的,我们以后要发布项目,做镜像,就要编写 DockerFile 文件,这个文件十分简单,Docker 镜像逐渐成为企业交付的标准,我们以前是需要交付一个jar包或war包,现在就需要进其构建为一个镜像。

  1. DockerFile:构建文件,制作镜像
  2. DockerImages:通过DockerFile构建生成的镜像,是最终运行和发布的产品
  3. Docker容器:容器就是镜像运行起来提供服务的