简体   繁体   English

如何自定义 golang-docker 镜像以使用 golang 进行脚本编写?

[英]How to customize golang-docker image to use golang for scripting?

I came across this blog: using go as a scripting language and tried to create a custom image that I can use to run golang scripts ie我遇到了这个博客: 使用 go 作为脚本语言并尝试创建一个自定义图像,我可以用它来运行 golang 脚本,即

FROM golang:1.15
RUN go get github.com/erning/gorun
RUN mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
RUN echo ':golang:E::go::/go/bin/gorun:OC' | tee /proc/sys/fs/binfmt_misc/register

It fails with error:它失败并出现错误:

mount: /proc/sys/fs/binfmt_misc: permission denied.
ERROR: Service 'go_saga' failed to build : The command '/bin/sh -c mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc' returned a non-zero code: 32

It's readonly file system so can't change the permissions as well.它是只读文件系统,因此也不能更改权限。 The task I'm trying to achieve here is well documented here .我想在这里实现的任务是有据可查的在这里 Please help me with following questions:请帮助我解决以下问题:

  1. Is that even possible ie mount /proc/sys/fs/binfmt_misc and write to the file: /proc/sys/fs/binfmt_misc/register ?这甚至可能,即挂载/proc/sys/fs/binfmt_misc并写入文件: /proc/sys/fs/binfmt_misc/register
  2. If Yes, how to do that ?如果是,该怎么做?

I guess, it would be great, if we could run golang scripts in the container.我想,如果我们可以在容器中运行 golang 脚本,那就太好了。

First a quick disclaimer that I haven't done this binfmt trick to run go scripts.首先是一个快速的免责声明,我没有使用这个 binfmt 技巧来运行 go 脚本。 I suppose it might work, but I just use go run when I want to run something on the fly.我想它可能会起作用,但是当我想即时运行某些东西时,我只使用go run

There's a lot to unpack in this.这里面有很多东西要解开。 Container isolation runs an application with a shared kernel in an isolated environment.容器隔离在隔离环境中运行具有共享内核的应用程序。 The namespaces, cgroups, and security settings are designed to prevent one container from impacting other containers or the host.命名空间、cgroup 和安全设置旨在防止一个容器影响其他容器或主机。

Why is that important?为什么这很重要? Because /proc/sys/fs/binfmt_misc is interacting with the kernel, and pushing a change to that would be considered a container escape since you're modifying the underlying host.因为/proc/sys/fs/binfmt_misc正在与内核交互,并且推送更改将被视为容器逃逸,因为您正在修改底层主机。

The next thing to cover is building an image vs running a container.接下来要介绍的是构建映像与运行容器。 When you build an image with the Dockerfile, you are defining the image filesystem and some metadata (labels, entrypoint, exposed ports, etc).当您使用 Dockerfile 构建映像时,您正在定义映像文件系统和一些元数据(标签、入口点、公开端口等)。 Each RUN command executes that command inside a temporary container, based on the previous step's result, and when the command finishes it captures the changes to the container filesystem.每个 RUN 命令都会根据上一步的结果在临时容器内执行该命令,当命令完成时,它会捕获对容器文件系统的更改。 When you mount another filesystem, that doesn't change the underlying container filesystem, so even if you could, the mount command would be a noop during the image build.当您挂载另一个文件系统时,这不会更改底层容器文件系统,因此即使可以,挂载命令在映像构建期间也将是一个 noop。

So if this is possible, you'll need to do it inside the container rather than during build time, that container will need to be privileged since doing things like mounting filesystems and modifying /proc requires access not normally given to containers, and you'll be modifying the host kernel in the process.因此,如果可能的话,您需要在容器内而不是在构建期间执行此操作,该容器需要具有特权,因为执行诸如挂载文件系统和修改 /proc 之类的操作需要通常不会授予容器的访问权限,并且您将在此过程中修改主机内核。 You'd need to make the container entrypoint run the mount and register the binfmt_misc entry, and figure out what to do if the entry is already setup/registered, but possibly to a different directory in another container.您需要让容器入口点运行挂载并注册 binfmt_misc 条目,并弄清楚如果该条目已经设置/注册但可能到另一个容器中的不同目录时该怎么做。

As an aside, when dealing with binfmt_misc and containers, the F flag is very important, though in your use case it's important that you don't have it.顺便说一句,在处理 binfmt_misc 和容器时, F 标志非常重要,但在您的用例中,重要的是您没有它。 Typically you need the F flag so the binary is found on the host filesystem rather than searched for within the container filesystem namespace.通常,您需要 F 标志,以便在主机文件系统上找到二进制文件,而不是在容器文件系统命名空间中搜索。 The typical use case of binfmt_misc and containers is configuring the host to be able to run containers for different architectures, eg Docker Desktop can run amd64, arm64, and a bunch of other platforms today using this. binfmt_misc 和容器的典型用例是将主机配置为能够运行不同架构的容器,例如 Docker Desktop 可以运行 amd64、arm64 以及今天使用它的许多其他平台。

In the end, if you want to run a container as a one off to run a go command as a script, I'd skip the binfmt misc trick and make an entrypoint that does a go run instead.最后,如果您想一次性运行容器以将 go 命令作为脚本运行,我会跳过 binfmt misc 技巧并创建一个执行go run的入口点。 But if you're using the container for longer run processes where you want to periodically run a go file as a script, you'll need to do that in the container, and as a privileged container that has the ability to escape to the host.但是,如果您将容器用于长时间运行的进程,并且您希望定期将 go 文件作为脚本运行,那么您需要在容器中执行此操作,并且作为能够转义到主机的特权容器.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM