DockerFile 的基础讲解

一:DockerFile的介绍

1:Dockerfile是什么

Dockerfile是一个创建镜像所有命令的文本文件, 包含了一条条指令和说明, 每条指令构建一层, 通过docker build命令,根据Dockerfile的内容构建镜像,因此每一条指令的内容, 就是描述该层如何构建.有了Dockefile, 就可以制定自己的docker镜像规则,只需要在Dockerfile上添加或者修改指令, 就可生成docker 镜像。也就是说,我们使用docker pull是拉取别人弄好的,而Dockerfile是可以制作自己想要的类型。

2:dockerfile解决了什么问题

Dockerfile 包含了镜像制作的完整操作流程,其他开发者可以通过 Dockerfile 了解并复现制作过程 Dockerfile 中的每一条指令都会创建新的镜像层,这些镜像可以被 Docker Daemon 缓存。再次制作镜像时,Docker 会尽量复用缓存的镜像层(using cache),而不是重新逐层构建,这样可以节省时间和磁盘空间。Dockerfile 的操作流程可以通过docker image history [镜像名称]查询,方便开发者查看变更记。

3:Dockerfile 的关键字

FROM 设置镜像使用的基础镜像
MAINTAINER 设置镜像的作者
RUN 编译镜像时运行的脚步
CMD 设置容器的启动命令
LABEL 设置镜像标签
EXPOSE 设置镜像暴露的端口
ENV 设置容器的环境变量
ADD 编译镜像时复制上下文中文件到镜像中
COPY 编译镜像时复制上下文中文件到镜像中
ENTRYPOINT 设置容器的入口程序
VOLUME 设置容器的挂载卷
USER 设置运行 RUN CMD ENTRYPOINT的用户名
WORKDIR 设置 RUN CMD ENTRYPOINT COPY ADD 指令的工作目录
ARG 设置编译镜像时加入的参数
ONBUILD 设置镜像的ONBUILD 指令
STOPSIGNAL 设置容器的退出信号量


EXPOSE指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应该就会开启这个端口的服务。在Dockerfile中写入这样的声明有两个好处:
是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;
在运行是使随机端口映射时,也就是docker run -P(大写)时,会自动随机映射EXPOSE端口。

copy:复制文件,相当于linux命令中的cp命令;功能类似ADD,但是是不会自动解压文件,也不能访问网络资源

ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget。

CMD:构建镜像后调用,也就是在容器启动时才进行调用。写一次dockerfile只能出现一次CMD,而出现CMD的地方,就属于结尾,如果下面有RUN指令,则都不执行。

二:实战讲解

1:最基本的语法

        在下面我们创建了个go语言的文件,设置了两个环境,加上了作者,以及设置了标签:hello。我们在这个镜像中跑代码:RUN,运行后面的代码。以及暴露端口80。最后使用CMD结尾,这个CMD中先是写了入口函数./app,以及后面加入了两个参数。然后写完之后,通过build构建项目,指定项目名称以及项目位置,最后启动。

FROM golang:1.18
ENV env1=env1value
ENV env2=env2value
MAINTAINER xiaoxin
LABEL hello 1.0.0
RUN git clone https://gitee.com/nickdemo/helloworld.git
WORKDIR helloworld
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
EXPOSE 80
CMD ["./app","--param1=p1","--param2=p2"]
docker build  -t hello:1.0.0 -f Dockerfile .
docker run -p 80:80 -d --name hello hello:1.0.0

2:多阶段构建以及ADD与COPY

多阶段构建

Docker 17.05版本以后,新增了Dockerfile多阶段构建。所谓多阶段构建,实际上是允许一个Dockerfile中出现多个 FROM 指令。这样做有什么意义呢?

多个 FROM 指令的意义多个 FROM 指令并不是为了生成多根的层关系,最后生成的镜像,仍以最后一条 FROM 为准,之前的FROM 会被抛弃,那么之前的FROM 又有什么意义呢?

每一条 FROM 指令都是一个构建阶段,多条 FROM 就是多阶段构建,虽然最后生成的镜像只能是最后一个阶段的结果,但是,能够将前置阶段中的文件拷贝到后边的阶段中,这就是多阶段构建的最大意义。

最大的使用场景是将编译环境和运行环境分离,比如,之前我们需要构建一个Go语言程序,那么就需要用到go命令等编译环境。

FROM golang:1.18 as stage0            #as 指定别名
ADD ./helloworld /go/src/helloworld/
WORKDIR /go/src/helloworld
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .


FROM alpine:latest
ENV env1=env1value
ENV env2=env2value
MAINTAINER nick
LABEL hello 1.0.0
WORKDIR /app/
COPY --from=stage0 /go/src/helloworld/app ./
EXPOSE 80
CMD ["./app","--param1=p1","--param2=p2"]

ADD与COPY

对于目录而言,COPY 和 ADD 命令具有相同的特点:只复制目录中的内容而不包含目录自身。

COPY 区别于ADD在于Dockerfile中使用multi-stage

ADD 命令除了不能用在 multistage 的场景下,ADD 命令可以完成 COPY 命令的所有功能,并且还可以完成两类的功能:
解压压缩文件并把它们添加到镜像中,对于宿主机本地压缩文件,ADD命令会自动解压并添加到镜像
从 url 拷贝文件到镜像中,需要注意:url 所在文件如果是压缩包,ADD 命令不会自动解压缩

FROM golang:1.18 as stage0

#下面的copy和add都可以
# ADD ./helloworld /go/src/helloworld/
COPY ./helloworld /go/src/helloworld/

