问题:
Docker 解决:

这样打包好的应用包中,既包含应用本身,也保护应用所需要的Libs、Deps,无需再操作系统上安装这些,自然就不存在不同应用之间的兼容问题了
Docker如何解决大型项目依赖关系复杂,不同组件依赖的兼容性问题?
Docker如何解决开发、测试、生产环境有差异的问题?
Docker是一个快速交付应用、运行应用的技术,具备下列优势:
Docker 中的一些概念
镜像(Image):Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像
容器(Container):镜像中的应用程序运行后形成的进程就是容器,只是Docker会给容器进程做隔离,对外不可见

DockerHub:DockerHub 是一个官方的 Docker 镜像的托管平台。这样的平台称为 Docker Registry

Docker 是一个 CS 架构的程序,由两部分组成:

首先来看下镜像的名称组成
常见的镜像命令如下图所示:

Tip:利用 docker xx --help 命令查看相关命令语法
常见容器命令如下图所示:

容器保护三个状态:
查看容器日志的命令:
查看容器状态:
案例:创建并运行一个容器
创建并运行nginx容器的命令:
docker run --name mn1 -p 80:80 -d nginx
命令解读:
我们还可以进入容器进入修改相关文件(了解)
docker exec -it mn1 bash
命令解读:
在之前的 nginx 案例中,修改 nginx 的 html 页面时,需要进入 nginx 内部。并且因为没有编辑器,修改文件也很麻烦。这就是因为容器与数据(容器内文件)耦合带来的后果

要解决这个问题,必须将数据与容器解耦,这就要用到数据卷了
实现数据与容器分离的方式:

接下来我们使用三种方式进行使用:
绑定文件夹:
我们首先在我们的宿主机下创建一个文件,此时该文件下为空目录,如下所示:

然后我们使用绑定文件夹的方式运行容器,如下所示:
docker run \
--name mn1 \
-d \
-p 82:80 \
-v /tmp/nginx/html:/usr/share/nginx/html \
nginx
然后我们访问,如下所示:

此时我们发现 403 Forbidden ,WHY???
这是因为我们使用绑定文件夹方式的话,数据是以宿主机的文件夹内容为主
当我们在宿主机下添加一个 index.html 后,我们再次进行访问,如下所示


绑定文件:
绑定文件的方式与绑定文件夹的方式类似,不过我们在编写命令时将对应的文件夹改为文件,如下所示:
docker run \
--name mn1 \
-d \
-p 83:80 \
-v /tmp/nginx/html/index.html:/usr/share/nginx/html/index.html \
nginx
这里依然是以宿主机的文件内容为主
绑定数据卷:🔥🔥🔥
**数据卷(volume)**是一个虚拟目录,指向宿主机文件系统中的某个目录

一旦完成数据卷挂载,对容器的一切操作都会作用在数据卷对应的宿主机目录了
这样,我们操作宿主机的 /var/lib/docker/volumes/html 目录,就等于操作容器的 /usr/share/nginx/html 目录了
数据卷操作的基本语法如下:
docker volume [COMMAND]
docker volume 命令是数据卷操作,根据命令后跟随的 command 来确定下一步的操作:
**案例:**给 nginx 挂载数据卷
docker volume create html
docker volume ls

docker volume inspect html

我们创建的 html 这个数据卷关联的宿主机目录为/var/lib/docker/volumes/html/_data
目录
并且此时该文件下的内容为空

docker run \
--name mn2 \
-d \
-p 83:80 \
-v html:/usr/share/nginx/html
nginx
然后我们访问即可,此时数据是以容器内的为主,如下所示:

然后我们再查看数据卷目录,如下所示,会发现多了 index.html 和 50x.html 两个文件


通过上述案例可以实现了容器与数据分离
总结:
docker run 的命令中通过 -v 参数挂载文件或目录到容器中:
数据卷挂载与目录直接挂载的
镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。
我们以 MySQL 为例,来看看镜像的组成结构:

简单来说,镜像就是在系统函数库、运行环境基础上,添加应用程序文件、配置文件、依赖文件等组合,然后编写好启动脚本打包在一起形成的文件
我们要构建镜像,其实就是实现上述打包的过程
构建自定义的镜像时,并不需要一个个文件去拷贝,打包。
我们只需要告诉 Docker,我们的镜像的组成,需要哪些 BaseImage、需要拷贝什么文件、需要安装什么依赖、启动脚本是什么,将来 Docker 会帮助我们构建镜像。
而描述上述信息的文件就是Dockerfile文件。
Dockerfile 就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer。
这里给出一些常见的的指令,更多指令可去官网查看

官网地址:https://docs.docker.com/engine/reference/builder
这里先给出我们的项目文件,如下所示:

Dockerfile 文件如下所示:
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar# 安装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 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
将上述文件上传到虚拟机目录下,然后进入 docker-demo 目录下,运行命令:
docker build -t javaweb:1.0 .

可以发现我们的镜像多了两个,然后我们将该镜像运行即可,输入以下命令:
docker run \
--name javaweb1.0 \
-d \
-p 8090:8090 \
javaweb:1.0

然后访问 http://192.168.80.128:8090/hello/count 即可,访问成功
此时我们的项目文件如下所示:

我们的 Dockerfile 如下所示:
# 指定基础镜像
FROM java:8-alpine
# 拷贝 java 项目的包
COPY ./docker-demo.jar /tmp/app.jar
# 暴露端口
EXPOSE 8090
# 入口,java 项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
然后把文件拷贝到 虚拟机目录下,然后构建镜像

然后我们将镜像运行即可,这种方式是我们常见的一种部署方式
更多知识在我的语雀知识库:https://www.yuque.com/ambition-bcpii/muziteng