Docker学习笔记
一、Docker 概述
1.1、容器与 Docker 的核心思想
容器是一种基础工具。
泛指可以任何可以用于容纳其它物品的工具,可以部分或完全封闭,被用于容纳、储存、运输物品。
物体也可以放在容器中,而容器可以保护内容物。
- Docker 的核心思想就是打包装箱,而每个箱子之间是相互隔离的。
- Docker 可以通过隔离机制,将服务器利用到极致
1.2、Docker 能干吗
1、环境配置
借助镜像可以快速进行项目部署,重要的是官方会提供很多可以支持项目程序部署环境的镜像,轻轻一拉便可运行。
传统的应用开发完成后,需要提供一堆安装程序和配置说明文档,安装部署后需根据配置文档进行繁杂的配置才能正常运行。Docker化之后只需要交付少量容器镜像文件,在正式生产环境加载镜像并运行即可,应用安装配置在镜像里已经内置好,大大节省部署配置和测试验证时间。
2、资源
每个运行的容器都是基本最小的虚拟机环境,可以简单理解为阉割版的虚拟机。Docker 的应用直接运行在宿主机的内核中,它没有自己的内核,也没有虚拟硬件。
Docker是内核级虚拟化,其不像传统的虚拟化技术一样需要额外的Hypervisor支持,所以在一台物理机上可以运行很多个容器实例,可大大提升物理服务器的CPU和内存的利用率。
3、伸缩扩容
在服务资源升级和回滚上,借助升级扩容,一键能完成成千上百的服务集群的快速部署。
1.3、Docker 基本组成
1、镜像(Image)
Docker 镜像好比是一个模板,可以通过这个模板来创建容器服务,比如说:tomcat 镜像 –> Run –> tomcat 容器(提供服务器)。
通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)
2、容器(Container)
Docker 利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。
3、仓库(Repository)
仓库就是存放镜像的地方,仓库分为公有仓库和私有仓库。
二、Docker 的安装
2.1、安装
- 卸载旧版本的 Docker
1 | yum remove docker \ |
- 安装
yum-utils
软件包
1 | yum install -y yum-utils |
- 设置 Docker 仓库(这里使用阿里云的地址)
1 | yum-config-manager \ |
- 更新
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 |
- 设置开机自启
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
1、run 的运行流程图
2、Docker 工作原理
- Docker 是一个 Client - Server 结构的系统,Docker 的守护进程运行在主机上,通过 Socket 从客户端访问。
- Docker Server 接收到 Docker Client 的指令后,就会执行该命令。
2.4、Docker为什么比 虚拟机快?
- Docker 有着比虚拟机更少的抽象层。
- Docker 利用的是宿主机的内核。
- 新建一个容器时,docker 不需要像虚拟机一样重新加载一个操作系统内核,可以避免引导,虚拟机是加载
Guest OS
,分钟级别的加载时间,而 docker 利用宿主机的操作系统,省略了这个复杂的过程,秒级
三、Docker 常用命令
3.1、Docker 帮助命令
1、docker Version
显示 Docker 版本信息
2、docker info
显示 Docker 详细信息,包括镜像和容器信息
3、docker –help
帮助命令
3.2、镜像命令
1、docker images
查看所有本地的主机上的镜像
- 结果
- 解释
- repository:镜像的仓库源
- TAG:镜像的标签
- IMAGE ID:镜像的 id
- CREATED:镜像的创建时间
- SIZE:镜像大小
- 可选参数
- -a
–all,列出所有镜像
- -q
只显示镜像 id
- 组合使用
2、docker search
用于搜索镜像
- 搜索一下
MySQL
的镜像
1 | docker search mysql |
- 可选参数 -f
通过收藏数过滤结果,查询收藏数大于3000的镜像
1 | docker search mysql -f=stars=3000 |
3、docker pull
用于下载镜像的命令
- 使用 docker 下载 rabbit MQ
1 | docker pull rabbitmq |
- 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
新建容器并启动
- 参数说明
- –name=”Name”
为容器起一个别名,用于区分容器
- -d
后台方式运行
- -it
使用交互方式运行,进入容器查看内容
1 | docker run -it centos /bin/bash |
运行我们拉取的 Centos 镜像
- -p
指定容器端口,可以与主机映射
-p 8080:8080
-p
ip:主机端口:容器端口
-p 主机端口:容器端口 (最常用)
-p 容器端口
容器端口
- -P
随机指定容器端口
- -e
配置环境,在启动
MySQL
时使用这个参数配置密码
2、exit
从容器内退回主机
- 从刚才的 Centos 镜像中退出
1 | exit |
- 容器不停止退出
1 | Ctrl + P + Q |
3、docker ps
查看运行中的容器
- -a
查看曾经运行过的容器
- 列出曾经运行过的容器
1 | docker ps -a |
- -n=N
显示最近创建的 N 个容器
- -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 |
4、查看镜像的元数据
1 | docker inspect 容器id |
5、进入当前正在运行的容器
通常容器都是使用后台方式运行的,有时候我们需要进入正在运行的容器,修改配置
- 方式一(常用)
进入容器后开启一个新的终端,可以在里面进行操作
1 | docker exec -it 容器id bash/shell |
- 方式二
进入容器正在运行的终端,不开启新的进程
1 | docker attach 容器id |
6、从容器中拷贝文件到主机上
1 | docker cp 容器id:容器内路径 目的主机路径 |
进入正在运行的容器中,在 / home 目录下创建一个 test.java
将test.java 拷贝到主机的 /home 目录下
1 | docker cp 4b05786e6099:/home/test.java /home/test.java |
3.5、小结
3.6、练习
1、使用 Docker 安装 Nginx
- 搜索镜像
1 | docker search nginx |
- 下载镜像
1 | docker pull nginx |
- 启动容器
后台启动
nginx
,同时为这个nginx
起个别名(nginx01
),在容器内启动的端口为80,同时映射到主机上的端口为3344,即访问虚拟机上的3344端口即可访问容器内端口为80的nginx
.
1 | docker run -d --name nginx01 -p 3344:80 nginx |
- 访问,查看结果
nginx
启动成功
2、使用 Docker 安装一个 Tomcat
- 搜索镜像
1 | docker search tomcat |
- 拉取镜像
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
目录上面!
- 特点
- 数据卷可以在容器之间共享或者重用数据
- 卷中的更改可以直接生效
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
5.2、数据卷使用
1、直接使用命令挂载
1 | docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口 |
- 启动 Centos 镜像容器,然后将 容器中的
/home
目录 挂在主机上的/home/ceshi
目录中
1 | docker run -it -v /home/ceshi:/home centos /bin/bash |
- 查看虚拟机 /home 目录
- 此时两个文件夹的文件内容可以相互同步
开启两个会话,在第一个会话中创建一个文件,然后在第二个会话中查看文件是否同步
- 未创建前
- 外部
/home/ceshi
文件夹
- 内部
/home
文件夹
- 在宿主机的
/home/ceshi
下创建一个文件test.java
- 此时查看容器中
/home
文件夹,可以看到文件已经同步
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
可以发现连接成功
- 在本地创建一个
testdb
数据库,然后查看/home/mysql/data
目录
可以看到出现了
testdb
目录
3、查看容器挂载的数据卷位置
需要在容器外使用此命令
1 | docker inspect 容器ID |
查看刚刚启动的
MySQL
挂载的位置
1 | docker inspect a6ef015d287b |
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
的数据卷
- 查看这个具名挂载卷的路径,使用
docker volume inspect 卷名
1 | docker volume inspect juming-nginx |
3、查看所有挂载卷的情况
1 | docker volume ls |
- 对于那些没有指定绝对挂载路径的挂载卷(具名、匿名),那么 Docker 会默认挂载在
/var/lib/docker/volumes
下
4、如何确定挂载方式
- 具名挂载
-v 参数后带 指定路径 : 容器内路径,注意这里的指定路径不是虚拟机内绝对路径,即不以
/
开头。
- 匿名挂载
-v 参数后不指定虚拟机路径,直接带容器内路径的挂载即为匿名挂载
- 指定路径挂载
-v 参数后带 宿主机绝对路径 : 容器内路径 的挂载是指定路径挂载,这里的宿主机绝对路径以
/
开头
六、DockerFile 镜像构建文件
6.1、介绍
1、概述
构建镜像的方式有两种:一种是基于容器制作,另一种就是通过
Dockerfile
。Dockerfile
其实就是我们用来构建Docker镜像的源码,当然这不是所谓的编程源码,而是一些命令的组合,只要理解它的逻辑和语法格式,就可以编写Dockerfile
了。
Dockerfile
是一个用来构建镜像的文本文件,是一个脚本文件,文本内容包含了一条条构建镜像所需的指令和说明。
Docker
中的镜像是一层一层的,DockerFile
中一条命令对应一层镜像。
2、作用
简要概括
Dockerfile
的作用:它可以让用户个性化定制Docker镜像。因为工作环境中的需求各式各样,网络上的镜像很难满足实际的需求。 用户可以将自己的应用打包成镜像,这样就可以将我们的应用放入容器中运行,我们同时可以使用
Dockerfile
修改DockerHub
给我们提供的官方镜像。
3、创建一个 DockerFile
以
centos
为基础镜像构建
1 | FROM centos |
使用命令生成镜像
1 | docker build -f 文件路径 -t 生成名称 . |
使用我们刚才编写的文件生成镜像
1 | [root@localhost testDockerFile]# docker build -f dockerfile1 -t wuhu/centos . |
此时查看所有镜像
4、构建步骤
- 编写一个
DockerFile
文件 - 使用
Docker build
指令构建成为一个镜像 - 使用
Docker run
指令运行镜像 - 使用
Docker push
发布镜像(可以发送到DockerHub
或者阿里云镜像仓库)
6.2、DockerFile 指令
1、基础知识
- 每个保留关键字(指令)都必须是大写字母。
- 指令从上到下顺序执行
#
表示注释- 每一个指令都会创建一个新的镜像层并提交
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 | 构建镜像时设置环境变量 |
LABEL | LABEL 用于为镜像添加元数据,元数据以键值对的方式指定 |
3、ENTRYPOINT 和 CMD
相同点
- 只能写一条,如果写了多条,那么只有最后一条生效
- 容器启动时才运行,运行时机相同
不同点
ENTRYPOINT
不会被运行的command
覆盖,而CMD
则会被覆盖- 如果我们在
DockerFile
中同时写了 ENTRYPOINT 和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT
的参数
补充:如果我们在
DockerFile
中同时写了 ENTRYPOINT 和CMD,并且CMD是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效
4、FROM 指定基础镜像
语法格式
1 | FROM <image> |
5、MAINTAINER 指定镜像作者
示例
1 | MAINTAINER hzx |
6、ADD 添加文件到容器
将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似
wget
- 语法格式
1 | ADD <src>... <dest> |
- 示例
1 | ADD test dest # 添加test文件到 `WORKDIR`/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 |
- 查看
ifconfig
命令
1 | [root@a32a64ce4e7b /]# ifconfig |
2、构建自己的 Centos
在原有的
Centos
镜像上添加 vim 编辑器和 net-tools 工具
dockerFile
内容如下
1 | FROM centos |
- 通过上面的文件构建我们自己的
Centos
镜像
1 | [root@localhost dockerfiledir]# docker build -f centosdockerfile -t mycentos:0.1 . |
以
centosdockerfile
构建我们自己的镜像
3、构建完成后,查看现有镜像
- 使用
docker images
查看所有镜像
1 | docker images |
可以看到我们刚刚构建的镜像在列表中
4、运行自定义镜像
1 | docker run -it mycentos:0.1 |
进入镜像后,测试 vim 编辑器和 net-tools 是否安装成功
- vim 编辑器
编辑
test.txt
文件
- net-tools
测试使用
ifconfig
命令
1 | ifconfig |
6.4、发布自己的 Docker 镜像
到 Docker Hub 上注册自己的账户
在自己的虚拟机中登录此用户,使用
docker login
命令
- 输入
docker login -u 账号
命令
1 | [root@localhost myimages]# docker login -u wuhuqifei123 |
- 输入密码
- 使用
docker push 镜像名:版本号
命令推送镜像,在提交前先给镜像打个标签,尽量带上版本号
- 打标签
1 | docker tag 948b3e7847b9 wuhuqifei123/mycentos:0.1 |
- 推送镜像
1 | docker push wuhuqifei123/mycentos:0.1 |
- 结果
6.5、Dockerfile 构建 Spring Boot 应用
1、构建步骤
开发一个完整的 Spring Boot 应用程序
对 Spring Boot 应用进行打包,打包方式通常有两种
- war 包,基于
Tomcat
镜像 - jar 包(主流),基于 JDK 镜像
- war 包,基于
将 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
即可打包
- 此时在项目的
target
文件夹中可以看到项目 jar 包
- 在项目
- 在服务器中创建
dockerfile
上下文目录,即存放dockerfile
的目录- 创建
Dockerfile
文件,可以先使用 touch 命令创建 - 上传应用 jar 包到上下文目录中
- 创建
2、编写 Dockerfile
1 | # Spring Boot jar包依赖于 jre |
3、构建并启动容器
- 构建容器
1 | docker build -t education_management_system:0.1 . |
- 启动容器
1 | docker run -d -p 8080:8080 --name ems education_management_system:0.1 |
查看容器启动结果
- 查看应用日志
1 | docker logs -f 容器id |
4、查看容器是否启动成功
我们可以访问这个应用的某个接口,由于
Docker
中没有MySQL
驱动,所以会报错,但我们已经连接上了这个应用