一、Docker 概述

image-20210429192804615

1.1、容器与 Docker 的核心思想

容器是一种基础工具。

泛指可以任何可以用于容纳其它物品的工具,可以部分或完全封闭,被用于容纳、储存、运输物品。

物体也可以放在容器中,而容器可以保护内容物。

  • Docker 的核心思想就是打包装箱,而每个箱子之间是相互隔离的。
  • Docker 可以通过隔离机制,将服务器利用到极致

1.2、Docker 能干吗

1、环境配置

借助镜像可以快速进行项目部署,重要的是官方会提供很多可以支持项目程序部署环境的镜像,轻轻一拉便可运行。

传统的应用开发完成后,需要提供一堆安装程序和配置说明文档,安装部署后需根据配置文档进行繁杂的配置才能正常运行。Docker化之后只需要交付少量容器镜像文件,在正式生产环境加载镜像并运行即可,应用安装配置在镜像里已经内置好,大大节省部署配置和测试验证时间。

2、资源

每个运行的容器都是基本最小的虚拟机环境,可以简单理解为阉割版的虚拟机。Docker 的应用直接运行在宿主机的内核中,它没有自己的内核,也没有虚拟硬件。

Docker是内核级虚拟化,其不像传统的虚拟化技术一样需要额外的Hypervisor支持,所以在一台物理机上可以运行很多个容器实例,可大大提升物理服务器的CPU和内存的利用率。

3、伸缩扩容

在服务资源升级和回滚上,借助升级扩容,一键能完成成千上百的服务集群的快速部署。

1.3、Docker 基本组成

image-20210417214830819

1、镜像(Image)

Docker 镜像好比是一个模板,可以通过这个模板来创建容器服务,比如说:tomcat 镜像 –> Run –> tomcat 容器(提供服务器)。

通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)

2、容器(Container)

Docker 利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。

3、仓库(Repository)

仓库就是存放镜像的地方,仓库分为公有仓库和私有仓库。

二、Docker 的安装

2.1、安装

  • 卸载旧版本的 Docker
1
2
3
4
5
6
7
8
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
  • 安装 yum-utils 软件包
1
yum install -y yum-utils
  • 设置 Docker 仓库(这里使用阿里云的地址)
1
2
3
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  • 更新 yum 软件包索引
1
yum makecache fast
  • 安装 docker
1
yum install docker-ce docker-ce-cli containerd.io

在各个选项中均选择 “y” 即可

  • 启动 Docker
1
systemctl start docker
  • 查看 docker 版本
1
docker version
  • 测试运行
1
docker run hello-world

image-20210417221527427

  • 设置开机自启
1
systemctl enable docker
  • 查看当前状态
1
systemctl status docker

2.2、卸载

  • 卸载依赖
1
yum remove docker-ce docker-ce-cli containerd.io
  • 删除资源
1
rm -rf /var/lib/docker

2.3、回顾 Hello World

image-20210417221527427

1、run 的运行流程图

image-20210417224143410

2、Docker 工作原理

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

image-20210417225250529

2.4、Docker为什么比 虚拟机快?

  • Docker 有着比虚拟机更少的抽象层。
  • Docker 利用的是宿主机的内核。

image-20210417225629611

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

image-20210417225823250

三、Docker 常用命令

3.1、Docker 帮助命令

1、docker Version

显示 Docker 版本信息

2、docker info

显示 Docker 详细信息,包括镜像和容器信息

3、docker –help

帮助命令

3.2、镜像命令

1、docker images

查看所有本地的主机上的镜像

  • 结果

image-20210417230912922

  • 解释
  1. repository:镜像的仓库源
  2. TAG:镜像的标签
  3. IMAGE ID:镜像的 id
  4. CREATED:镜像的创建时间
  5. SIZE:镜像大小
  • 可选参数
  1. -a

–all,列出所有镜像

image-20210417231424738

  1. -q

只显示镜像 id

image-20210417231444345

  1. 组合使用

image-20210417231508290

用于搜索镜像

  • 搜索一下 MySQL 的镜像
1
docker search mysql

image-20210417232300133

  • 可选参数 -f

通过收藏数过滤结果,查询收藏数大于3000的镜像

1
docker search mysql -f=stars=3000

image-20210417232503052

3、docker pull

用于下载镜像的命令

  • 使用 docker 下载 rabbit MQ
1
docker pull rabbitmq

image-20210417233021327

  • docker pull 镜像名 [tag]

可以指定要下载的版本,默认下载最新版

