接下来,我们要利用Docker部署一个应用程序
我们拿一个Java应用程序为例
我们将SpringBooot打包为一个jar包,并上传到服务器上,打包为一个Docker镜像,并运行起来
我们编写一个SpringBoot,尝试连接Redis进行一些操作
首先就需要我们启动一个Redis
首先是拉取一个Redis的镜像
docker pull redis
拉取完成之后,对于Redis的启动
,需要考虑Redis的持久化问题
上面文字中说明了,我们可以利用-v 进行挂载,讲宿主机上的目录和镜像中的 /data进行映射就可以进行显示
所以我们的启动时候可以加入-v
docker run -d –name myredis -v /redisdata:/data
而且如果我们想要使用自定义的配置文件,需要考虑两个方面
分别是启动命令 以及 配置文件的挂在
$ docker run -v /myredis/conf:/usr/local/etc/redis –name myredis redis redis-server /usr/local/etc/redis/redis.conf
上面是官方给出的配置文件使用方式
redis redis-server /usr/local/etc/redis/redis.conf即为启动命令
我们可以利用-v挂载一个文件,并在启动命令中指定
我们先创建一个redis.conf
然后-v中进行挂载
-v /data/redis.conf:/etc/redis/redis.conf
然后在启动中制定
redis redis-server /etc/redis/redis.conf
docker run -d –name myredis -v /redisdata:/data -v /data/redis.conf:/etc/redis/redis.conf -p 6379:6379 redis:latest redis-server /etc/redis/redis.conf
使用如上命令,我们启动了一个redis
然后我们启动一个相关的Java应用,并将Java应用进行打包部署
关于Java代码的书写就先跳过不表
假设我们已经有了一个Jar包
我们需要将这个Jar包转换为对应的镜像,这就需要一个新的概念,DockerFile
我们将对应的DockerFile进行书写,并利用Docker进行打包,那么我们就讲解如何书写DockerFile
首先是DockerFile的基础层
因为我们需要一个运行环境,对于Java,我们需要使用一个JDK运行环境
于是我们从DockerHub查找对应的JDK运行环境
对应的JDK环境为openjdk:8-jdk-slim
故首先在DockerFile的第一行书写上
FROM openjdk:8-jdk-slim
然后我们讲这个jar包拷贝到这个容器环境中
使用的命令是
COPY target/*.jar /app.jar
将当前目录下的target目录下的jar包,拷贝为容器环境中的根目录下的app.jar
之后是设置启动命令
ENTRYPOINT [“java”,”-jar”,”/app.jar”]
每一个空格都用逗号分隔
之后就是docker build
整体命令为
docker build -t java-demo:v1.0 .
最后别忘了这个点,为了表明上下文环境为当前的目录
之后就可以启动这个容器来查看了
docker run -d -p 8080:8080 –name myjava-app java-demo:v1.0
关于镜像的上传和分享其实并不困难了
docker login
然后进行改名
docker tag oldname newname
推送到docker hub
docker push newname
其他的机器就可以
docker pull newname
从而进行使用
关于DocekrFile的具体使用,我们展开说说
首先是关于From指令,是一个必要的指令,指定了基础镜像,推荐是使用
apline或者slim这类的小镜像,比如tomcat
其次是选择的镜像要配合应用的环境,Java应用要使用java基础镜像或者tomcat基础镜像
其次是LABEL
用于给镜像打标签
可以给一个镜像打上多个标签
中间使用空格就可以了
诸如
如果需要换行,直接空格加上反斜杠即可
之后我们讲一下ARG 和 ENV两个参数
ARG会定义一个变量,也可以在构建的时候使用–build-arg进行传递,docker build 会传递给构建器
–build-arg会覆盖DockerFile中的同名参数
不给过ARG只会在构建期有效,运行期无效
而且书写的时候不支持同时指定多个
只能一次指定一个
ARG parma=123456
ARG msg=456789
–build-arg也是
之后是ENV命令
用于声明环境变量
推荐使用KEY=VALUE,不推荐使用 KEY Value这种格式
负责给容器运行的时候使用
docker run –env 可以覆盖这些值
ENV为了给容器运行时使用,可以使用docker inspect image查看
需要注意个问题,关于ENV的持久化问题
如果两个ENV变量
ENV msg=ffff
ENV msg2=$msg
那么如果在启动的时候制定了msg为dddd,那么运行的时候环境变量
msg为dddd,msg2为ffff
这是因为,build的时候ENV会生成层,也就是固化,导致的运行时不改变
之后我们说下Run
Run可以配合上面的ARG
在当前的镜像层顶层执行任何命令,并提交结果,生成新的镜像层
可以使用多个RUN命令,来创建不同的镜像层
常见的方式有两种
RUN command
RUN [“exec”,”param1″]
两种是有一定的区别
RUN /bin/bash -c ‘source $HOME/ .bashrc;echo $HOME’
RUN [“/bin/bash”,”-c”,”echo hello”]
记住如果使用[],是不能输出任何变量信息的,直接使用
RUN command,可以输出变量信息
RUN没有上下文联系
CMD和ENTRYPOINT
都是可以作为容器启动的入口
首先是CMD命令
CMD [“exec”,”param1″,”param2″] exec方式
CMD [“param1″,”param2”] 为ENTRYPOINT提供默认参数
CMD command param1 param2 shell形式
只能有一个CMD命令
DockerFile中只有一个CMD指令,如果列出多个CMD,只有最后一个可以执行
CMD主要目的视为执行的容器提供默认值,这种情况下,还必须要制定ENTRYPOINT指令
ADD和COPY
都是将文件加入到镜像中
不过ADD会将远程地址的文件自动下载到镜像中
而且ADD会将压缩包在镜像中解压出来
如果是远程压缩包,并不会自动解压
别忘了ADD后的镜像内路径,如果想放在某个文件夹下,需要在最后加个/
之后是两个目录相关的命令,分别是WORKDIR和VOLUME
对于WORKDIR,是为之后的指令,诸如RUN CMD ENTRYPOINT COPY ADD指令设置一个上下文目录,如果在容器中不存在这个目录,也会被自动的创建
WORKDIR /app
RUN pwd
发现会是 /app
而且会嵌套使用,比如我们如下的使用
WORKDIR /a
WORKDIR b
WORKDIR c
结果是 /a/b/c
关于Volume
主要是讲容器内的某些文件夹映射到容器的外部
常见的写法
VOLUME [“/var/log/”]
VOLUME /var/log
VOLUME /var/log /var/db
但是需要注意一些坑,如果进行了指定VOLUME,但是启动的时候没有指定-v,那么也会在启动之后,挂载对应的卷到一个宿主机上的地方,这是其一
如果在DockerFile的Volume原语后进行了对容器挂载卷的修改,那么所有的修改都不会生效,这是其二
如果修改了Volume相关挂载卷中的文件了,那么即使之后Commit,也不会保存修改
对于DockerFile中的EXPOSE来说
用于对外暴露端口,但是只是一个声明,建议还是在run的时候配合-p指令
如果声明了一个,是会在启动的时候挂载这些随机的端口,但并没有什么用
书写方式如下
EXPOSE <port>
EXPOSE [80,443]
EXPOSE 80/tcp
EXPOSE 80/udp
最重要的士ENTRYPOINT 和 CMD
一个类似是门一样的角色,门是不会变得 Entrypoint
一个类似是口令一样的角色,口令会是变得 CMD
而且CMD和ENTRYPOINT都是只有一个会生效,定义在最后的才会生效
两个配合使用才是最强
基本配合的图标如下所示
一般我们都是使用[]这种的写法
由CMD负责提供参数,由ENTRYPOINT负责实际的执行
就好比 java -jar xxx.jar param
ENTRYPOINT负责执行javar -jar xxx.jar 后面的param
而且CMD得命令还会被docker run 时候传入的arg覆盖比如下面的操作
docker run xxxx 的话,执行的指令就是echo 111
docker run xxxx arg 就是 echo arg
这就是上面两点的配合使用
还有就是多阶段构建的概念
multi-stage builds
进行多阶段构建,每一次的构建基于前一个阶段构建的成果
我们的使用可以如下
首先第一步,构建一个jar包,我们需要使用maven,进行构建
分别是基于maven 镜像
将目录下的java文件拷贝进镜像中,然后进行maven打包
然后我们基于打包好的镜像,在进行一次打包
将上一阶段的jar包拷贝到新的镜像中
–from指的是根据什么镜像,我们基于了上面的builder镜像
进行了COPY
我们还是指定了openjdk的运行环境
然后进行运行/app下的jar包
对于DockerFile的使用和打包
我们给出以下的建议
选项的基础镜像可以相对小的
然后是合并RUN的指令,将多个RUN命令合成一个RUN命令,少生成一些层
对于RUN过程中产生的临时缓存,可以自行删除
RUN mvn….. && rm -rf xxxx
合理使用 .dockerignoe文件,排除上下文中无需构建的资源
必要刻意使用缓存,如果不需要缓存可以使用–no-cache