目录
前言:我们以前是如何部署项目的?
1、镜像由哪几部分构成的
2、如何手动自定义一个镜像
2.1、Dockerfile
2.2、dockerfile文本文件中,最终要写什么?
2.3、构建镜像
3、案例:部署java项目
4、如何与其他容器相互访问,例如:java项目镜像创建的容器与mysql容器相互访问
4.1、使用默认的网络
4.1、网络相关命令
4.3、创建新的网络
前言:我们以前是如何部署项目的?
这个我在这篇文章中,有做说明,刚兴趣的小伙伴,可以去看看:http://t.csdnimg.cn/KPu7o
另外,是来学习的伙伴们,需要自己准备一个java项目,并准备好他的jar包~
1、镜像由哪几部分构成的
传统的部署项目,大致有以下几个步骤:
- 准备一个Linux服务器
- 安装jdk并配置环境变量
- 拷贝jar包【关于数据库,我们后面会单独说】
- 运行jar包
看到这些步骤,我们就要回顾一下,镜像是什么了?
镜像就是包含了应用程序、程序运行的系统函数库、运行配置等文件的文件包。那我们构建镜像其实就是上述这些文件打包的过程~
到这里,就理解了,我们接下来,要构建的镜像就会包含以下几个方面:
有一个Linux运行环境【镜像自己内部准备一个运行环境,那就不用担心系统不兼容等问题了】、有安装jre并配置环境变量、有拷贝jar包、并将运行jar包设置为一个启动脚本文件。这个文件糅合在一起,构成了一个我们的java应用镜像~
那我们一起来看看,他到底是怎么去糅合在一起的呢:
因为我们搞一个什么运行环境,整一个系统函数库【因为我们不知道这个项目需要依赖哪些系统函数库,所以我们直接就把整个库都搬过来】,这一堆文件;而我们整个jre,再去配置环境变量和配置也是一堆文件;jar包也是个文件;运行脚本还是一个文件。那docker呢,就将这些个文件都进行分别压缩,最后这些压缩包合并在一起构成最终的一个镜像。因此镜像其实就是由很多个压缩包合并而成的,在Docker中,他们被称为LER,也就是层的意思。【我们其实在拉取镜像的时候,也会看到,他会打印几行日志,其实这一行就是对应了一层~】
我们看图理解:
Docker为什么要把这些文件分别分层打包呢?
- 可以实现某些层的共享
例如:我们大部分镜像的第一层都是基础镜像【应用依赖的系统函数库、环境、配置、文件等】,我们上面说的是不知道要用哪些系统函数库,所以我们全部下载下来。那如果说,有一个大佬,把JRE所依赖的网络函数全部单独挑出来了,那这样的话,就可以大大的缩小镜像的体积。这样一来,就可以实现层的共享了~
- 提升本地下载镜像的速度
我们在本地拉取镜像时,按层一层一层拉取,如果说,第一个镜像拉取下来后,拉取第二个镜像时,他和第一层的某几层相同,那我们是不是就可以直接跳过,不用拉取这个层了,直接使用你本地的这个就可以了。这样一来,就可以提升本地下载镜像的速度了~
2、如何手动自定义一个镜像
通过上面的了解,我们在制作镜像中,需要我们去给每一层打包,但我们真的这么操作的话,岂不是比以前部署项目还要复杂的多,就没必要了~
所以Docker中,不需要我们手动去制作镜像,我们只需要描述清楚我们的镜像结构,描述清楚这个镜像的入口是什么?中间有哪些层?基础是什么? 描述清楚这些后,Docker就可以自动帮我们完成构建镜像这个操作了~
接下来,需要我们去了解一下Dockerfile,使用Dockerfile描述镜像结构~
2.1、Dockerfile
Dockerfile就是一个文本文件,其中包含了一个个的指令,用指令来说明要执行什么操作来构建镜像。如何来书写这个文本文件呢?就需要借助他的相关指令了:
- FROM :指定基础镜像——例如,我们这里的基础镜像就是centos:6 / 7 ,例:FROM CentOS:6
- ENV :设置环境变量
- COPY:拷贝本地文件到镜像的的指定目录,例:COPY ./jdk8.tar.gz /tmp
- RUN :执行Linux的shell命令,一般就是安装过程的命令,例:RUN tar -axvf /tmp/jdk8.tar.gz && EXPORTS path=/tmp/jdk8:$path
- EXPOSE:指定容器运行时监听的端口 ,是给镜像使用者看的 ,例: EXPOSE 8080
- ENTRYPOINT:镜像中应用的启动命令,容器运行时调用,例:ENTRYPOINT java -jar xx.jar &
举例该文本文件内部到底如何下:
# 制定基础镜像
FROM centos:6
# 配置环境变量,JDK的安装目录,容器内时区
ENV JAVA_DIR=/usr/local
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./xx.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
# 入口,java项目的启动命令
ENTRYPOINT ["java","-jar","/app.jar"]
说明:
这个文件写完后,等我们下次再要制作新的java项目的镜像时,需要更改的内容有哪些呢:
我们需要修改的,可能就只有这个待拷贝的java的jar包不同,那我们是不是可以对这个文本文件再优化~
2.2、dockerfile文本文件中,最终要写什么?
上述我们已经看到了,文本文件内大致要写的内容,我们现在要做的是,可不可以继续优化一下:
我们提到,文本文件中,每次要修改的只有拷贝jar包时,命令要稍微改一下,那思考一下,前面我们把基础镜像从拷贝全部的系统库函数到写一个镜像,只把我们要使用的库提出来,那在这里我们也可以这样做,我们把上述的基础镜像、拷jdk包、安装jdk,配置环境变量等操作,也可以做成一个镜像,供我们后续使用,例如已经有人做好的:
# 基础镜像
FROM openjdk:11.0-jre-buster
# 拷贝jar包
COPY xx.jar /app.jar
# 入口
ENTRYPOINT ["java","-jar","/app.jar","&"]
说明:
2.3、构建镜像
当我们编写好Dockerfile后,使用如下命令,来构建镜像,例如:
docker build -t myImage:1.0 .
说明:
- docker build -t 后面跟你给这个镜像气的名字,冒号后面为版本,不写的话,默认为最新版
- 后面的一个 . 指的是dockerfile所在的目录,当前目录就为 .
3、案例:部署java项目
首先,我们创建一个目录,为构建镜像做准备,任意命名,例如我的:
一定要进到这个目录中来~
然后,把你的java项目的jar扔到这个目录来:
然后创建一个文件,名为:Dockerfile:
打开文件,填写内容:
保存后,执行命令:docker build -t 镜像名【自定义】:
有了镜像,我们就去创建运行容器了:
然后,你的项目就可以正常与运行了~
但是,项目虽然部署好了,我们全称部署也没有提到数据库MySQL呀,那我的项目就是要用到MySQL的呀。我们前面已经运行的有mysql容器了是不是【没有的伙伴,可以看:http://t.csdnimg.cn/uB6gl】所以,下面我们需要继续学习,可以把我们让我们的容器与容器之间相互访问:
4、如何与其他容器相互访问,例如:java项目镜像创建的容器与mysql容器相互访问
在这里,就需要我们学习另一个知识点:网络~
4.1、使用默认的网络
我们在安装docker时,docker就创建一张虚拟的网卡,默认名字为docker0,并且会给这个虚拟的网卡创建一个虚拟的网桥,在我们不指定的情况下,我们创建的容器都会与默认的网卡建立连接,如下:
例如我们查看一下,我们之前的容器mysql和Nginx:
查看容器信息,输入命令:docker inspect 容器名
mysql:
Nginx:
我们会看到,他俩的网关都是默认的127.17.0.1 ; 那是不是说明,他俩就可以相互访问了呢?例,进入我们刚才部署的java项目的这个容器】:
一定要是进入我们创建的项目的容器内,进行ping操作,因为mysql容器和Nginx容器中,都没有提供ping的这个操作,安装的话,会比较麻烦~
这个时候,有伙伴们就会说,那我们就不需要配置了呗,只要在我自己的项目中访问数据库的配置信息修改一下不就好了吗?
例如:
改好后,重新部署一下不就好了吗?
不!不好!!! 为什么呢?我们想想,当我们把mysql容器停掉后,重启;或者是我们把镜像推给别人~想一想这两种情况能够保证mysql容器每次的ip都一样吗?那不一样,不就会报错了吗?
大家可能会说,可以把ip用容器名替代吗?他可以通过容器名解析到这个ip吗?
回答是:可以但不完全可以。详细的说,就是默认的这个网卡是不可以的,但是如果我们不使用默认的网卡,我们自己去创建一个网络,把这些容器加入到这个新的网络中是可以做到的。例如,我们现在在默认网卡中试试:
对吧?这是做不到的,所以我们又要学习新的知识,网络相关的:
4.1、网络相关命令
- docker network create : 创建一个网络
- docker network ls : 查看所有网络
- docker network rm : 删除指定网络
- docker network prune :清楚未使用的网络
- docker network connect :使指定容器连接加入某网络
- docker network disconnect:使指定容器连接离开某网络
- docker network inspect :查看网络详细信息
4.3、创建新的网络
先查看我们原本有哪些网络:
创建一个网络:
使mysql容器加入该网络:
我们可以看到这个mysql容器,先是创建容器时就自动加入了默认网络中,然后也加入了刚才我们指定的网络中,在这个网络中,这个网络的网关是172.18.0.1,这个容器在这个网络中的ip为172.18.0.2
如果说我们的java项目的容器不想让他加入默认的网络中呢?那需要我们把之前的启动的项目容器删掉,然后重新创建容器,在创建容器时就需要指定他所在的网络:
此时,我们再来查看这个容器的信息:
就只一个这一个了~
此时,两个容器就可以一起相互访问了~ 可通过容器名,来直接访问,如下:
这时呢,我们只需要把项目的配置文件改一下:
好啦,我们重新打包上传的操作就不演示啦~
本期就结束啦!!下期见~