1
docker pull mysql:5.7

这样就可以直接下载 MySQL 5.7 的镜像

4、docker rmi

用于删除镜像,可以通过镜像 ID 和镜像名称进行删除,如:

1
docker rmi -f xxx(image Id)

其中 f 表示全部删除

  • 可以根据 Image Id 进行批量删除

docker images -eq :列出所有镜像 id

1
docker rmi -f ${docker images -aq}

3.3、容器命令

我们需要先有镜像,才可以创建容器

1、docker run [可选参数] image

新建容器并启动

  • 参数说明
  1. –name=”Name”

为容器起一个别名,用于区分容器

  1. -d

后台方式运行

  1. -it

使用交互方式运行,进入容器查看内容

1
docker run -it centos /bin/bash

运行我们拉取的 Centos 镜像

image-20210418131847355

  1. -p

指定容器端口,可以与主机映射

-p 8080:8080

-p ip:主机端口:容器端口

-p 主机端口:容器端口 (最常用)

-p 容器端口

容器端口

  1. -P

随机指定容器端口

  1. -e

配置环境,在启动 MySQL 时使用这个参数配置密码

2、exit

从容器内退回主机

  • 从刚才的 Centos 镜像中退出
1
exit

image-20210418131931705

  • 容器不停止退出
1
Ctrl + P + Q

3、docker ps

查看运行中的容器

  1. -a

查看曾经运行过的容器

  • 列出曾经运行过的容器
1
docker ps -a

image-20210418132015696

  1. -n=N

显示最近创建的 N 个容器

image-20210418132347537

  1. -q

只显示容器编号

4、docker rm

  • docker rm 容器id

删除指定容器,不能删除正在运行的容器,如果需要强制删除,那么可以使用docker rm -f

  • docker rm -f $(docker ps -aq)

删除所有的容器

5、docker start 容器 id

启动容器

6、docker restart 容器 id

重启容器

7、docker stop 容器id

停止容器

8、docker kill 容器 id

强制停止一个容器

3.4、常用其他命令

1、后台启动容器

1
docker run -d rabbitmq

注意:docker 容器在使用后台运行时,必须要有一个前台进程,如果没有任何一个前台进程,那么docker 就会自动停止此容器,也就是这个服务直接停止。

2、查看日志命令

1
docker logs

3、查看容器中的进程信息

1
docker top 容器id

image-20210418134251226

4、查看镜像的元数据

1
docker inspect 容器id

image-20210418134429854

5、进入当前正在运行的容器

通常容器都是使用后台方式运行的,有时候我们需要进入正在运行的容器,修改配置

  • 方式一(常用)

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

1
docker exec -it 容器id bash/shell

image-20210418134950677

  • 方式二

进入容器正在运行的终端,不开启新的进程

1
docker attach 容器id

image-20210418135424621

6、从容器中拷贝文件到主机上

1
docker cp 容器id:容器内路径 目的主机路径
  • 进入正在运行的容器中,在 / home 目录下创建一个 test.java

  • 将test.java 拷贝到主机的 /home 目录下

1
docker cp 4b05786e6099:/home/test.java /home/test.java

image-20210418140306702

3.5、小结

image-20210418140843414

3.6、练习

1、使用 Docker 安装 Nginx

  • 搜索镜像
1
docker search nginx

image-20210418141440013

  • 下载镜像
1
docker pull nginx
  • 启动容器

后台启动 nginx ,同时为这个 nginx 起个别名(nginx01),在容器内启动的端口为80,同时映射到主机上的端口为3344,即访问虚拟机上的3344端口即可访问容器内端口为80的 nginx.

1
docker run -d --name nginx01 -p 3344:80 nginx

image-20210418141817420

  • 访问,查看结果

nginx 启动成功

image-20210418141907566

2、使用 Docker 安装一个 Tomcat

  • 搜索镜像
1
docker search tomcat

image-20210418143043839

  • 拉取镜像
1
docker pull tomcat:9.0
  • 启动容器
1
docker run -d --name tomcat01 -p 3345:8080 tomcat
  • docker 中下载的 tomcat 镜像是被阉割过的,webapps 文件夹是空的,保证了最小可用环境

四、Docker 镜像讲解

镜像是一种轻量级、可执行的独立软件包,用来打包软件环境和基于环境开发的软件,它包括运行某些软件所需要的所有内容,包括代码、库、环境变量和配置文件。

所有的应用直接打包成为一个 docker 镜像,就可以直接跑起来

五、容器数据卷

5.1、介绍

