本文主要介绍如何将go项目打包成镜像,首先介绍Dockerfile常用命令介绍,然后介绍使用工具goctl用于生成Dockerfile,还可以根据需求自定义指令内容,最后讲解如何将go-blog项目打包成镜像,以及如何运行等
前言
参考文档:
开发完项目之后,可以通过dockerfile将项目打包成镜像
Dockerfile介绍
Dockerfile 是用于构建 Docker 镜像的文本文件,其中包含一系列指令(命令)。这些指令按照顺序执行,用于定义镜像的构建过程。下面是常用的 Dockerfile 命令及其详细解释:
- FROM:指定基础镜像,用于构建当前镜像的基础。例如:
FROM ubuntu:latest
。 - LABEL:为镜像添加元数据,可以包含任意键值对。例如:
LABEL maintainer="yourname@example.com"
。 - RUN:在镜像中执行命令,并创建新的镜像层。例如:
RUN apt-get update && apt-get install -y curl
。 - CMD:指定容器启动时要执行的命令,该命令只能有一个。例如:
CMD ["nginx", "-g", "daemon off;"]
。 - EXPOSE:声明容器运行时监听的端口。例如:
EXPOSE 8080
。 - ENV:设置环境变量。例如:
ENV MYSQL_VERSION 5.7
。 - ADD:将文件、目录或远程 URL 的内容复制到镜像中。例如:
ADD app.jar /app/
。 - COPY:将文件或目录复制到镜像中。例如:
COPY ./src /app/src
。 - WORKDIR:设置工作目录,后续命令将在该目录下执行。例如:
WORKDIR /app
。 - VOLUME:声明持久化目录,用于在容器和主机之间共享数据。例如:
VOLUME /data
- ENTRYPOINT:指定容器启动时要执行的命令,与 CMD 不同的是,ENTRYPOINT 不会被Dockerfile 中的指令覆盖。例如:
ENTRYPOINT ["java", "-jar", "app.jar"]
。 - USER:设置运行后续命令的用户名或 UID。例如:
USER myuser
。 - ARG:定义构建参数,可以在构建镜像时通过 --build-arg 传递。例如:
ARG VERSION=latest
。 - ONBUILD:指定触发器命令,在当前镜像被继承时执行。例如:
ONBUILD ADD . /app
。
下面是一个简单的示例,演示了如何编写一个用于构建基本 Go 应用程序的 Dockerfile。
# 使用官方的 Golang 镜像作为基础镜像
FROM golang:1.16
# 在容器内创建一个目录来存放我们的应用代码
RUN mkdir /app
# 将工作目录切换到 /app
WORKDIR /app
# 将当前目录下的所有文件拷贝到 /app 目录
COPY . .
# 编译 Go 应用程序
RUN go build -o myapp .
# 暴露 8080 端口
EXPOSE 8080
# 运行应用程序
CMD ["./myapp"]
当然还有更简便的方式,使用goctl工具生成Dockerfile,解放了生成力~
goctl工具生成Dockerfile
安装工具
go install github.com/zeromicro/go-zero/tools/goctl@latest
命令行输入
(base) yangmiao@ym-mac gin-blog % goctl docker --help
Generate Dockerfile
Usage:
goctl docker [flags]
Flags:
--base string The base image to build the docker image, default scratch (default "scratch")
--branch string The branch of the remote repo, it does work with --remote
--exe string The executable name in the built image
--go string The file that contains main function
-h, --help help for docker
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
--port int The port to expose, default none
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
--tz string The timezone of the container (default "Asia/Shanghai")
--version string The goctl builder golang image version
在执行该命令后,Goctl 会自动生成一个名为 Dockerfile 的文件,包含适当的环境配置和基础镜像信息。
goctl docker --go main.go
生成的Dockerfile文件如下所示
Dockerfile
多阶段构建
- 第一个 FROM 开始的部分是构建一个 builder 镜像,目的是在其中编译出可执行文件 main
- 第二个 From 开始的部分是从第一个镜像里 copy 出来可执行文件 main,并且用了基础镜像 scratch ,以保障最终镜像尽可能小
FROM golang:alpine AS builder
LABEL stage=gobuilder
ENV CGO_ENABLED 0
ENV GOPROXY https://goproxy.cn,direct
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk update --no-cache && apk add --no-cache tzdata
WORKDIR /build
ADD go.mod .
ADD go.sum .
RUN go mod download
COPY . .
RUN go build -ldflags="-s -w" -o /app/main main.go
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
ENV TZ Asia/Shanghai
WORKDIR /app
COPY --from=builder /app/main /app/main
CMD ["./main"]
- 默认禁用了 cgo
- 启用了 GOPROXY 加速 go mod download
- 去掉了调试信息 -ldflags=“-s -w” 以减小镜像尺寸
- 安装了 ca-certificates,这样使用 TLS证书就没问题了
- tzdata 在 builder 镜像安装,并在最终镜像只拷贝了需要的时区
- 自动设置了本地时区
构造镜像
至于docker如何使用,可以参考Docker-常用命令介绍,看这一篇就够了
在项目根目录下,执行docker build
,用于生成镜像,生成镜像后就可以查看和启动了~
docker build -t go-blog:v1 .
(base) yangmiao@ym-mac gin-blog % docker build -t go-blog:v1 .
ERROR: Cannot connect to the Docker daemon at tcp://localhost:2375. Is the docker daemon running?
(base) yangmiao@ym-mac gin-blog % sudo docker build -t go-blog:v1 .
Password:
[+] Building 515.7s (18/18) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 694B 0.0s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/golang:alpine 308.4s
=> [internal] load build context 10.3s
=> => transferring context: 215.37MB 10.1s
=> [builder 1/9] FROM docker.io/library/golang:alpine@sha256:70afe55365a265f0762257550bc38440e0d6d6b97020d3f8c85328f00200dd8e 156.9s
=> => resolve docker.io/library/golang:alpine@sha256:70afe55365a265f0762257550bc38440e0d6d6b97020d3f8c85328f00200dd8e 0.0s
=> => sha256:86a63ed24dc22a348b35d99b5ec9dc67ff66563b539875e5c8ab2d870b3991ac 286.31kB / 286.31kB 75.8s
=> => sha256:ae48e6158ebb1a353f7d7b0676b0bd55a09a448a440b65135db378ffb0040919 64.09MB / 64.09MB 153.7s
=> => sha256:70afe55365a265f0762257550bc38440e0d6d6b97020d3f8c85328f00200dd8e 1.65kB / 1.65kB 0.0s
=> => sha256:635bf83d6a1993bf40e3c575d7b522d41950af4f1a5c1c7cd01c81d93b76f4bf 1.16kB / 1.16kB 0.0s
=> => sha256:1ddcbcaf7f02eab589ea6e5727ede30fe040922e4674737894898cddeaba40e0 6.34kB / 6.34kB 0.0s
=> => sha256:2c03dbb20264f09924f9eab176da44e5421e74a78b09531d3c63448a7baa7c59 3.33MB / 3.33MB 76.8s
=> => sha256:edabe92b0de78c4b662f63a4b2884d0821795e38a90c7ec070ccfa98f8aa236c 156B / 156B 151.3s
=> => extracting sha256:2c03dbb20264f09924f9eab176da44e5421e74a78b09531d3c63448a7baa7c59 0.8s
=> => extracting sha256:86a63ed24dc22a348b35d99b5ec9dc67ff66563b539875e5c8ab2d870b3991ac 0.1s
=> => extracting sha256:ae48e6158ebb1a353f7d7b0676b0bd55a09a448a440b65135db378ffb0040919 2.6s
=> => extracting sha256:edabe92b0de78c4b662f63a4b2884d0821795e38a90c7ec070ccfa98f8aa236c 0.0s
=> [builder 2/9] RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories 1.0s
=> [builder 3/9] RUN apk update --no-cache && apk add --no-cache tzdata 2.7s
=> [builder 4/9] WORKDIR /build 0.0s
=> [builder 5/9] ADD go.mod . 0.0s
=> [builder 6/9] ADD go.sum . 0.0s
=> [builder 7/9] RUN go mod download 14.2s
=> [builder 8/9] COPY . . 7.4s
=> [builder 9/9] RUN go build -ldflags="-s -w" -o /app/main main.go 24.5s
=> [stage-1 1/4] COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt 0.0s
=> [stage-1 2/4] COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai 0.0s
=> [stage-1 3/4] WORKDIR /app 0.0s
=> [stage-1 4/4] COPY --from=builder /app/main /app/main 0.1s
=> exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:556e5362b86a63c8d1325549b595d987c8c79ad749524875c9d018c44cbf3ad5 0.0s
=> => naming to docker.io/library/go-blog:v1 0.0s
查看镜像:
sudo docker images | grep go-blog
启动镜像:
sudo docker run -it go-blog:v1