dockerfile 详解

dockerfile 详细解释

  • 本次内容是对上一篇文章的补充

博客:docker制作自己的镜像并上传dockerhub

dockerfile 内容

FROM golang:alpine AS builder

LABEL stage=gobuilder

ENV CGO_ENABLED 0
ENV GOOS linux
ENV GOPROXY https://goproxy.cn,direct

WORKDIR /build/zero

ADD go.mod .
ADD go.sum .
RUN go mod download
COPY . .
COPY service/hello/etc /app/etc
RUN go build -ldflags="-s -w" -o /app/hello service/hello/hello.go

FROM alpine

RUN apk update --no-cache && apk add --no-cache ca-certificates tzdata
ENV TZ Asia/Shanghai

WORKDIR /app
COPY --from=builder /app/hello /app/hello
COPY --from=builder /app/etc /app/etc
CMD ["./hello", "-f", "etc/hello-api.yaml"]

dockerfile 详解

#当我在/Users/myself/Golang/common_project/src/greet目录下执行 docker build -t hello:v1 -f service/hello/Dockerfile . 命令
# -f service/hello/Dockerfile 代表的事dockerfile文件的所在目录,可以是任意目录
# . 代表的是当前目录的所有文件,就是执行命令所在的目录下的文件,所以 greet目录下 的所有文件都会打包到  Docker引擎(服务端守护进程)
# 如果没有 . ,那么默认上下文路径就是 Dockerfile 所在的位置。
#所以首先会把  greet目录 打包到 守护进程,后面继续执行以下代码


#FROM <image>
#FROM <image>:<tag>
#FROM <image>@<digest>
#tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
#打包依赖阶段使用golang:alpine作为基础镜像
FROM golang:alpine AS builder

#维护者信息
MAINTAINER Dong Lei
MAINTAINER 2781897595@qq.com
MAINTAINER Dong Lei <2781897595@qq.com>

#LABEL:用于为镜像添加元数据
LABEL stage=gobuilder

#ENV:设置环境变量
ENV CGO_ENABLED 0
ENV GOOS linux
ENV GOPROXY https://goproxy.cn,direct

#WORKDIR:工作目录,类似于cd命令,进入/build/zero这个目录
WORKDIR /build/zero
#格式:
#    WORKDIR /path/to/workdir
#示例:
#    WORKDIR /a  (这时工作目录为/a)
#    WORKDIR b  (这时工作目录为/a/b)
#    WORKDIR c  (这时工作目录为/a/b/c)
#注:
#  通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUNCMDENTRYPOINTADDCOPY等命令都会在该目录下执行。在使用
#ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget
# 因为复制的上下问目录是 greet,所以  将项目目录下的
# 把docekr守护进程下的 go.mod 拷贝到  /build/zero目录下
ADD go.mod .
ADD go.sum .
RUN go mod download
#COPY:功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
# .是上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。
#解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。
#如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。
#注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢
#COPY <源路径>... <目标路径>
#COPY <src>... <dest>
#dest: 指得是镜像(image)中的路径
#src: 指得是Dockerfile所在的context路径
#那么COPY的作用就是:将构建镜像的电脑上的文件或者文件夹拷贝到镜像中去。
#我们知道,Dockerfile文件往往是放在github上的某个工程里,当我们checkout工程,然后执行 docker build 命令的时候,我们的电脑和作者的电脑肯定不一样的,所以,明白了这一点,基于这样最基本的常识,我们马上就能明白什么样的src是正确的,什么样的src是错误的:

#正确:
#COPY ./package.json /app/
#COPY package.json /usr/src/app/
#错误:
#COPY ../package.json /app 因为上一层目录大家都不一样的
#或者 COPY /opt/xxxx /app 有可能连操作系统都不一样,哪里有什么/opt这样的目录
#所以,Dockerfile中的COPY中的context(上下文)指得就是 Dockerfile 所在的工程中的目录结构,离开了这个工程的其他目录都是错误的。
#顺便说一下:dest 是可以在镜像中的任意位置的,这个无所谓,不用解释大家都明白了吧。



#COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。
#对于 COPYADD 命令来说,如果要把本地的文件拷贝到镜像中,那么本地的文件必须是在上下文目录中的文件。其实这一点很好解释,因为在执行 build 命令时,docker 客户端会把上下文中的所有文件发送给 docker daemon。考虑 docker 客户端和 docker daemon 不在同一台机器上的情况,build 命令只能从上下文中获取文件。如果我们在 Dockerfile 的 COPYADD 命令中引用了上下文中没有的文件,就会收到类似下面的错误:
#. 便是当前目录
# 如果在 Dockerfile 中这么写:
# COPY ./package.json /app/
# 这并不是要复制执行 docker build 命令所在的目录下的 package.json,也不是复制 Dockerfile 所在目录下的 package.json,而是复制 上下文(context) 目录下的 package.json。
# 因此,COPY 这类指令中的源文件的路径都是相对路径。这也是初学者经常会问的为什么 COPY ../package.json /app 或者 COPY /opt/xxxx /app 无法工作的原因,因为这些路径已经超出了上下文的范围,Docker 引擎无法获得这些位置的文件。如果真的需要那些文件,应该将它们复制到上下文目录中去。
#理解构建上下文对于镜像构建是很重要的,避免犯一些不应该的错误。比如有些初学者在发现 COPY /opt/xxxx /app 不工作后,于是干脆将 Dockerfile 放到了硬盘根目录去构建,结果发现 docker build执行后,在发送一个几十 GB 的东西,极为缓慢而且很容易构建失败。那是因为这种做法是在让 docker build 打包整个硬盘,这显然是使用错误。


# 把docekr守护进程下的所有文件 复制到 /build/zero 目录下,相当于  zero 就是 greet一样
COPY . .
#把service/hello/etc 这个文件夹 复制到 容器中 /app/etc
# 因为我是在greet 这个项目下执行的 打包命令  docker build -t hello:v1 -f service/hello/Dockerfile .
# 所以上下文就是 greet,相当于把 greet整个 拷贝到守护进程,所以
COPY service/hello/etc /app/etc
# 指定编译完成后的文件名,可以不设置使用默认的,最后一步要执行该文件名,因为service/hello/hello.go里面是mian函数编译到 /app/hello
RUN go build -ldflags="-s -w" -o /app/hello service/hello/hello.go

#通过上面的copy和RUN go 使 /app/etc 和 /app/hello 两个数据生成 ,/app/hello是编译后的文件,而不是文件夹

# 运行阶段指定scratch作为基础镜像
FROM alpine

#RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
#RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
RUN apk update --no-cache && apk add --no-cache ca-certificates tzdata
ENV TZ Asia/Shanghai

# 进去app 目录
WORKDIR /app
#COPY --from=builder将上一层镜像复制制定目录复制到当前工作目录   上一阶 通过COPYRUN go 生成的  /app/hello  复制到 /app/hello
COPY --from=builder /app/hello /app/hello
COPY --from=builder /app/etc /app/etc

# 执行结果如下
#/ # ls
#app    bin    dev    etc    home   lib    media  mnt    opt    proc   root   run    sbin   srv    sys    tmp    usr    var
#/ # cd app
#/app # ls
#etc    hello
#/app #

#CMD:构建容器后调用,也就是在容器启动时才进行调用。
#CMD不同于RUNCMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
CMD ["./hello", "-f", "etc/hello-api.yaml"]

案例1

dockerfile 文件

FROM golang:alpine AS builder

LABEL stage=gobuilder

ENV CGO_ENABLED 0
ENV GOOS linux
ENV GOPROXY https://goproxy.cn,direct

WORKDIR /build/zero
# 把docekr守护进程下的 go.mod 拷贝到  /build/zero目录下
ADD go.mod .

启动容器

luwei@luweideMacBook-Pro-2 greet % docker build -t hello:v4 -f service/hello/Dockerfile .
[+] Building 81.4s (9/9) FINISHED                                                                                                                                                                         
 => [internal] load build definition from Dockerfile                                                                                                                                                 0.1s
 => => transferring dockerfile: 6.13kB                                                                                                                                                               0.0s
 => [internal] load .dockerignore                                                                                                                                                                    0.1s
 => => transferring context: 2B                                                                                                                                                                      0.0s
 => [internal] load metadata for docker.io/library/golang:alpine                                                                                                                                    80.4s
 => [auth] library/golang:pull token for registry-1.docker.io                                                                                                                                        0.0s
 => [internal] load build context                                                                                                                                                                    0.1s
 => => transferring context: 27B                                                                                                                                                                     0.0s
 => [1/3] FROM docker.io/library/golang:alpine@sha256:55da409cc0fe11df63a7d6962fbefd1321fedc305d9969da636876893e289e2d                                                                               0.0s
 => CACHED [2/3] WORKDIR /build/zero                                                                                                                                                                 0.0s
 => CACHED [3/3] ADD go.mod .                                                                                                                                                                        0.0s
 => exporting to image                                                                                                                                                                               0.1s
 => => exporting layers                                                                                                                                                                              0.0s
 => => writing image sha256:b1298754a175d735d9e8d767e025c0b4ccf8ee1f65b78bd6af8a091b4f36a1b5                                                                                                         0.0s
 => => naming to docker.io/library/hello:v4                                                                                                                                                          0.0s