Docker 将应用和环境打包为一个镜像!

对于容器中的数据,如果数据都在容器中,那么我们容器删除的时候,数据就会丢失!

所以我们需要对数据进行持久化!(例如:MySQL中的数据需要存储在本地)

容器之间可以有一个数据共享技术!Docker容器中产生的数据,同步到本地!

这就是卷技术,目录的挂载,将我们容器内的目录挂载到 linux 目录上面!

image-20210418160042726

  • 特点
  1. 数据卷可以在容器之间共享或者重用数据
  2. 卷中的更改可以直接生效
  3. 数据卷中的更改不会包含在镜像的更新中
  4. 数据卷的生命周期一直持续到没有容器使用它为止

5.2、数据卷使用

1、直接使用命令挂载

1
docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口
  • 启动 Centos 镜像容器,然后将 容器中的 /home 目录 挂在主机上的 /home/ceshi 目录中
1
docker run -it -v /home/ceshi:/home centos /bin/bash

image-20210418161000996

  • 查看虚拟机 /home 目录

image-20210418161032645

  • 此时两个文件夹的文件内容可以相互同步

开启两个会话,在第一个会话中创建一个文件,然后在第二个会话中查看文件是否同步

  • 未创建前
  1. 外部 /home/ceshi 文件夹

image-20210427202322082

  1. 内部 /home 文件夹

image-20210427202346637

  • 在宿主机的 /home/ceshi 下创建一个文件 test.java

image-20210427202433781

  • 此时查看容器中 /home 文件夹,可以看到文件已经同步

image-20210427202501727

2、MySQL 数据同步

  • 安装 MySQL
1
docker pull mysql:8.0.19
  • 启动 MySQL
1
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=root --name mysql01 mysql:8.0.19
  • 连接 MySQL

可以发现连接成功

image-20210418162457259

  • 在本地创建一个 testdb 数据库,然后查看 /home/mysql/data 目录

可以看到出现了 testdb 目录

image-20210427205714409

3、查看容器挂载的数据卷位置

需要在容器外使用此命令

1
docker inspect 容器ID

查看刚刚启动的 MySQL 挂载的位置

1
docker inspect a6ef015d287b

image-20210427204353948

5.3、具名挂载和匿名挂载

1、具名挂载

​ 所谓匿名挂载(匿名卷),即在进行数据卷挂载的时候不指定宿主机的数据卷目录,-v命令之后直接跟上容器内数据卷所在的路径

​ 如果我们使用匿名挂载,那么我们不能直接知道容器内目录的具体挂载位置,此时我们可以使用 docker inspect 容器ID 命令来查看当前容器内目录在虚拟机中的挂在位置

1
docker run -d -P --name nginx02 -v /etc/nginx nginx

2、匿名挂载

​ 而具名挂载(命名卷)即在进行数据卷挂载的时候既指定宿主机数据卷所在路径,又指定容器数据卷所在路径

注意,这里宿主机的路径不是绝对路径

1
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
  • 此时再查看所有的挂载卷,可以看到一个名为 juming-nginx 的数据卷

image-20210427212922138

  • 查看这个具名挂载卷的路径,使用 docker volume inspect 卷名
1
docker volume inspect juming-nginx

image-20210427215049610

3、查看所有挂载卷的情况

1
docker volume ls

image-20210427212440619

  • 对于那些没有指定绝对挂载路径的挂载卷(具名、匿名),那么 Docker 会默认挂载在 /var/lib/docker/volumes

4、如何确定挂载方式

  • 具名挂载

-v 参数后带 指定路径 : 容器内路径,注意这里的指定路径不是虚拟机内绝对路径,即不以 / 开头。

  • 匿名挂载

-v 参数后不指定虚拟机路径,直接带容器内路径的挂载即为匿名挂载

  • 指定路径挂载

-v 参数后带 宿主机绝对路径 : 容器内路径 的挂载是指定路径挂载,这里的宿主机绝对路径以 / 开头

六、DockerFile 镜像构建文件

6.1、介绍

1、概述

image-20210429194954425

​ 构建镜像的方式有两种:一种是基于容器制作,另一种就是通过 DockerfileDockerfile 其实就是我们用来构建Docker镜像的源码,当然这不是所谓的编程源码,而是一些命令的组合,只要理解它的逻辑和语法格式,就可以编写 Dockerfile 了。

Dockerfile 是一个用来构建镜像的文本文件,是一个脚本文件,文本内容包含了一条条构建镜像所需的指令和说明。