WORKDIR /go/src/helloworld
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .

FROM alpine:latest
ENV env1=env1value
ENV env2=env2value
MAINTAINER nick
LABEL hello 1.0.0

#ADD从网页中的gz文件,不会自动解压和Copy一样
ADD https://nginx.org/download/nginx-1.21.6.tar.gz /soft/
COPY nginx-1.21.6.tar.gz /soft/copy/

# ADD可以自动解压压缩文件,除了从网页中获取。
ADD nginx-1.21.6.tar.gz /soft/add/

WORKDIR /app/

#copy可以在多层级中使用,而ADD不可以
COPY --from=stage0 /go/src/helloworld/app ./
EXPOSE 80
CMD ["./app","--param1=p1","--param2=p2"]

3:CMD 与 ENTRYPOINT

CMD

1. CMD 指令提供容器运行时的默认值,这些默认值可以是一条指令,也可以是一些参数。
2. 一个dockerfile中可以有多条CMD指令,但只有最后一条CMD指令有效。
3. CMD参数格式是在CMD指令与ENTRYPOINT指令配合时使用,CMD指令中的参数会添加到ENTRYPOINT指令中。
4. 使用shell 和exec 格式时,命令在容器中的运行方式与RUN 指令相同。不同在于,RUN指令在构建镜像时执行命令,并生成新的镜像。
5. CMD指令在构建镜像时并不执行任何命令,而是在容器启动时默认将CMD指令作为第一条执行的命令。如果在命令行界面运行docker run 命令时指定命令参数,则会覆盖CMD指令中的命令

# shell 格式
CMD <command>
# exec格式,推荐格式
CMD ["executable","param1","param2"]
# 为ENTRYPOINT 指令提供参数
CMD ["param1","param2"]

ENTRYPOINT

 shell 格式
ENTRYPOINT <command>
# exec 格式,推荐格式
ENTRYPOINT ["executable","param1","param2"]

1. ENTRYPOINT指令和CMD指令类似,都可以让容器每次启动时执行相同的命令,但它们之间又有不同。一个Dockerfile中可以有多条ENTRYPOINT指令,但只有最后一条ENTRYPOINT指令有效。
2. 当使用shell格式时,ENTRYPOINT指令会忽略任何CMD指令和docker run 命令的参数,并且会运行在bin/sh -c中。
3. 推荐使用exec格式,使用此格式,docker run 传入的命令参数将会覆盖CMD指令的内容并且附加到ENTRYPOINT指令的参数中。
4. CMD可以是参数,也可以是指令,ENTRYPOINT只能是命令;docker run 命令提供的运行命令参数可以覆盖CMD,但不能覆盖ENTRYPOINT。
5. 可以通过docker run --entrypoint 替换容器的入口程序

ROM golang:1.18 as stage0
ADD ./helloworld /go/src/helloworld/
WORKDIR /go/src/helloworld
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
FROM alpine:latest
ENV env1=env1value
ENV env2=env2value
MAINTAINER nick
LABEL hello 1.0.0
WORKDIR /app/
COPY --from=stage0 /go/src/helloworld/app ./
EXPOSE 80
ENTRYPOINT ["./app"]
CMD ["--param1=p1","--param2=p2"]
docker build -t hello:1.0.0 .
# 指定启动参数
docker run -d -p 80:80 hello:1.0.0  --param1=1 --param2=2
# 指定入口程序为sh
docker run -dit -p 80:80 --entrypoint sh  hello:1.0.0

4:target与cache-from

        对于多阶段构建,可以通过--target指定需要重新构建的阶段。--cache-from 可以指定一个镜像作为缓存源,当构建过程中dockerfile指令与缓存镜像源指令匹配,则直接使用缓存镜像中的镜像层,从而加快构建进程。可以将缓存镜像推送到远程注册中心,提供给不同的构建过程使用,在使用前需要先pull到本地。

FROM golang:1.18 as s0
ADD ./helloworld /go/src/helloworld/
WORKDIR /go/src/helloworld
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .

FROM alpine:latest as s1
ENV env1=env1value
ENV env2=env2value
MAINTAINER nick
LABEL hello 1.0.0
WORKDIR /app
COPY --from=s0 /go/src/helloworld/app ./
EXPOSE 80
ENTRYPOINT ["./app","--param1=p1","--param2=p2"]

docker build -t prehello:1.0.0 --target s0 .


docker build -t hello:1.0.0 --cache-from prehello:1.0.0 --target s1 .

5:onbuild

        onbuild指令将指令添加到镜像中,当镜像作为另一个构建的基础镜像时,将触发这些指令执行。触发指令将在下游构建的上下文中执行。注意:onbuild指令不会影响当前构建,但会影响下游构建 。

FROM golang:1.18
ONBUILD ADD ./helloworld /go/src/helloworld/
ONBUILD WORKDIR /go/src/helloworld
ONBUILD RUN go env -w 
GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
ONBUILD RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
docker build -t mygolang:1.0.0  .
FROM mygolang:1.0.0 as s0
  
FROM alpine:latest as s1
ENV env1=env1value
ENV env2=env2value
MAINTAINER nick
LABEL hello 1.0.0
WORKDIR /app
COPY --from=s0 /go/src/helloworld/app ./
EXPOSE 80
ENTRYPOINT ["./app","--param1=p1","--param2=p2"]
docker build -t hello:1.0.0 .

本篇主要讲解了Dockerfile的基础知识,谢谢大家的观看。https://github.com/0voice

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值