🔥 本文由 程序喵正在路上 原创,CSDN首发!
💖 系列专栏:Springcloud微服务
🌠 首发时间:2024年6月22日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾
目录
- 环境准备
- 准备Linux环境
- SSH客户端
- 安装MobarXterm
- 配置默认编辑器
- 配置右键粘贴
- SSH配置
- 关闭X-Server服务
- 安装Docker
- 快速入门
- 部署MySQL
- 命令解读
- Docker常见命令
- 数据卷
- 什么是数据卷
- 数据卷命令
- 挂载本地目录或文件
环境准备
学习 Docker,我们需要一台虚拟机,这里我们使用的是 CentOS7。
准备Linux环境
首先,我们要准备一个 Linux 的系统,成本最低的方式就是在本地安装一台虚拟机。为了统一学习环境,不管是使用 MacOS 还是 Windows 系统,都建议安装一台虚拟机。
Windows 采用 VMware 或者 VirtualBox,Mac 则采用 Fusion,或者其他你熟悉的 Linux 环境。
安装教程在 CSDN 有很多,也可以点击此处参考我的这篇博客,注意需要配置好虚拟机的网络,宿主机和虚拟机要可以互相 ping 通。
SSH客户端
安装MobarXterm
在 VMware 或者 VirtualBox 界面中直接操作 CentOS7 虚拟机是非常不友好的,所以一般推荐使用专门的 SSH 客户端。市面上常见的有:
Xshell
:个人免费,商业收费,之前爆出过有隐藏后门,不推荐Finshell
:基础功能免费,高级功能收费,基于 Java,内存占用较高(在1个G左右),不推荐MobaXterm
:基础功能免费、高级功能收费。开源、功能强大、内存占用低(只有10M左右),推荐使用,点击此处进入下载
下载解压后,双击 .exe 文件即可使用,无需安装:
界面是这样的:
连接虚拟机:
界面说明:
配置默认编辑器
首先建议设置一下默认编辑器,这样我们通过 MobaXterm 的 FTP 工具打开文件时会以指定的编辑器打开,方便修改。我这里配置的是 vscode:
配置右键粘贴
复制粘贴是很常用的配置,MobaXterm 默认左键选中即复制,但是需要配置右键点击为粘贴:
这样,复制和粘贴可以全部通过鼠标操作,无需按键。
SSH配置
接下来还有几个 ssh 配置:
分别是:
- 默认的登录用户
- ssh 保持连接
- 取消连接成功后的欢迎 banner
关闭X-Server服务
大多数情况下,我们没有 x-server 的需求,因此可以选择不要自启动:
安装Docker
安装教程参考 Docker 官方文档,地址如下:https://docs.docker.com/engine/install/centos/
卸载旧版Docker
首先如果系统中已经存在旧的 Docker,则先卸载:
sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
配置Docker的yum库
首先要安装一个 yum 工具:
yum install -y yum-utils
安装成功后,执行命令,配置 Docker 的 yum 源:
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
安装Docker
最后,执行命令,安装 Docker:
yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
查看 Docker:
docker -v
启动和校验
# 启动Docker
systemctl start docker# 停止Docker
systemctl stop docker# 重启
systemctl restart docker# 设置开机自启
systemctl enable docker# 执行docker ps命令,如果不报错,说明安装启动成功
docker ps
配置镜像加速
这里以阿里云镜像加速为例。
首先访问阿里云网站:https://www.aliyun.com/,注册一个账号。
在首页的产品中,找到阿里云的容器镜像服务:
点击后进入控制台:
找到镜像工具下的镜像加速器,页面向下滚动,即可找到配置的文档说明,执行操作文档的指令即可:
快速入门
部署MySQL
首先,我们利用 Docker 来安装一个 MySQL 软件,如果是利用传统方式部署 MySQL,大概的步骤有:
- 搜索并下载 MySQL 安装包
- 上传至 Linux 环境
- 编译和配置环境
- 安装
而使用 Docker 安装,仅仅需要一步即可,在命令行输入下面的命令:
docker run -d \--name mysql \-p 3306:3306 \-e TZ=Asia/Shanghai \-e MYSQL_ROOT_PASSWORD=123 \mysql
运行效果如图:
这样,MySQL 就安装完毕了。
大家可以发现,当我们执行命令后,Docker 做的第一件事情,是去自动搜索并下载了 MySQL,然后会自动运行 MySQL,我们完全不用插手,是不是非常方便。
而且,这种安装方式你完全不用考虑运行的操作系统环境,它不仅仅在 CentOS 系统是这样,在 Ubuntu 系统、macOS 系统、甚至是装了 WSL 的 Windows 下,都可以使用这条命令来安装 MySQL。
要知道,不同操作系统下其安装包、运行环境是都不相同的。如果是手动安装,必须手动解决安装包不同、环境不同的、配置不同的问题。
而使用了 Docker,这些完全不用考虑。就是因为 Docker 会自动搜索并下载 MySQL。注意,这里下载的不是安装包,而是镜像。镜像中不仅包含了 MySQL 本身,还包含了其运行所需要的环境、配置、系统级函数库。因此它在运行时就有自己独立的环境,就可以跨系统运行,也不需要手动再次配置环境了。这套独立运行的隔离环境我们称为容器。
说明:
- 镜像:英文是 image
- 容器:英文是 container
因此,Docker 安装软件的过程,就是自动搜索下载镜像,然后创建并运行容器的过程。
Docker 会根据命令中的镜像名称自动搜索并下载镜像,那么问题来了,它是去哪里搜索和下载镜像的呢?这些镜像又是谁制作的呢?
Docker 官方提供了一个专门管理、存储镜像的网站,并对外开放了镜像上传、下载的权利。Docker 官方提供了一些基础镜像,然后各大软件公司又在基础镜像基础上,制作了自家软件的镜像,全部都存放在这个网站。这个网站就成了 Docker 镜像交流的社区:https://hub.docker.com/。
基本上我们常用的各种软件都能在这个网站上找到,我们甚至可以自己制作镜像上传上去。
像这种提供存储、管理 Docker 镜像的服务器,被称为 DockerRegistry,可以翻译为镜像仓库。DockerHub 网站是官方仓库,阿里云、华为云会提供一些第三方仓库,我们也可以自己搭建私有的镜像仓库。
官方仓库在国外,下载速度较慢,一般我们都会使用第三方仓库提供的镜像加速功能,提高下载速度。而企业内部的机密项目,往往会采用私有镜像仓库。
总之,镜像的来源有两种:
- 直接去 DockerRegistry 下载
- 基于官方基础镜像自己制作
总结一下:
Docker 本身包含一个后台服务,我们可以利用 Docker 命令告诉 Docker 服务,帮助我们快速部署指定的应用。Docker 服务部署应用时,首先要去搜索并下载应用对应的镜像,然后根据镜像创建并允许容器,应用就部署完成了。
命令解读
利用 Docker 快速的安装了 MySQL,非常的方便,不过我们执行的命令到底是什么意思呢?
docker run -d \--name mysql \-p 3306:3306 \-e TZ=Asia/Shanghai \-e MYSQL_ROOT_PASSWORD=123 \mysql
docker run -d
:创建并运行一个容器,-d
则是让容器以后台进程运行--name mysql
: 给容器起个名字叫 mysql,具有唯一性,不同容器名称不能一样-p 3306:3306
: 设置端口映射- 容器是隔离环境,外界不可访问。但是可以将宿主机端口映射到容器内的端口,当访问宿主机指定端口时,就是在访问容器内的端口了。
- 容器内端口往往是由容器内的进程决定,例如 MySQL 进程默认端口是 3306,因此容器内端口一定是 3306;而宿主机端口则可以任意指定,一般与容器内保持一致。
- 格式:
-p 宿主机端口:容器内端口
,示例中就是将宿主机的 3306 映射到容器内的 3306 端口
-e TZ=Asia/Shanghai
: 配置容器内进程运行时的一些参数- 格式:
-e KEY=VALUE
,KEY 和 VALUE 都由容器内进程决定 - 案例中,
TZ=Asia/Shanghai
是设置时区;MYSQL_ROOT_PASSWORD=123
是设置 MySQL 默认密码
- 格式:
mysql
: 设置镜像名称,Docker 会根据这个名字搜索并下载镜像- 格式:
REPOSITORY:TAG
,例如mysql:8.0
,其中REPOSITORY
可以理解为镜像名,TAG
是版本号 - 在未指定
TAG
的情况下,默认是最新版本,也就是mysql:latest
- 格式:
镜像的名称不是随意的,而是要到 DockerRegistry 中寻找,镜像运行时的配置也不是随意的,要参考镜像的帮助文档,这些在 DockerHub 网站或者软件的官方网站中都能找到。
如果我们要安装其它软件,也可以到 DockerRegistry 中寻找对应的镜像名称和版本,阅读相关配置即可。
Docker常见命令
接下来,我们一起来学习 Docker 使用的一些基础知识,为将来部署项目打下基础。具体用法可以参考 Docker 官方文档:https://docs.docker.com/
首先我们来学习 Docker 中的常见命令,可以参考官方文档:https://docs.docker.com/engine/reference/commandline/cli/
其中,比较常见的命令有:
命令 | 说明 | 文档地址 |
---|---|---|
docker pull | 拉取镜像 | docker pull |
docker push | 推送镜像到DockerRegistry | docker push |
docker images | 查看本地镜像 | docker images |
docker rmi | 删除本地镜像 | docker rmi |
docker run | 创建并运行容器(不能重复创建) | docker run |
docker stop | 停止指定容器 | docker stop |
docker start | 启动指定容器 | docker start |
docker restart | 重新启动容器 | docker restart |
docker rm | 删除指定容器 | docker rm |
docker ps | 查看容器 | docker ps |
docker logs | 查看容器运行日志 | docker logs |
docker exec | 进入容器 | docker exec |
docker save | 保存镜像到本地压缩文件 | docker save |
docker load | 加载本地压缩文件到镜像 | docker load |
docker inspect | 查看容器详细信息 | docker inspect |
用一副图来表示这些命令的关系:
默认情况下,每次重启虚拟机我们都需要手动启动 Docker 和 Docker 中的容器。我们可以通过命令来实现开机自启:
# Docker开机自启
systemctl enable docker# Docker容器开机自启
docker update --restart=always [容器名/容器id]
接下来,我们以 Nginx 为例来演示一下上述命令。
-
在 DockerHub 中搜索 Nginx 镜像,查看镜像的名称
-
拉取 Nginx 镜像
# 不指定版本, 默认最新版本 docker pull nginx
-
查看本地镜像列表
# 会显示镜像名称、版本、唯一ID、创建时间、大小 docker images
-
如果不知道一个命令怎么用,可以使用
--help
查看用法 -
保存镜像到本地
# 指定保存名称、镜像名称以及版本 docker save -o nginx.tar nginx:latest
-
删除镜像
docker rmi nginx:latest
-
加载本地镜像
-
创建并运行 Nginx 容器
docker run -d --name nginx -p 80:80 nginx
-
查看容器
有点复杂# 将其格式化,只输出指定内容 docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
# 查看所有容器, 包括运行的和没运行的 docker ps -a
-
停止容器
docker stop nginx
-
再次启动容器
docker start nginx
-
进入 Nginx 容器
# bash:以命令行方式进入 docker exec -it nginx bash
-
进入 mysql 容器
docker exec -it mysql mysql -uroot -p
-
退出容器:
exit
-
删除容器
# 运行中的容器无法删除 docker rm nginx
# 加上 -f 可以强制删除 docker rm -f nginx
-
查看容器日志
docker logs nginx
在调试时可以加上
-f
参数,一直查看容器日志docker logs -f nginx
给命令起别名
有时候,我们需要给一些常用的 Docker 命令起别名,方便我们的操作。
具体步骤如下:
# 修改 /root/.bashrc 文件
vim /root/.bashrc 或者 vim ~/.bashrc
进入该文件后,在已有别名后面添加下面这两个别名,alias 表示别名,等号左边为别名,右边为原始命令:
alias dps='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"'
alias dis='docker images'
然后,执行下面的命令使别名生效:
source /root/.bashrc 或者 source ~/.bashrc
数据卷
容器是隔离环境,容器内程序的文件、配置、运行时产生的容器都在容器内部,我们要读写容器内的文件非常不方便。大家思考几个问题:
- 如果要升级 MySQL 版本,需要销毁旧容器,那么数据岂不是跟着被销毁了?
- MySQL、Nginx 容器运行后,如果我要修改其中的某些配置该怎么办?
- 我想要让 Nginx 代理我的静态资源怎么办?
因此,容器提供程序的运行环境,但是程序运行产生的数据、程序运行依赖的配置都应该与容器解耦。
什么是数据卷
数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。
以 Nginx 为例,我们知道 Nginx 中有两个关键的目录:
- html:放置一些静态资源
- conf:放置配置文件
如果我们要让 Nginx 代理我们的静态资源,最好是放到 html 目录;如果我们要修改 Nginx 的配置,最好是找到 conf 下的 nginx.conf 文件。
但遗憾的是,容器运行的 Nginx 所有的文件都在容器内部。所以我们必须利用数据卷将两个目录与宿主机目录关联,方便我们操作。如图:
在上图中:
- 我们创建了两个数据卷:conf、html
- Nginx 容器内部的 conf 目录和 html 目录分别与两个数据卷关联。
- 而数据卷 conf 和 html 分别指向了宿主机的
/var/lib/docker/volumes/conf/_data
目录和/var/lib/docker/volumes/html/_data
目录
这样一来,容器内的 conf 和 html 目录就与宿主机的 conf 和 html 目录关联起来,我们称为挂载。此时,我们操作宿主机的 /var/lib/docker/volumes/html/_data
就是在操作容器内的 /usr/share/nginx/html/_data
目录。只要我们将静态资源放入宿主机对应目录,就可以被 Nginx 代理了。
/var/lib/docker/volumes
这个目录就是默认的存放所有容器数据卷的目录,其下再根据数据卷名称创建新目录,格式为/数据卷名/_data
。
为什么不让容器目录直接指向宿主机目录呢?
- 因为直接指向宿主机目录就与宿主机强耦合了,如果切换了环境,宿主机目录就可能发生改变了。由于容器一旦创建,目录挂载就无法修改,这样容器就无法正常工作了。
- 但是容器指向数据卷,一个逻辑名称,而数据卷再指向宿主机目录,就不存在强耦合。如果宿主机目录发生改变,只要改变数据卷与宿主机目录之间的映射关系即可。
数据卷命令
命令 | 说明 | 文档地址 |
---|---|---|
docker volume create | 创建数据卷 | docker volume create |
docker volume ls | 查看所有数据卷 | docker volume ls |
docker volume rm | 删除指定数据卷 | docker volume rm |
docker volume inspect | 查看某个数据卷的详情 | docker volume inspect |
docker volume prune | 清除数据卷 | docker volume prune |
注意:容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据卷会自动创建。
- 在执行
docker run
命令时,使用-v 数据卷名称:容器内目录
即可完成数据卷的挂载 - 容器内的目录可以从容器的使用文档中获得,比如我们想将静态资源挂载到 nginx,那么就必须知道其 html 文件夹的目录,我们可以在 docker hub 中搜索 nginx 并查看其文档:
下面演示一下 nginx 的 html 目录挂载:
# 1.首先创建容器并指定数据卷,注意通过 -v 参数来指定数据卷
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx# 2.然后查看数据卷
docker volume ls
# 结果
DRIVER VOLUME NAME
local 29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f
local html# 3.查看数据卷详情
docker volume inspect html
# 结果
[{"CreatedAt": "2024-05-17T19:57:08+08:00","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/html/_data","Name": "html","Options": null,"Scope": "local"}
]# 4.查看/var/lib/docker/volumes/html/_data目录
ll /var/lib/docker/volumes/html/_data
# 可以看到与nginx的html目录内容一样,结果如下:
总用量 8
-rw-r--r--. 1 root root 497 12月 28 2021 50x.html
-rw-r--r--. 1 root root 615 12月 28 2021 index.html
然后,我们先看一下现在 nginx 的页面,在浏览器输入虚拟机的 ip,后面加上 :80
也可以不加,回车即可看到:
下面我们来到宿主机的目录下修改一下这个页面:
# 5.进入该目录,并随意修改index.html内容
cd /var/lib/docker/volumes/html/_data
vim index.html
再次查看页面:
# 6.进入容器内部,查看/usr/share/nginx/html目录内的文件是否变化
docker exec -it nginx bashcd /usr/share/nginx/htmlcat index.html
我们在执行 docker volume ls
查看所有数据卷的时候,会发现本来就有一个名字特别长的数据卷,这个数据卷是怎么来的呢?
其实,这个是 MySQL 容器创建时自动创建的匿名数据卷 。
我们用 docker inspect mysql
来查看 mysql 容器的详情:
在 Config 的 Volumes 下可以发现这个容器声明了一个本地目录,需要挂载数据卷,但是数据卷未定义,这就是匿名卷。
在查看 Mounts 部分,可以发现,其中有几个关键属性:
Name
:数据卷名称。由于定义容器未设置容器名,这里的就是匿名卷自动生成的名字,一串 hash 值。Source
:宿主机目录Destination
: 容器内的目录
上述配置是将容器内的 /var/lib/mysql
这个目录,与数据卷 29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f
挂载。于是在宿主机中就有了 /var/lib/docker/volumes/29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f/_data
这个目录。这就是匿名数据卷对应的目录,其使用方式与普通数据卷没有差别。
挂载本地目录或文件
我们可以发现,数据卷的目录结构较深,如果我们去操作数据卷目录会不太方便。在很多情况下,我们会直接将容器目录与宿主机指定目录挂载,而不是挂载在数据卷。挂载语法与数据卷类似:
# 挂载本地目录
-v 本地目录:容器内目录
# 挂载本地文件
-v 本地文件:容器内文件
注意:本地目录或文件必须以 /
或 ./
开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。
-v mysql:/var/lib/mysql # 会被识别为一个数据卷叫mysql,运行时会自动创建这个数据卷
-v ./mysql:/var/lib/mysql # 会被识别为当前目录下的mysql目录,运行时如果不存在会创建目录
案例:删除并重新创建 mysql 容器,并完成本地目录挂载:
- 挂载
/root/mysql/data
到容器内的/var/lib/mysql
目录 - 挂载
/root/mysql/init
到容器内的/docker-entrypoint-initdb.d
目录(初始化的 SQL 脚本目录) - 挂载
/root/mysql/conf
到容器内的/etc/mysql/conf.d
目录(这个是 MySQL 配置文件目录)
首先,在宿主机创建相应目录:
cd ~ # 回到根目录mkdir mysqlcd mysqlmkdir datamkdir initmkdir conf
然后将资料中的 init 和 conf 文件夹复制到宿主机中:
现在 data 下还是没有数据的,我们删除原来的 mysql 容器,然后重新创建:
记得先回到根目录,不然会直接在当前目录新建 mysql 文件夹:
docker run -d \--name mysql \-p 3306:3306 \-e TZ=Asia/Shanghai \-e MYSQL_ROOT_PASSWORD=123 \-v ./mysql/data:/var/lib/mysql \-v ./mysql/conf:/etc/mysql/conf.d \-v ./mysql/init:/docker-entrypoint-initdb.d \mysql
可以看到已经有数据了。