Docker 中的镜像是一层一层的,DockerFile 中一条命令对应一层镜像。

2、作用

    简要概括 Dockerfile 的作用:它可以让用户个性化定制Docker镜像。因为工作环境中的需求各式各样,网络上的镜像很难满足实际的需求。

  ​ 用户可以将自己的应用打包成镜像,这样就可以将我们的应用放入容器中运行,我们同时可以使用 Dockerfile 修改 DockerHub 给我们提供的官方镜像。

3、创建一个 DockerFile

centos 为基础镜像构建

1
2
3
4
5
6
FROM centos

VOLUME ["volume01","volume02"]

CMD echo "---------end--------"
CMD /bin/bash

使用命令生成镜像

1
docker build -f 文件路径 -t 生成名称 .

使用我们刚才编写的文件生成镜像

1
[root@localhost testDockerFile]# docker build -f dockerfile1 -t wuhu/centos .

image-20210427230536629

此时查看所有镜像

image-20210427230716602

4、构建步骤

  • 编写一个 DockerFile 文件
  • 使用 Docker build 指令构建成为一个镜像
  • 使用 Docker run 指令运行镜像
  • 使用 Docker push 发布镜像(可以发送到 DockerHub 或者阿里云镜像仓库)

6.2、DockerFile 指令

1、基础知识

image-20210429200225696

  • 每个保留关键字(指令)都必须是大写字母。
  • 指令从上到下顺序执行
  • # 表示注释
  • 每一个指令都会创建一个新的镜像层并提交

DockerFile 是面向开发的,以后我们需要发布项目,做镜像时,就需要编写 DockerFile

DockerFile 这个构建文件,定义了一切步骤,相当于一份源代码。

DockerImages 通过 DockerFile 构建生成的镜像,最终变成发布和运行的产品

2、指令概览

指令说明
FROM指定这个镜像的基础镜像,FROM 指令必是 Dockerfile 文件中的首条命令,启动构建流程后,Docker 将会基于该镜像构建新镜像,FROM 后的命令也会基于这个基础镜像。
MAINTAINER指定镜像维护者信息(镜像作者,姓名 + 邮箱)
RUN用于指定 docker build (构建)过程中要运行的命令,并生成一个中间镜像,一个镜像可以包含多个 RUN 命令
ADD**将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似 wget**,如果我们需要在自定义的 Centos 镜像中添加一个 TOMCAT,那么此时可以使用 add 命令添加 tomcat 镜像,每次添加都会多一层镜像
WORKDIR镜像的工作目录,之后的命令都是基于此工作目录,类似于 cd 命令
VOLUME容器数据卷,用于指定持久化目录(即挂载在虚拟机上的路径)
EXPOSE对外暴露的端口(常用)
COPY功能类似ADD,但是是不会自动解压文件,也不能访问网络资源,就是不能解压,其他限制条件跟ADD一样
CMD指定这个容器启动时要运行的命令,如果写了多条命令,那么只有最后一条生效,但 CMD 会被运行时的 command 覆盖
ENTRYPOINT指定这个容器启动时要运行的命令,如果写了多条命令,那么只有最后一条生效,但 ENTRYPOINT 不会被运行时的 command 覆盖
ENV构建镜像时设置环境变量
LABELLABEL 用于为镜像添加元数据,元数据以键值对的方式指定

3、ENTRYPOINT 和 CMD

相同点

  • 只能写一条,如果写了多条,那么只有最后一条生效
  • 容器启动时才运行,运行时机相同

不同点

  • ENTRYPOINT 不会被运行的 command 覆盖,而 CMD 则会被覆盖
  • 如果我们在 DockerFile 中同时写了 ENTRYPOINT 和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为 ENTRYPOINT 的参数

补充:如果我们在 DockerFile 中同时写了 ENTRYPOINT 和CMD,并且CMD是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效

4、FROM 指定基础镜像

语法格式

1
FROM <image>

5、MAINTAINER 指定镜像作者

示例

1
2
3
MAINTAINER hzx
MAINTAINER 763882220@qq.com
MAINTAINER hzx <763882220@qq.com>

6、ADD 添加文件到容器

将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似 wget

  • 语法格式
1
ADD <src>... <dest>
  • 示例
1
2
ADD test dest    # 添加test文件到 `WORKDIR`/dest 文件夹中
ADD test /dest # 添加test文件到 `/dest 文件夹中

6.3、构建自己的 Centos

Docker Hub 中绝大部分镜像都是从 scratch 开始构建的,在原有的 Centos 镜像上添加功能。

1、查看 Docker 自带的 Centos

  • 进入 Docker 自带的 Centos 容器中
1
[root@localhost dockerfiledir]# docker run -it -P centos
  • 查看 vim 命令
1
vim test.txt

image-20210429143547136

  • 查看 ifconfig 命令
1
[root@a32a64ce4e7b /]# ifconfig

image-20210429143633462

2、构建自己的 Centos

在原有的 Centos 镜像上添加 vim 编辑器和 net-tools 工具

  • dockerFile 内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
FROM centos
MAINTAINER hzx<763882220@qq.com>

# 设置一个环境变量
ENV MYPATH /usr/local

# 指定工作目录
WORKDIR $MYPATH

# 安装一些docker自带centos中没有的功能
# 安装vim文本编辑器
RUN yum -y install vim
# 安装网络工具
RUN yum -y install net-tools

# 指定对外暴露的端口
EXPOSE 80

CMD echo $MYPATH
CMD echo "=============end============="
CMD /bin/bash
  • 通过上面的文件构建我们自己的 Centos 镜像
1
[root@localhost dockerfiledir]# docker build -f centosdockerfile -t mycentos:0.1 .

centosdockerfile 构建我们自己的镜像

image-20210429144528335

3、构建完成后,查看现有镜像

  • 使用 docker images 查看所有镜像
1
docker images

可以看到我们刚刚构建的镜像在列表中

image-20210429145035710

4、运行自定义镜像

1
docker run -it mycentos:0.1

进入镜像后,测试 vim 编辑器和 net-tools 是否安装成功

  • vim 编辑器

编辑 test.txt 文件

image-20210429145632802

  • net-tools

测试使用 ifconfig 命令

1
ifconfig

image-20210429145834639

6.4、发布自己的 Docker 镜像

  • Docker Hub 上注册自己的账户

  • 在自己的虚拟机中登录此用户,使用 docker login 命令

  1. 输入 docker login -u 账号 命令
1
[root@localhost myimages]# docker login -u wuhuqifei123

image-20210429191552634

  1. 输入密码

image-20210429191731691

  • 使用 docker push 镜像名:版本号 命令推送镜像,在提交前先给镜像打个标签,尽量带上版本号
  1. 打标签
1
docker tag 948b3e7847b9 wuhuqifei123/mycentos:0.1
  1. 推送镜像
1
docker push wuhuqifei123/mycentos:0.1
  • 结果

image-20210429193422946

6.5、Dockerfile 构建 Spring Boot 应用

1、构建步骤

  • 开发一个完整的 Spring Boot 应用程序

  • 对 Spring Boot 应用进行打包,打包方式通常有两种

    • war 包,基于 Tomcat 镜像
    • jar 包(主流),基于 JDK 镜像
  • 将 Spring Boot 打包成 jar 包的方式

    • 在项目 pom.xml 文件下添加以下配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
    <execution>
    <goals>
    <goal>repackage</goal>
    </goals>
    </execution>
    </executions>
    </plugin>
    </plugins>
    </build>
    • 点击 Maven 中的 pagkage 即可打包

    image-20210429201847874

    • 此时在项目的 target 文件夹中可以看到项目 jar 包

image-20210429201936081

  • 在服务器中创建 dockerfile 上下文目录,即存放 dockerfile 的目录
    • 创建 Dockerfile 文件,可以先使用 touch 命令创建
    • 上传应用 jar 包到上下文目录中

image-20210429202521138

2、编写 Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
# Spring Boot jar包依赖于 jre
FROM openjdk:8-jre
# 指定工作目录
WORKDIR /usr/local/docker/education_management_system

# 拷贝应用jar包到镜像中,并重命名为app.jar
ADD education_management_system-1.0.0-SNAPSHOT.jar app.jar

# 向外暴露8080端口,应用中暴露的端口也是8080
EXPOSE 8080

ENTRYPOINT ["java","-jar"]
CMD ["app.jar"]

3、构建并启动容器

  • 构建容器
1
docker build -t education_management_system:0.1 .

image-20210429211641685

  • 启动容器
1
docker run -d -p 8080:8080 --name ems education_management_system:0.1

查看容器启动结果

image-20210429211753319

  • 查看应用日志
1
docker logs -f 容器id

image-20210429215458220

4、查看容器是否启动成功

我们可以访问这个应用的某个接口,由于 Docker 中没有 MySQL 驱动,所以会报错,但我们已经连接上了这个应用

image-20210429214919547