luwei@luweideMacBook-Pro-2 greet % 

查看

luwei@luweideMacBook-Pro-2 greet % docker images
REPOSITORY         TAG        IMAGE ID       CREATED         SIZE
hello              v4         b1298754a175   42 hours ago    315MB

启动容器

可以看到 go.mod被复制到容器 /build/zero 中

luwei@luweideMacBook-Pro-2 greet % docker run -t -i hello:v4          
/build/zero # ls
go.mod
/build/zero # cd go.mod
/bin/sh: cd: can't cd to go.mod: Not a directory

文件目录

为什么需要 ADD go.sum . 因为其实 go.sun 是在根目录下并不是 g.mod 目录下

dcokerfile 详解

dcokerfile 详解

案例2

dockerfile 文件

FROM golang:alpine AS builder

LABEL stage=gobuilder

ENV CGO_ENABLED 0
ENV GOOS linux
ENV GOPROXY https://goproxy.cn,direct

WORKDIR /build/zero
# 把docekr守护进程下的所有文件 复制到 /build/zero 目录下,相当于  zero 就是 greet一样
COPY . .

打包镜像

docker build -t hello:v4 -f service/hello/Dockerfile .

luwei@luweideMacBook-Pro-2 greet % docker build -t hello:v4 -f service/hello/Dockerfile .
[+] Building 88.6s (9/9) FINISHED                                                                                                                                                                         
 => [internal] load build definition from Dockerfile                                                                                                                                                 0.1s
 => => transferring dockerfile: 6.13kB                                                                                                                                                               0.0s
 => [internal] load .dockerignore                                                                                                                                                                    0.0s
 => => transferring context: 2B                                                                                                                                                                      0.0s
 => [internal] load metadata for docker.io/library/golang:alpine                                                                                                                                    83.7s
 => [auth] library/golang:pull token for registry-1.docker.io                                                                                                                                        0.0s
 => [1/3] FROM docker.io/library/golang:alpine@sha256:55da409cc0fe11df63a7d6962fbefd1321fedc305d9969da636876893e289e2d                                                                               0.0s
 => [internal] load build context                                                                                                                                                                    2.9s
 => => transferring context: 145.68MB                                                                                                                                                                2.8s
 => CACHED [2/3] WORKDIR /build/zero                                                                                                                                                                 0.0s
 => [3/3] COPY . .                                                                                                                                                                                   0.5s
 => exporting to image                                                                                                                                                                               1.0s
 => => exporting layers                                                                                                                                                                              1.0s
 => => writing image sha256:2a71b6880ec710842cd090ffbf44ece12ab49829981aec3a424739c1f208f224                                                                                                         0.0s
 => => naming to docker.io/library/hello:v4                                                                                                                                                          0.0s
luwei@luweideMacBook-Pro-2 greet % 

查看内容

内容和greet 内容一样的

/build/zero # ls
Dockerfile    README.en.md  README.md     default.etcd  go.mod        go.sum        service

案例3

dockerfile 文件

FROM golang:alpine AS builder

LABEL stage=gobuilder

ENV CGO_ENABLED 0
ENV GOOS linux
ENV GOPROXY https://goproxy.cn,direct

WORKDIR /build/zero

# 这三个可以不放,前提是你已经把扩展已经同步过去了
#ADD go.mod .
#ADD go.sum .
#RUN go mod download

COPY . .
COPY service/hello/etc /app/etc
RUN go build -ldflags="-s -w" -o /app/hello service/hello/hello.go

FROM alpine

RUN apk update --no-cache && apk add --no-cache ca-certificates tzdata
ENV TZ Asia/Shanghai

WORKDIR /app
COPY --from=builder /app/hello /app/hello
COPY --from=builder /app/etc /app/etc
CMD ["./hello", "-f", "etc/hello-api.yaml"]

启动容器并进去

luwei@luweideMacBook-Pro-2 greet % docker run -t -i hello:v5 /bin/sh                     
/app # 
/app # ls
etc    hello
/app # 

请求测试

luwei@luweideMacBook-Pro-2 ~ % curl -i http://localhost:8889/from/you
HTTP/1.1 200 OK
Content-Type: application/json
X-Trace-Id: efd07feabdbedf9e3dd51e2eb6ddcb1b
Date: Thu, 25 Nov 2021 04:13:09 GMT
Content-Length: 14

{"message":""}%
luwei@luweideMacBook-Pro-2 ~ %
本作品采用《CC 协议》,转载必须注明作者和本文链接
good good study day day up
讨论数量: 1

标题错了,dockerfile

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!