目录
前言
-
Docker是用以项目上线部署的工具
-
Docker并不会很难,只要你跟着将所有的命令敲一遍、将项目部署流程走一遍就行
-
我会从6个方面详细展示在生产环节中Docker的使用。帮助你在最短的时间内完成理论 + 实践 + 巩固的学习
【扩展阅读】在学习Docker遇到困难时,推荐去了解了其他同学们的笔记,你将会受益匪浅。
史上最详细的Docker 镜像的制作-上传-拉取--部署(阿里云)_制作镜像的时候,如何知道需要拷贝哪些依赖库-CSDN博客
Docker入门:镜像分层概念简述_docker镜像分层-CSDN博客
一、实验环境准备
简单交代一下,实验操作环境为:centos7 + finalShell远程工具
1.1 安装Docker
1.卸载旧版
首先卸载系统中已经存在旧的Docker,保存实验环境的干净:
bash
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine \
docker-selinux
2.配置Docker的yum库
安装yum工具
bash
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
配置Docker的yum源:
bash
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
更新yum,建立缓存
bash
sudo yum makecache fast
3.安装Docker
bash
yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
看到**完毕!**才证明安装过程没有出错
4.启动和校验
bash
# 启动Docker
systemctl start docker
# 停止Docker
systemctl stop docker
# 重启
systemctl restart docker
# 设置开机自启
systemctl enable docker
# 执行docker ps命令,如果不报错,说明安装启动成功
docker ps
1.2 配置可用的Docker镜像源
当前镜像截至2024.10.29 测试任然有效
bash
# 创建目录
mkdir -p /etc/docker
# 复制内容,当前镜像截至2024.10.29 测试任然有效
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.1panel.dev",
"https://docker.fxxk.dedyn.io",
"https://docker.xn--6oq72ry9d5zx.cn",
"https://docker.m.daocloud.io",
"https://a.ussh.net",
"https://docker.zhai.cm"]
}
EOF
# 重新加载配置
systemctl daemon-reload
# 重启Docker
systemctl restart docker
1.3 部署MySQL,测试容器可行性
1. 运行安装命令
bash
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
mysql
2. 测试MySQL连接
显示连接成功了
1.4 Docker的镜像、容器与镜像仓库
对于我们上面安装的MySQL软件,使用Docker安装只是输入了一堆指令,然后Docker就开始给我们框框下载,具体工作流程如何呢?
事实上,了解docker的都知道,我们刚才做的事就是从远程的docker仓库中将MySQL文件给拉取下来了。我们会把类似MySQL的软件称之为镜像。镜像不仅包含了软件本身,还包含了软件运行所需要的各种环境。
而且正因为拉取了软件运行的完全体环境,使用docker镜像可以屏蔽操作系统的差异性,不同主机间的差异性。
另外可以留意到,Docker还给MySQL软件创建了一个容器,**这个容器拥有独立的资源。你当然可以把它理解成又一台的虚拟机。**由此,MySQL的运行环境隔离起来。
1.5 Docker安装容器软件的命令解读
对于我们刚刚输入的MySQL安装命令:
bash
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;而宿主机端口则可以任意指定,一般与容器内保持一致。
总结:外部可以直接访问docker虚拟机,但容器是隔离的无法访问。而docker可以通过端口映射访问其内置的容器,于是乎形成一条访问链:外部访问docker端口,端口映射到相关容器,于是乎我们就连上了MySQL软件
格式:
-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
二、Docker常见命令
2.1 命令介绍
建议结合图片来理解Docker生产过程中常用到的命令:
- docker pull ------拉取远程镜像到本地服务器中
- docker push ------将本地服务器镜像创建提交到远程镜像仓库中
- docker build ------打包自定义的镜像保存到本地服务器
- docker save ------将镜像打包压缩,存放到本地中
- docker load ------将镜像包拉取到本地服务器
- docker images ------查看本地服务器的镜像
- docker rmi ------删除本地服务器的镜像
- docker run ------创建并运行容器
- docker stop ------停止但不销毁容器
- docker start ------启动但不创建容器
- docker ps ------查看容器状态
- docker rm ------销毁容器
- docker logs ------查看容器日志情况
- docker exec ------进入容器内部【类似配置界面中】
- ......
2.2 命令实践
镜像相关的命令:
容器相关命令
实验完整命令
bash
# 第1步,去DockerHub查看nginx镜像仓库及相关信息
# 第2步,拉取Nginx镜像
docker pull nginx
# 第3步,查看镜像
docker images
# 结果如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 16 months ago 141MB
mysql latest 3218b38490ce 17 months ago 516MB
# 第4步,创建并允许Nginx容器
docker run -d --name nginx -p 80:80 nginx
# 第5步,查看运行中容器
docker ps
# 也可以加格式化方式访问,格式会更加清爽
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
# 第6步,访问网页,地址:http://虚拟机地址
# 第7步,停止容器
docker stop nginx
# 第8步,查看所有容器
docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
# 第9步,再次启动nginx容器
docker start nginx
# 第10步,再次查看容器
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
# 第11步,查看容器详细信息
docker inspect nginx
# 第12步,进入容器,查看容器内目录
docker exec -it nginx bash
# 或者,可以进入MySQL
docker exec -it mysql mysql -uroot -p
# 第13步,删除容器
docker rm nginx
# 发现无法删除,因为容器运行中,强制删除容器
docker rm -f nginx
三、Docker数据卷
3.1 数据卷的功能介绍
【问题导向】既然容器可以部署应用,那就必然会涉及到修改、添加应用数据、资源的情况,现在我们尝试使用容器内置的系统进行nginx静态资源的修改,却发现了容器并没有给我们安装vi编辑器等工具。也就是在容器系统中,想要修改资源、数据是困难的,如何解决这个问题,成为我们学习Docker数据卷相关知识的动力。
【是什么】数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。
【原理 】通过数据卷,实现数据双向绑定
【优势】在宿主机系统中改文件资源还不是轻轻松松、手到擒来呀!
注意事项:
/var/lib/docker/volumes
这个目录就是默认的存放所有容器数据卷的目录,其下再根据数据卷名称创建新目录,格式为/数据卷名/_data
。为什么不让容器目录直接指向 宿主机 目录呢?
因为直接指向宿主机目录就与宿主机强耦合了,如果切换了环境,宿主机目录就可能发生改变了。由于容器一旦创建,目录挂载就无法修改,这样容器就无法正常工作了。
但是容器指向数据卷,一个逻辑名称,而数据卷再指向宿主机目录,就不存在强耦合。如果宿主机目录发生改变,只要改变数据卷与宿主机目录之间的映射关系即可。
3.2 数据卷的创建
相关命令
命令 | 说明 | 文档地址 |
---|---|---|
docker volume create | 创建数据卷 | docker volume create |
docker volume ls | 查看所有数据卷 | docs.docker.com |
docker volume rm | 删除指定数据卷 | docs.docker.com |
docker volume inspect | 查看某个数据卷的详情 | docs.docker.com |
docker volume prune | 清除数据卷 | docker volume prune |
命令实践
【提示】
- 在执行docker run命令时,使用 -v 数据卷:容器内目录 可以完成数据卷挂载(也就是说一开始已经创建的容器需要删除,需要再重新创建的过程中指定卷挂载)
- 当创建容器时,如果挂载了数据卷且数据卷不存在,会自动创建数据卷
【基础命令】创建挂载数据卷、查看数据卷详情、查看宿主机的数据卷绑定目录
【修改测试】在宿主机中修改资源内容,观察网页变化:
3.3 MySQL容器的数据挂载实践
我们并没有创建mysql相关的数据卷,但是还是出现了。这种卷就叫做匿名卷。用于数据存储
匿名卷的名字太长了,所以最好还是在创建的时候我们主动的进行数据挂载
【查看数据库】
【完整项目指令】
# 1.删除原来的MySQL容器
docker rm -f mysql
# 2.进入root目录
cd ~
# 3.创建并运行新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
# 4.查看root目录,可以发现~/mysql/data目录已经自动创建好了
ls -l mysql
# 结果:
总用量 4
drwxr-xr-x. 2 root root 20 5月 19 15:11 conf
drwxr-xr-x. 7 polkitd root 4096 5月 19 15:11 data
drwxr-xr-x. 2 root root 23 5月 19 15:11 init
# 查看data目录,会发现里面有大量数据库数据,说明数据库完成了初始化
ls -l data
# 5.查看MySQL容器内数据
# 5.1.进入MySQL
docker exec -it mysql mysql -uroot -p123
# 5.2.查看编码表
show variables like "%char%";
# 6.查看数据
# 6.1.查看数据库
show databases;
5 rows in set (0.00 sec)
# 6.2.切换到hmall数据库
use hmall;
# 6.3.查看表
show tables;
四、Docker自定义镜像
到此为止,我们前面的小实验都是直接拉取的别人做好的镜像。不过在一些特定的公式需求中,现有的Docker镜像可能无法满足,或者是存在隐患。这个时候就需要我们自己制作一个自己的镜像。那么我们要如何制作自己的镜像呢?这一节我们来看看吧。
4.1 了解镜像结构
要想自己构建镜像,必须先了解镜像的结构。
镜像之所以能让我们快速跨操作系统部署应用而忽略其运行环境、配置,就是因为镜像中包含了程序运行需要的系统函数库、环境、配置、依赖。
自定义镜像本质就是依次准备好程序运行的基础环境、依赖、应用本身、运行配置等文件,并且打包而成。
因此,我们制作一个镜像通常都会考虑几方面。
**底层的:**运行环境,也称基础镜像,通常是由Linux等相关操作系统制作而成
**中间层:**软件,这一部分通常是项目的配置、安装包、依赖等相关的资源
**顶层:**镜像运行入口,这一部分则是启动镜像项目的一些脚本,常见的java项目的java -jar等等
此外,镜像结构一般都是分层的(如上图),其中的设计优点如下:
资源共享,方便复制迁移,容易实现资源复用。正因为分层,假设有一个镜像被很多其他的镜像所使用,这时候我们只需要准备一份,进行共享就可以实现功能。既减少了资源的重复拷贝,还提高了制作镜像的效率。
4.2 如何构建?DockerFile来也
听完对镜像的描述,你可能还在感慨这制作镜像还是很难啊!没关系,只要学习了DockerFile之后,你就能掌握无痛制作镜像的秘诀。
Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。 由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以Docker就提供了自动打包镜像的功能。**我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,将来Docker可以根据Dockerfile帮我们构建镜像。**常见指令如下:
指令 | 说明 | 示例 |
---|---|---|
FROM | 指定基础镜像 | FROM centos:6 |
ENV | 设置环境变量,可在后面指令使用 | ENV key value |
COPY | 拷贝本地文件到镜像的指定目录 | COPY ./xx.jar /tmp/app.jar |
RUN | 执行Linux的shell命令,一般是安装过程的命令 | RUN yum install gcc |
EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | EXPOSE 8080 |
ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | ENTRYPOINT java -jar xx.jar |
【案例】:基于Ubuntu制作一个Java项目的镜像:
bash
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录、容器内时区
ENV JAVA_DIR=/usr/local
ENV TZ=Asia/Shanghai
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 设定时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装JDK
RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 指定项目监听的端口
EXPOSE 8080
# 入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]
然而上述镜像操作还是太复杂啦,仔细观察,其实基础镜像部分、安装目录、jdk版本之类的大众镜像层我们可以进一步去封装,最后只需要考虑拷贝jar包即可完成镜像的制作:
【运行DockerFile】编写好了Dockerfile后如何交由Docker运行呢?
了解Docker build命令
是不是看起来制作镜像简单了起来,那接下来我们来尝试制作一下镜像吧!
4.3 镜像制作实践
1. 上传制作镜像的相关文件
2.制作镜像,使用docker-build
3. 测试镜像是否正常
五、Docker网络相关
受限于容器之间相互隔离、虚拟网桥等机制,我们很难做到让容器之间保持稳定的相互访问。但是我们通常部署的应用软件之间需要做到相互通信。例如java项目与数据库项目的相互通信等等,对此我们需要学习容器网络相关的内容,了解容器之间是如何进行通信的。
5.1 Docker网络结构
【原理结构】默认情况下,所有容器都是以bridge方式连接到Docker的一个虚拟网桥上:
容器之间是否能相互访问呢?我们马上来做个小测试看看:
【小测试】现在我们有两个启动的容器,查看它们的IP地址,并尝试是否可以正常访问彼此
docker ps 查看容器
docker inspect 查看容器详情
docker exec + ping 测试ping状态
【结论 】诶?这不是正常访问到了么?那不是没什么问题嘛?------------------仔细想想,**现在的IP地址是不是Docker网桥自动分配的?自动分配的IP固然好,但是输在不稳定。每当我们项目容器进行了重启,其IP地址都有可能改变,这时原先配置好的容器访问配置又不生效了。**就像学习Linux虚拟机的时候,ip不固定是不是每次远程之前都还要修改一下IP,哈哈一个道理,所以我们还得进行配置没解决这个问题。
5.2 自定义网络:稳定的容器访问
为了解决IP地址变化引起的容器间不稳定的访问,docker提供了自定义网络的功能,只要确保所有的容器都在统一网络下,我们就可以采用绑定容器名的方式去访问容器。因为容器名是不可变的。
docker网络的相关命令
|---------------------------|--------------|-----------------------------------------------------------------------------------------------------------------------------------|
| docker network create | 创建一个网络 | docker network create |
| docker network ls | 查看所有网络 | docs.docker.com |
| docker network rm | 删除指定网络 | docs.docker.com |
| docker network prune | 清除未使用的网络 | docs.docker.com |
| docker network connect | 使指定容器连接加入某网络 | docs.docker.com |
| docker network disconnect | 使指定容器连接离开某网络 | docker network disconnect |
| docker network inspect | 查看网络详细信息 | docker network inspect |
【命令测试】
六、Docker项目部署实践
到此为止,你已经把Docker的核心精华内容给牢牢掌握了,接下来就是检验你学习成果的时候。在本节,你需要使用Docker部署一个真实的项目,去体会Docker部署过程中的便捷与快速。
【任务目标】本次实验需要你想办法部署Java程序和前端程序,并实现访问Docker容器内部的MySQL服务器中的hmall数据库。
6.1 部署后端Java项目
- 检查Java配置环境,确认上线mysql的连接参数
- 编写Dockerfile文件用于镜像制作
- 将后端项目进行打包,将生成的jar包 和 dockerfile文件一并上传到Linux服务器上
- 使用docker build 命令创建镜像
- 检查端口占用情况,排除占据8080端口的容器
- 创建容器、指定网段、运行容器
- 将mysql容器也加入到zhicong自定义网络
- 使用命令 docker logs -f docker-hm 查看启动日志
- 访问网页、数据库测试
6.2 部署前端项目
【任务需求】创建一个全新的nginx容器,将准备好的nginx.conf、html目录与容器进行挂载绑定,然后实现前端项目的部署。
- 查看nginx.conf文件,注意几个关键配置
- 上传文件到服务器中
- 参考官网挂载nginx.conf文件的方法,配置nginx容器的创建命令
bash
docker run -d \
--name nginx \
-p 18080:18080 \
-p 18081:18081 \
-v /root/nginx/html:/usr/share/nginx/html \
-v /root/nginx/nginx.conf:/etc/nginx/nginx.conf \
--network zhicong \
nginx
- 查看容器是否正常运行
- 前端页面测试
6.3 前后端联调测试
使用docker logs -f docker-hm 命令打开后端控制台,前端发送一个登录请求,观察日志输出
6.4 整体自动部署优化:DockerCompose【章鱼哥部署】
呼,舒一口气。进行到这里的你已经太棒啦!!你已经顺利的完成了Docker的学习,并手把手的部署了一个简易的项目。不过你应该也发现了,手动部署项目是一件工作量非常大的事情。部署前端、部署后端、部署数据库....每一个容器都要去部署,整个项目好像被割裂开来一样。所以,本节我介绍一个用于整体化自动部署的工具------章鱼哥给你,希望能帮助你减轻部署项目的工作量。
【介绍DockerCompose 】Docker Compose就可以帮助我们实现多个相互关联的Docker容器的快速部署。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器。
章鱼哥的学习网站: https://docs.docker.com/reference/compose-file/legacy-versions/
【基本语法】
docker compose [OPTIONS] [COMMAND]
其中,OPTIONS和COMMAND都是可选参数,比较常见的有:
类型 | 参数或指令 | 说明 |
---|---|---|
Options | -f | 指定compose文件的路径和名称 |
Options | -p | 指定project名称。project就是当前compose文件中设置的多个service的集合,是逻辑概念 |
Commands | up | 创建并启动所有service容器 |
Commands | down | 停止并移除所有容器、网络 |
Commands | ps | 列出所有启动的容器 |
Commands | logs | 查看指定容器的日志 |
Commands | stop | 停止容器 |
Commands | start | 启动容器 |
Commands | restart | 重启容器 |
Commands | top | 查看运行的进程 |
Commands | exec | 在指定的运行中容器中执行命令 |
【使用DockerCompose】
对比如下:
docker run 参数 | docker compose 指令 | 说明 |
---|---|---|
--name | container_name | 容器名称 |
-p | ports | 端口映射 |
-e | environment | 环境变量 |
-v | volumes | 数据卷配置 |
--network | networks | 网络 |
【部署】使用Docker部署很简单,将原先的所有容器全部删除,然后导入docker-compose.yml文件,使用docker compose 命令进行一键部署!
至此,你对Docker的这门技术已经掌握啦!完结,赶快尝试去部署你最近写的项目吧!
七、Docker知识追问强化
-
什么是Docker?Docker用来做什么的?
-
什么是镜像?什么是容器?什么是镜像仓库?
-
请你描述Docker部署软件的一般性流程?
-
Docker的优点是什么?
-
为何要配置端口映射?
-
请你谈谈Docker run 命令的参数及其含义?
-
谈谈容器相关的命令有哪些?
-
什么是数据卷?为什么要使用数据卷?
-
如何挂载数据卷?
-
数据卷常见的命令有那些?
-
构建一个自定义镜像的基本步骤?
-
为什么镜像结构是分层的?有什么样的好处?
-
DockerFile是用来做什么的?都有哪些常用的命令?
-
构建镜像的命令是什么?
-
简单描述制作镜像的流程
-
docker如何解决容器之间的相互访问问题?