目录

前言:我们以前是如何部署项目的?

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:6ENV  :设置环境变量COPY:拷贝本地文件到镜像的的指定目录,例:COPY  ./jdk8.tar.gz  /tmpRUN  :执行Linux的shell命令,一般就是安装过程的命令,例:RUN  tar -axvf  /tmp/jdk8.tar.gz &&  EXPORTS path=/tmp/jdk8:$pathEXPOSE:指定容器运行时监听的端口 ,是给镜像使用者看的 ,例: EXPOSE 8080ENTRYPOINT:镜像中应用的启动命令,容器运行时调用,例: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项目的容器不想让他加入默认的网络中呢?那需要我们把之前的启动的项目容器删掉,然后重新创建容器,在创建容器时就需要指定他所在的网络:

        此时,我们再来查看这个容器的信息:

就只一个这一个了~

此时,两个容器就可以一起相互访问了~ 可通过容器名,来直接访问,如下:

这时呢,我们只需要把项目的配置文件改一下:

好啦,我们重新打包上传的操作就不演示啦~

本期就结束啦!!下期见~ 

相关文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: