Docker--初识Dockerfile
Dockerfile是构建Docker镜像的脚本文件,由一系列指令构成。
通过docker build 命令构建镜像时,Dockerfile 中的指令由上到下依次执行,每条指令都会构建出一个镜像(就是镜像的分层)。因此指令越多,层次就越多,创建的镜像就越多,效率就越低。
所以在定义Dockerfile时,能在一个指令完成的动作就不要分为两条。
指令简介
指令不区分大小写,一般惯例是写为全大写
指令后至少会携带一个参数
注释以# 开头
FORM 指令,用于指定基础镜像。且必须是第一条指令;若省略了tag,则默认为latest
FORM [:]
MAINTAINER 指令的参数填写的一般是维护者的姓名和邮箱。此指令官方不建议使用,使用LABEL指令代替
MAINTAINER
#LABEL 指令:以键值对的形式包含任意镜像的元数据信息,用来代替MAINTAINER指令。通过docker inspect 可查看 LABEL 和MAINTAINER 的内容
LABEL = = = …
ENV指令:指定环境变量,这些环境变量后续可以被RUN指令使用,容器运行后,也可以在容器中获取这些环境变量
ENV
ENV = = = …
#WORKDIR指令:容器打开后默认进入的目录,一般在后续的RUN、CMD、ENTRYINT、ADD等指令中会引用该目录。
可以设置多个WORKDIR 指令,后续WORKDIR指令若使用相对路径,则会基于之前WORKDIR指令的路径。
使用docker run 运行容器时,加-w 参数可以覆盖 上面设置的工作目录。
WORKDIR path
RUN :这里的 时shell命令,在docker build 过程中,使用shell 运行指定的command
RUN
在docker build 过程中,会调用第一个参数“EXECUTABLE” 指定的程序运行,并使用后面的 参数作为运行参数
RUN [“EXECUTABLE”,“PARAM1”,“PARAM2”…]
在容器启动后,即执行完docker run 后立即执行“EXECUTABLE”指定的可执行文件,并将后面的参数作为运行参数
CMD [“EXECUTABLE”,“PARAM1”,“PARAM2”…]
command表示shell 命令,在容器启动后立即运行指定的shell命令
CMD command param1 param2 …
#提供给ENTRYPOINT 的默认参数
CMD [“PARAM1”,“[PARAM2]”,…]
在容器启动过程中,即执行完docker run 时,会执行“EXECUTABLE”指定的可执行文件,并将后面的参数作为运行参数
ENTRYPOINT [“EXECUTABLE”,“PARAM1”,“PARAM2”…]
command表示shell 命令,在容器启动过程中,会运行指定的shell命令
ENTRYPOINT command param1 param2 …
EXPOSE […]
ARG [=]
复制宿主机的文件(src)到容器中的指定目录(dest)
src可以是绝对路径,也可以是相对路径(相对路径是相对于docker build 命令所指定的路径的)
src可以是一个压缩文件,复制到容器后自动解压
src也可以是一个url。这时ADD指令相当于wget命令
src 最好不要是目录,不然会将目录中的所有内容复制到容器中
dest 是一个绝对路径,其最后的路径必须要加上斜杠,不然会将最后的目录名称当作是文件名
ADD
ADD [“”,“”] #路径中存在空格时使用双引号引起来
功能和ADD相同,但是src不能是url,若src是压缩未见,复制到容器后不能自动解压
COPY
指定当前镜像的子镜像进行构建时要执行的指令
ONBUILD [INSTRUCTION]
在容器创建可以挂载的数据卷
VOLUME [“dir1”,“dir2”,…]
指令用法(构建自己的HelloWorld镜像)
scratch 镜像
scratch 镜像是一个空镜像,是所有镜像的Base Image。
scratch 镜像只能在Dockerfile 中被继承,不能pull拉取,不能run,没有tag,并且他不会生成镜像中的文件系统层。
scratch 是一个保留字,用户不能作为自己镜像的名称。
安装编译器
由于要编写C语言。所以要安装C语言的编译器
yum install -y gcc gcc-c++
yum install -y glibc-static
创建hello.c
在宿主机创建一个hello.c 文件
#includ<stdio.h>
int main()
{
printf(“hello my docker world\n”);
return 0;
}
编译测试hello.c
gcc --statuc -o hello hello.c
./hello
创建Dockerfile
在当前目录下新建Dockerfile (vim Dockerfile ,文件名就叫Dockerfile ),内容如下:
FROM scratch
ADD hello /
CMD [“/hello”]
构建镜像
docker build -t hello-my-world .
-t :指定要生成镜像的和。若省略tag,则默认latest
最后的【.】:是一个宿主机的URL路径。构建镜像时会从该路径中查找Dockerfile文件。
此时执行docker images 可以看到自己创建的镜像。
然后可以运行这个镜像了:docker run hello-my-world
为经常重新打标签
当进行过出新版本了,上个版本的镜像标签就不能是tag了。
docker tag 命令 可以对镜像重打标签。重打标签实际是复制了一份镜像,将新镜像指定新的tag。新镜像的IMageID和Digest 和原镜像的相同。
docker tag hello-my-world hello-my-world:1.0
CMD与ENTRYPOINT
这两个指令都是用于指定容器启动时要执行的命令,无论哪个指令,每个Dockerfile中只能有一个CMD/ENTRYPOINT 指令,多个指令只会执行最后一个。
不同点如下:
CMD指定的是容器启动时默认的命令,即docker run 若指定了要运行的命令,则Dockerfile 中的CMD指定的命令时不会执行的。
而ENTRYPOINT 指定的是容器启动时一定会执行的命令。
CMD 例子
创建Dockerfile,在dfs目录中新建文件Dockerfile2,其内容如下:
FROM centos:7
CMD cal
然后构建镜像
docker build -f ./Dockerfile2 -t mycal .
-f :指定构建时要使用的Dockerfile文件(当文件名称不是默认的Dockerfile时才需要指定)
然后运行就会显示当前月份的日历
docker run -it mycal
此时若在docker run 时指定要执行的命令,则Dockerfile中CMD 指定的命令就不执行了
无标题
此时也无法为CMD指定的命令设置选项
无2标题
如果说Dockerfile 的内容如下(CMD指令的另一种形式),也是一样的效果,
FROM centos:7
CMD [“/bin/bash”,“-c”,“cal”]
ENTRYPOINT例子
1.创建Dockerfile,名字为Dockerfile4,其内容如下:
FROM centos:7
ENTRYPOINT cal
然后构建并运行,结果显示本月的日历
如果docker run 时指定了执行命令,ENTRYPOINT的指令依然会执行,不会被覆盖
无标3题
此时,即使在docker run中添加命令选项,也是无效的。
如果Dockerfile 的内容如下,那么在docker run中添加命令选项 是有效的。
FROM centos:7
ENTRYPOINT [“cal”]
屏幕4截图_29-5-2026_162930_
总结
CMD指定命令:启动命令docker run 中不能添加参数【arg】。
因为Dockerfile 中的CMD可以被替代,如果启动的镜像 后仍有内容,对于docker daemon来说 ,会认为是一个命令,如果有两个或两个以上,后面才会认为是参数。
ENTRYPOINT指令:启动命令docker run 中可以添加参数【arg】。
因为ENTRYPOINT 不能被替代,如果启动的镜像 后仍有内容,对于docker daemon来说,其只能是【arg】。
不过,docker daemon 对于ENTRYPOINT 指定的【command】和【“EXECUTABLE”】的处理方式不同:
【command】指定的是shell:daemon会直接运行。而不会与docker run 后的【arg】拼接,
【“EXECUTABLE”】指定的命令,daemon会先与docker run 后的【arg】拼接,然后运行拼接后的结果。
结论:无论CMD还是ENTRYPOINT ,使用[“EXECUTABLE”]的方式的通用性会更强。
ADD与COPY指令
创建一个Dockerfile,其内容如下:
FROM centos:7
WORKDIR /opt
ADD zookeeper.tar.gz /opt/add
COPY zookeeper.tar.gz /opt/copy
CMD /bin/bash
构建并运行镜像后会发现:
ADD指令添加的是解压后的目录
COPY指令添加的是未解压的。
ARG指令
该指令用于定义一个变量,该变量会在镜像构建时使用,而不是容器启动时。
创建一个Dockerfile,其内容如下:
FROM centos:7
ARG name=TOM
RUN echo $name
RUN指令用于指定在docker build时要执行的内容
使用ARG默认值构建
docker build -t myargs:1.0 .
构建时没给变量name赋予新值,所以name还是=TOM
使用ARG指定值构建
docker build -t myargs:1.0 --build-arg name=jerry .
构建时给变量name赋予新值,所以name=jerry
ONBUILD指令
ONBUILD指令 只对当前镜像的子镜像进行构建时有效。
比如下面实现的是:父镜像中没有wget命令,但是子镜像会增加。
父镜像的Dockerfile
FROM centos:7
ENV WORKPATH /usr/local
WORKDIR $WORKPATH
ONBUILD RUN yum -y install wget
CMD /bin/bash
当前镜像及其子镜像的工作目录都是/usr/local.
子镜像在进行docker build 时会运行RUN的安装命令。
构建父镜像
docker build -t parent:1.0
子镜像的Dockerfile
FROM parent:1.0
构建并运行子镜像后,就可以使用wget指令了。
构建新镜像的方式总结
docker build
docker commit
docker import (注意:docker load并没有构建出新镜像,其与原镜像是同一个镜像)
docker compose
docker hub 中完成Automated Builds
将Springboot项目部署到Docker
准备应用
新建一个名称为hello-docker的简单SpringBoot项目。
POM文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
4.0.0
org.springframework.boot
spring-boot-starter-parent
4.0.6
com.ali
hello-docker
0.0.1-SNAPSHOT
hello-docker
hello-docker
<java.version>17</java.version>
org.springframework.boot
spring-boot-starter-web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
其配置文件application.yml内容如下:
logging:
pattern:
console: level-%-5level - %msg%n
Controller类如下:
package com.ali.hellodocker.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SomeController {
@GetMapping("/hello")
public String hello() {
System.out.println("================hello========================");
return "Hello Docker!";
}
}
然后打成jar包
发布应用
在宿主机上创建一个专门的目录,用来存放jar包和Dockerfile 等内容。
mkdir /root/hello-docker
然后将jar包上传到这个目录
创建Dockerfile
FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/openjdk:17
MAINTAINER zhangsan zs@163.com
LABEL version=“1.0” description=“my own app”
COPY hello-docker-0.0.1-SNAPSHOT.jar hd.jar
ENTRYPOINT [“java”,“-jar”,“hd.jar”]
EXPOSE 9000
然后构建并运行镜像
docker build -t hello-docker:1.0 .
docker run --name myhd -dp 9000:8080 hello-docker:1.0
这时就可以通过ip:9000/hello访问了
无标4题
可以通过docker log命令查看输出日志
无标5题
更多推荐



所有评论(0)