2017-08-16 20:50
浏览 128


There is an option to use FROM scratch for me it looks like a really attractive way of building my Go containers.

My question is what does it still have natively to run binaries do I need to add anything in order to reliably run Go binaries? Compiled Go binary seems to run it at least on my laptop.

My goal is to keep image size to a minimum both for security and infra management reasons. In an optimal situation, my container would not be able to execute binaries or shell commands outside of build phase.

图片转代码服务由CSDN问答提供 功能建议

对我来说,可以选择使用 FROM从头开始,它看起来像是一种非常吸引人的方式 构建我的Go容器。

我的问题是,运行二进制文件本来还有什么本性,为了可靠地运行Go二进制文件,我需要添加任何内容吗? 编译后的Go二进制文件似乎至少可以在我的笔记本电脑上运行。

出于安全和红外管理的考虑,我的目标是使图像大小最小。 在最佳情况下,我的容器将无法在构建阶段之外执行二进制文件或Shell命令。

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • douyou1960 2017-08-16 20:59

    The scratch image contains nothing. No files. But actually, that can work to your advantage. It turns out, Go binaries built with CGO_ENABLED=0 require absolutely nothing, other than what they use. There are a couple things to keep in mind:

    • With CGO_ENABLED=0, you can't use any C code. Actually not too hard.
    • With CGO_ENABLED=0, your app will not use the system DNS resolver. I don't think it does by default anyways because it's blocking and Go's native DNS resolver is non-blocking.
    • Your app may depend on some things that are not present:
      • Apps that make HTTPS calls (as in, to other services, i.e. Amazon S3, or the Stripe API) will need ca-certs in order to confirm HTTPS certificate authenticity. This also has to be updated over time. This is not needed for serving HTTPS content.
      • Apps that need timezone awareness will need the timezone info files.

    A nice alternative to FROM scratch is FROM alpine, which will include a base Alpine image - which is very tiny (5 MiB I believe) and includes musl libc, which is compatible with Go and will allow you to link to C libraries as well as compile without setting CGO_ENABLED=0. You can also leverage the fact that alpine is regularly updated, using its tzinfo and ca-certs.

    (It's worth noting that the overhead of Docker layers is amortized a bit because of Docker's deduplication, though of course that is negated by how often your base image is updated. Still, it helps sell the idea of using the quite small Alpine image.)

    You may not need tzinfo or ca-certs now, but it's better to be safe than sorry; you can accidentally add a dependency without realizing it breaks your build. So I recommend using alpine as your base. alpine:latest should be fine.

    Bonus: If you want the advantages of reproducible builds inside Docker, but with small image sizes, you can use the new Docker multi-stage builds available in Docker 17.06+.

    It works a bit like this:

    FROM golang:alpine
    ADD . /go/src/github.com/some/gorepo  # may need some go getting if you don't vendor
    RUN go build -o /app github.com/some/gorepo
    FROM scratch  # or alpine
    COPY --from=0 /app /app
    ENTRYPOINT ["/app"]

    (I apologize if I've made any mistakes, I'm typing that from memory.)

    Note that when using FROM scratch you must use the exec form of ENTRYPOINT, because the shell form won't work (it depends on the Docker image having /bin/sh, which it won't.) This will work fine in Alpine.

    点赞 打赏 评论

相关推荐 更多相似问题