使用共享的Dockerfile用于多个Dockerfile

3
我手头有很多相似而简单的dockerfile,但是我想要一个基础的dockerfile,让我的dockerfile将它们的变量传递给它。
在我的情况下,dockerfile之间唯一的区别只是它们的EXPOSE,所以我认为最好保留一个基础的dockerfile,其他dockerfile只需像模板引擎一样将变量注入到基础dockerfile中。
以下是一个示例dockerfile
FROM golang:1.17 AS builder
WORKDIR /app
COPY . .
RUN go mod download
RUN go build -o /bin/app ./cmd/root.go

FROM alpine:latest
WORKDIR /bin/
COPY --from=builder /bin/app .
EXPOSE 8080
LABEL org.opencontainers.image.source="https://github.com/mohammadne/bookman-auth"
ENTRYPOINT ["/bin/app"]
CMD ["server", "--env=dev"]
4个回答

5

IMPORT指令将永远不会被实现

很久以前,Docker提出了IMPORT指令。

不幸的是,问题已关闭,但PR仍然打开:

你的解决方案

但是对于你的情况,你只需要使用一点sed即可。

例如:

# Case1: inplace templating
EXPOSED_PORT=8081 sed -i "s/EXPOSE 8080/EXPOSE $EXPOSED_PORT/" Dockerfile

# Case2: generating Dockerfile from template
sed "s/EXPOSE 8080/EXPOSE $EXPOSED_PORT/" Dockerfile.template > Dockerfile

说明:

  • EXPOSED_PORT=8081 声明本地 bash 变量
  • sed 是一个文本操作工具
  • sed -i "s/EXPOSE 8080/EXPOSE $EXPOSED_PORT/" DockerfileDockerfile 中的 EXPOSE 8080 替换为 EXPOSE 8081
  • sed "s/EXPOSE 8080/EXPOSE $EXPOSED_PORT/" Dockerfile.template > DockerfileDockerfile.template 生成新的 Dockerfile

这个能跨平台实现吗?sed 在 Windows 中的命令是什么? - eastwater

4

您可以将暴露的端口作为镜像构建参数。如果你创建一个如下的Dockerfile:

FROM alpine:latest
ARG EXPOSED_PORT
EXPOSE ${EXPOSED_PORT}

你可以通过像这样传递端口号来指定构建时公开的端口。
docker build -t myimage --build-arg EXPOSED_PORT=8000 .

值得注意的是,EXPOSE语句主要用于文档记录。即使没有EXPOSE语句,您的镜像也会正常工作。


2

正如yasen所说,导入指令是不可能的。

最后我所做的是:

链接到Github存储库

  1. 创建一个带有EXPOSE ${{ EXPOSED_PORT }}的模板文本文件:
FROM golang:1.17 AS builder

WORKDIR /app

COPY . .

RUN go mod download && make ent-generate

RUN go build -o /bin/app ./cmd/root.go

FROM alpine:latest

WORKDIR /bin/

COPY --from=builder /bin/app .

EXPOSE ${{ EXPOSED_PORT }}

LABEL org.opencontainers.image.source="https://github.com/mohammadne/bookman-library"

ENTRYPOINT ["/bin/app"]

CMD ["server", "--env=dev"]


创建一个 Python 脚本。
#!/usr/bin/python
from shutil import copyfile
import os


class Config:
    def __init__(self, service, port):
        self.service = service
        self.port = port


configs = [
    Config("auth", "8080"),
    Config("user", "8081"),
    Config("library", "8082"),
]

pathToDir = "../build"
template = f"{pathToDir}/template.txt"

for config in configs:
    outputDir = f"{pathToDir}/{config.service}"
    os.mkdir(outputDir)

    fileName = copyfile(template, f"{outputDir}/Dockerfile")

    with open(fileName, "rt") as file:
        replacedText = file.read().replace('${{ EXPOSED_PORT }}', config.port)

    with open(fileName, "wt") as file:
        file.write(replacedText)

然后在Python脚本中,您可以替换您的模式!!!

2
你的想法很好。我有两个想法:
  1. 按你所描述的创建基础dockerfile, 然后像这样构建它: docker image build tag base。然后,您可以拥有两行代码的Dockerfiles,看起来像 FROM base \n EXPOSE 8080
  2. 或者,您可以有一个单一的Dockerfile,并只是改变运行容器的方式。 有一个 'expose' 开关。 Dockerfile中指定的任何内容都可以在 'run' 命令中被覆盖。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接