太长不读版: 案例地址:https://github.com/gholly/docker-scaffold.git
1. Dockerfile是什么?
Dockerfile是Docker用来构建镜像的文本文件,包含自定义的指令和格式。可以通过docker build命令从Dockerfile中构建镜像.
2. 镜像构建过程
Dockerfile描述了组装镜像的步骤,其中每条指令都是单独执行的。除了FROM指令,其他每一条指令都会在上一条指令所生成镜像的基础上执行,执行完后会生成一个新的镜像层,新的镜像层覆盖原来的镜像之上从而形成了新的镜像,Dockerfile所生成的最终镜像就是在基础镜像上面叠加一层层的镜像层组建的。
3. Dockerfile指令
在Dockerfile中,指令(INSTRUMENT)不区分大小写,但是为了与参数区分,推荐为大写。Docker会顺序执行Dockerfile中的指令,第一条指令必须为FROM指令,它用于制定构建镜像的基础镜像。在Dockerfile中以#开头的行为注释,而在其他位置的#会被当成参数。
指令的格式如下:
# comments
INSTRUMENT argument
Dockerfile的指令有FROM,MAINTAINER,RUN,CMD,EXPOSE,ENV,ADD,COPY,ENTRYPOINT,VOLUMN,USER,WORKDIR,ONBUILD等
- ENV
格式: ENV <key> <value> 或 ENV <key>=<value>
ENV 指令可以为镜像创建出来的容器声明环境变量,并且在Dockerfile文件,ENV指令声明的环境变量会被后面的指定指令(即ENV,add,copy,workdir,expose,volume,user)解释使用。其他指令使用环境变量时,使用格式为$variable_name 或${variable_name}.在变量前下\可以转义,如$foo或者${foo},都会被转成$foo 和${foo},而不是环境变量所保存的值。另外,ONBUILD指令不支持环境替换。
- FROM
格式: FROM <image> 或 ENV <image>:<tag>
FROM指令的功能是为后面的指令提供基础镜像,因此一个有效的Dockerfile必须以FROM指令作为第一条非注释指令。基础镜像可以选取任何有效的镜像。在一个dockerfile文件中,From指令可以出现多次,这样会构建多个镜像。在每一个镜像创建完成后,docker命令行会输出该镜像的ID。若from指令中tag参数为空,则tag默认为lastest;若参数image或tag指定的镜像不存在,则返回错误。
从公共镜像库拉取镜像很容易?example中的镜像来源是?
- COPY
格式: COPY <src> <dest>
COPY指令复制<src>所指向的文件或目录,将它添加到新镜像中,复制的文件或目录在镜像中的路径是<dest>.
- ADD
格式: ADD <src> <dest>
add和copy指令功能相似,都支持复制本地文件到镜像的功能,但add指令还支持其他功能。<src>可以是一个指向一个网络文件的url,<dest>指向一个目录,则url必须是完全路径,这样可以获取该网络文件的filename.
ADD http://example.com/foofile / #会创建文件/foofile
<src>还可以指向一个本地压缩归档文件,该文件在复制到容器中时会被解压提取,如:
ADD example.tar.xz / #则创建example文件
但若网络文件url中的文件是压缩文件,则不会被解压提取。 ADD和copy指令虽然功能相似,推荐使用copy,因为copy只支持本地文件,相比add更透明。
- RUN
格式:
RUN <command> #shell格式
RUN ["executable","param1","param2"] #exec格式,推荐格式
RUN指令会在前一条命令创建出的镜像的基础上创建一个容器,并在容器中运行命令,在命令结束后提交容器为新镜像,新镜像被dockerfie中的下一条指令使用。
当使用exec格式时,命令是直接运行的,容器不调用shell 程序,即容器中没有shell程序。exec格式中的参数会被当成json数组被docker解析,所以要使用双引号。若希望运行shell程序,指令需要写成这样 CMD [ "sh", "-c", "echo" , "$HOME"]
- CMD
格式:
CMD <command> #shell格式
CMD ["executable","param1","param2"]#exec格式,推荐格式
CMD [param1","param2"]
CMD指令提供容器运行时的默认值,这些默认值可以为一条指令,也可以是参数。一个dockerfie文件中可以有多个cmd指令,只有最后一条生效。
CMD指令在构建镜像时不执行任何指令,而是在容器启动时默认将cmd的指令作为第一条执行的命令。如果docker run命令时指定了命令参数,则会覆盖cmd指令中的命令。
- ENTRYPOINT
格式:
ENTRYPOINT <command> #shell格式
ENTRYPOINT ["executable","param1","param2"]#exec格式,推荐格式
ENTRYPOINT指令与cmd命令相似,都可以让容器在每次启动的时候执行相同的命令。最后一条ENTRYPOINT生效。
当为shell格式时,ENTRYPOINT会忽略掉任何cmd指令和docker run命令的参数,所以推荐exec格式。
使用exec格式时,docker run会覆盖cmd的内容,并且附加到ENTRYPOINT的指令的参数中。
4. 根据以上指令实践一下:尝试把一个简单的springboot项目打包成一个镜像 Dcokerfile文件
# openjdk:lastest 可从https://hub.docker.com/官方镜像仓库去查找你想要的镜像
FROM openjdk:latest
COPY ./build/libs/scaffold-1.0-SNAPSHOT.jar docker-scaffold.jar
#JAVA_OPTS 是用来设置JVM相关运行参数的变量
ENV JAVA_OPTS=""
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "docker-scaffold.jar"]
- 5.验证
docker build -f ./Dockerfile . -t scaffold
docker run scaffold #启动镜像
docker exec -it container-id sh 或者 docker exec -it container-id sh #进入到容器中
curl -i http://localhost:8080/hi
返回200,说明此时成功了。