在这里我们会介绍两种部署方式:
- 直接构建镜像
- 分阶段构建镜像
方式一:直接构建镜像
首先在我们的项目根目录下编写Dockerfile文件,文件名称就是Dockerfile,没有后缀名嗷!!
具体请参考如下内容:
FROM golang:alpine
# 为我们的镜像设置必要的环境变量
# GO111MODULE=on 开启go mod
# CGO_ENABLED=1, 进⾏编译时, 会将⽂件中引⽤libc的库(⽐如常⽤的net包),以动态链接的⽅式⽣成⽬标⽂件。
# CGO_ENABLED=0, 进⾏编译时, 则会把在⽬标⽂件中未定义的符号(外部函数)⼀起链接到可执⾏⽂件中。
# GOOS 编译目标系统为Linux
# GOARCH=amd64:编译目标的指令集架构为 64位 x86架构
# GOPROXY=https://goproxy.cn 指定一下国内源,提升下载速度
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64 \
GOPROXY=https://goproxy.cn
# 移动到工作目录:/build
WORKDIR /build
# 复制项目中的 go.mod 和 go.sum文件并下载依赖信息
COPY go.mod .
COPY go.sum .
RUN go mod download
# 将代码复制到容器中
COPY . .
# 将我们的代码编译成二进制可执行文件app
RUN go build -o app .
# 移动到用于存放生成的二进制文件的 /dist 目录
WORKDIR /dist
# 将二进制文件从 /build 目录复制到这里
RUN cp /build/app .
# 声明服务端口,但是不起实际作用,只是一个标识,具体启动端口是容器中程序的配置
EXPOSE 8888
# 启动容器时运行的命令
CMD ["/dist/app"]
Dockerfile中的内容中的字段不是固定的,根据自己实际情况去修改里边的文件路径、端口号、环境变量、可执行文件名称等
编写完成后,在Dockerfile文件路径下执行命令,命令最后有一个点“.”,可不要忘记咯
docker build -t test_app:v1.0 .
接下来就是等了
PS G:\Go_OBJ\src\test> docker build -t test_app:v1.0 .
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 1.03kB 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/golang:alpine 5.9s
=> [internal] load build context 0.3s
=> => transferring context: 39.05MB 0.3s
=> [1/6] FROM docker.io/library/golang:alpine@sha256:7cc62574fcf9c5fb87ad42a9789d5539a6a085971d58ee75dd2ee146cb8a8695 0.0s
=> CACHED [2/6] WORKDIR /build 0.0s
=> [3/6] COPY . . 0.4s
=> CANCELED [4/6] RUN go build -o app . 56.8s
context canceled
在执行过程中可能会报time out的错,这个就是网络问题了,可能是被墙了,也可能是本地的网络不好,我们再重新执行一下命令试一下就可以!
执行完成后,我们就查看一下镜像是否成功生成
PS G:\Go_OBJ\src\bluebell> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test_app v1.0 0f0c534e7c19 22 minutes ago 955MB
test_app v2.0 4195fcf1f956 49 minutes ago 39MB
我们可以看到test_app:v1.0镜像已经成功生成,我们就可以使用docker run 的命令去启动了!
通过上边的内容,我们成功构建了test_app:v1.0的镜像了,但是我们也可以明显的看出,这个镜像有955M,属实有点大啊,在我们实际应用中,其实只需要里边生成好的二进制可执行文件,其他的环境我们并不关心,也并不需要,这个时候我们可以用分阶段构建镜像,就是我们先去生成一个环境齐全的镜像,然后构生成我们的二进制可执行文件,然后我们把这个可执行文件赋值到另一个小镜像内,并且只保留这个小镜像。可能我讲的有点不清楚,接下来咱们直接上手!
方式二:分阶段构建镜像
第一步仍然是编写Dockerfile文件,参考内容如下:
# 拉取 golang镜像,让其作为一个构造者
FROM golang:alpine AS builder
# 为我们的镜像设置必要的环境变量
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64 \
GOPROXY=https://goproxy.cn
# 移动到工作目录:/build
WORKDIR /build
# 复制项目中的 go.mod 和 go.sum文件并下载依赖信息
COPY go.mod .
COPY go.sum .
RUN go mod download
# 将代码复制到容器中
COPY . .
# 将我们的代码编译成二进制可执行文件 app
RUN go build -o app .
###################
# 接下来创建一个小镜像
###################
FROM scratch
# 程序中可能有配置文件,我们将配置文件也复制过来,拷贝到相应目录
COPY ./cfg /cfg
# 从builder镜像中把/dist/app 拷贝到当前目录
COPY --from=builder /build/app /
# 声明服务端口(不起实际作用,只是一个标识,具体启动端口是容器中程序的配置)
EXPOSE 8081
# 需要运行的命令
ENTRYPOINT ["/app", "cfg/config.yaml"]
然后我们同样是要运行命令
docker build -t test_app:v1.0 .
PS G:\Go_OBJ\src\test> docker build -t test_app:v2.0 .
[+] Building 35.6s (11/11) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 1.12kB 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/golang:alpine 2.1s
=> [1/6] FROM docker.io/library/golang:alpine@sha256:7cc62574fcf9c5fb87ad42a9789d5539a6a085971d58ee75dd2ee146cb8a8695 0.0s
=> [builder 7/7] RUN go build -o bluebell_app . 8.1s
=> CACHED [stage-1 1/2] COPY ./conf /conf 0.0s
=> CACHED [stage-1 2/2] COPY --from=builder /build/bluebell_app / 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:4195fcf1f9567697d490365e21a79816093f44f4be6bf44521a83c2179421268 0.0s
=> => naming to docker.io/library/test_app:v2.0 0.0s
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
我们再查看一下镜像是否构建成功
PS G:\Go_OBJ\src\bluebell> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test_app v1.0 0f0c534e7c19 22 minutes ago 955MB
test_app v2.0 4195fcf1f956 49 minutes ago 39MB
这时我们可以看出镜像已经构建成功了,并且只有39M,也非常符合预期!
此内容是参照七米老师的博客理解的,大家也可以去他的网站看一下:liwenzhou.com,感谢阅读!