Dockerfile 是一个文本文件,其内包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。我们一般会使用Dockerfile 文件来定制镜像。我们知道通过docker commit
可以提交一个镜像,其实也是在原有镜像的基础上定制新的镜像,docker commit
提交镜像的好处就是可以直接启动一个容器,在容器内执行各种操作非常方便,例如我们可以灵活的使用各种linux命令,可以在容器里安装jdk、maven等,操作完成之后再将这个容器提交成一个镜像,那么以这个镜像去启动的容器就有我们安装的这些环境了;但实际中我们应该慎用docker commit
来定制镜像,原因就是使用 docker commit
意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体的操作。这种黑箱镜像的维护工作是非常痛苦的。但是使用DockerFile来构建镜像的好处是可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之后我们想要知道某个镜像是如何构建的,就可以通过查看Dockerfile文件,一目了然。
DockerFile常用指令
- FROM:指定基础镜像,表示我们新构建的镜像是基于哪个镜像构建的,例如可以是jdk、centos;还可以是最基础的镜像scratch,这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
- MAINTAINER:指定镜像的作者,一般写明作者+邮箱
- ENV:设置环境变量,一般多用来设置我们的路径,例如设置工作目录环境变量
ENV mypath /usr/local
- WORKDIR:指定镜像的工作目录,也就是当基于该镜像启动一个容器,我们进入容器默认就会进到我们设置的这个工作目录,如果没有指定工作目录的话,那么默认就是根目录/,例如我们指定
WORKDIR $mypath
,那么工作目录就是/usr/local - ADD:将文件添加到我们构建的docker镜像中
- COPY:功能类似于ADD,可以拷贝文件到镜像中
- RUN:指定镜像构建时运行的命令,例如我们可以指定镜像构建的时候去yum安装一些yum源,例如
RUN yum -y intall vim
- EXPOSE:暴露端口,如果我们在构建镜像的时候暴露了端口,就不用在每次docker run的时候加上-p选项进行端口映射
- VOLUME:指定挂载的目录,同样,如果我们在构建镜像的时候指定挂载的目录,就不用在每次docker run的时候加上-v选项进行目录挂载了,需要注意的是,以这种方式去挂载目录,无法指定宿主机目录,只能指定容器内目录,例如:VOLUME ["/root/user1","/root/user2"],该命令是挂载了容器内两个目录,但是宿主机的目录无法指定,如果我们要指定宿主机目录,还得通过docker run指定-v参数的方式
- CMD:指定容器启动时运行的命令,也就是docker run的时候会执行的命令
- ENTYRPOINT:功能类似于CMD,也是指定容器启动时运行的命令
PS:CMD与ENTYRPOINT最大的区别就在于CMD只能覆盖命令,而ENTYRPOINT可以追加命令,例如我们指定CMD ["ls","-a"]
,该命令表示docker run启动容器时会执行这两条命令,组合起来就是 ls -a,如果我们执行命令 docker run -l 镜像名
那么会报错,我们期望的效果是容器启动的时候执行Dockerfile文件CMD命令的 ls -a命令拼接上 -l命令,也就是ls -al,但是由于CMD只能覆盖命令不能追加命令,所以最终启动容器的时候执行的命令仅仅是 -l ,这是一条不存在的命令,如果我们要达到我们期望的效果,可以将CMD命令改成ETRYPOIT,也就是ENTYRPOINT ["ls","-a"]
关于CMD命令:
①在Dockerfile文件里面声明多条CMD命令,只有最后一条CMD命令会执行
(例如:CMD echo “hello”;CMD echo “hi”;docker run 镜像名:标签;最终启动容器的时候只会输出hi)
②/bin/bash也是一条可执行命令,因此如果在启动容器的时候加上了这个命令,那么Dockerfile文件里的CMD命令不会执行
(例如:CMD echo “hello”;docker run -it 镜像名:标签 /bin/bash;最终启动容器的时候不会输出hello)
(例如:CMD echo “hello”;CMD /bin/bash;docker run -it 镜像名:标签;最终启动容器的时候同样不会输出hello)
使用Dockerfile文件定制镜像的步骤:
# 1. 编写一个Dockerfile文件,命名为标准命名Dockerfile
# 2. 在Dockerfile文件所在目录构建一个镜像
docker build -f Dockerfile文件所在路径 -t 镜像名:版本号 .
# 一般来说,我们都会将Dockfile文件放置在我们当前要构建镜像的这个目录,并且命名为标准命名Dockerfile,那么可以省去-f选项
例如:docker build -t mycentos:v1.1 .
# 3. 启动容器,测试镜像是否没问题
docker run -d -P 镜像名
# 4. 将我们定制的镜像发布到Docker Hub上
docker login -u 用户名 (回车,之后输入密码) # 登录我们的Docker Hub账号
docker push 镜像名:版本号
将springboot项目打包成镜像
- 我们可以在IDEA中先编写好Dockerfile文件,在这之前可以先在IDEA中安装一个Docker的插件,IDEA2020版本的好像自动带有这个插件了,这样IDEA就能识别我们的Dockerfile文件,我们编写Dockerfile文件的时候就会给我们提示,非常方便
Docker插件如下: - 将我们的springboot项目使用maven命令中的package命令打成一个jar包
- 编写Dockerfile文件,示例如下:
FROM java:8 # 指定基础镜像为jdk8
COPY *.jar /app.jar # 将当前路径下的jar包拷贝到根目录下,命名为app.jar
EXPOSE 8085 # 暴露端口8085
CMD ["--server.port=8085--"] # 启动容器时运行的命令,仅仅是起到提示用户项目端口号为8085的作用
ENTRYPOINT ["java","-jar","/app.jar"] # 启动容器时运行的命令,该命令就是启动我们的jar包
以上的Dockerfile文件只是一个示例,可以根据需要自己定制,例如上面的COPY命令,拷贝jar包也可以不用重命名,ENTRYPOINT命令指定启动jar包的命令也可以加上"nohup"配合“&”表示jar包在后台不挂断自动运行
- 将我们本地的jar包以及Dockerfile文件一并上传到安装了Docker服务的远程服务器上
- 使用docker build命令构建镜像
- 使用docker run命令启动容器,如果项目能正常启动,并且没报任何异常表示我们的docker镜像打包成功
- 可以将镜像发布到Docker Hub或者阿里云镜像仓库上,供他人使用
总结
其实现在外面的企业基本都是使用编写Dockerfile文件来定制镜像,所以对于Dockerfile文件的一些基本指令应该有所了解;对于后台开发的小伙伴,现在大多数都是最终交付一个jar包以及编写的Dockerfile文件;所以学会编写Dockerfile文件对我们后台开发的小伙伴来说是必须掌握的本领了。
文章内容总结的可能会不到位或者有写错的地方,欢迎指正! 😄