使用共享的Dockerfile用于多个Dockerfile。

huangapple go评论93阅读模式
英文:

using shared dockerfile for multiple dockerfiles

问题

我所拥有的是多个相似且简单的dockerfile

但是我想要的是只有一个基础的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"]
英文:

What I have, are multi similar and simple dockerfiles

But what I want is to have a single base dockerfile and my dockerfiles
pass their variables into it.

In my case the only difference between dockerfiles are
simply their EXPOSE, so I think it's better to keep a base dockerfile and other dockerfiles only inject that variables into base dockerfile like a template engine

A sample 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"]

答案1

得分: 5

IMPORT指令将永远不会被实现

很久以前,有人提出了在Docker中使用IMPORT指令的建议。

不幸的是,这些问题已经关闭,但PR仍然是开放的:

解决方案

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

例如:

# 情况1:原地模板化
EXPOSED_PORT=8081 sed -i "s/EXPOSE 8080/EXPOSE $EXPOSED_PORT/" Dockerfile

# 情况2:从模板生成Dockerfile
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文件
英文:

IMPORT directive will never be implemented

A long time ago there was proposed IMPORT directive for Docker

Unfortunately, issues are closed while PR's are still open:

Solution for your case

But for your case, all you need - is just a bit of sed

E.g.:

# 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

Explanation:

  • EXPOSED_PORT=8081 declares local bash variable
  • sed is a tool for text manipulation
  • sed -i "s/EXPOSE 8080/EXPOSE $EXPOSED_PORT/" Dockerfile replaces EXPOSE 8080 to EXPOSE 8081
  • sed "s/EXPOSE 8080/EXPOSE $EXPOSED_PORT/" Dockerfile.template > Dockerfile generates the new Dockerfile from Dockerfile.template

答案2

得分: 4

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

FROM alpine:latest
ARG EXPOSED_PORT
EXPOSE ${EXPOSED_PORT}

在构建镜像时,你可以通过传递端口号来指定要暴露的端口,例如:

docker build -t myimage --build-arg EXPOSED_PORT=8000 .

值得注意的是,EXPOSE语句主要是用于文档说明。即使没有EXPOSE语句,你的镜像也可以正常工作。

英文:

You can have the exposed port as a build argument for the image. If you make a dockerfile like this

FROM alpine:latest
ARG EXPOSED_PORT
EXPOSE ${EXPOSED_PORT}

You can specify which port is exposed when you build it by passing the port number like this

docker build -t myimage --build-arg EXPOSED_PORT=8000 .

It's worth noting that the EXPOSE statement mainly is documentation. Your image will work the same without the EXPOSE statement.

答案3

得分: 2

你有一个非常好的想法。我有两个想法:

  1. 按照你描述的方式创建基础的dockerfile,然后像这样构建它:docker image build tag base。然后你可以有两行的Dockerfile,看起来像是FROM base \n EXPOSE 8080
  2. 或者你可以只有一个Dockerfile,然后在运行容器的方式上进行更改。有一个expose开关,你可以在Dockerfile中指定的几乎任何东西都可以在run命令中被覆盖。
英文:

You have a very good idea. I have two thoughts:

  1. Create the base dockerfile as you described and then build it like this: docker image build tag base. Then you can have two liner Dockerfiles that look like FROM base \n EXPOSE 8080
  2. Alternatively you can have a single Dockerfile and just change the way you run the containers. There is an expose switch. Just about anything you specify in the Dockerfile can be overriden in the run command.

答案4

得分: 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"]

  1. 然后创建一个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脚本中,你可以替换你的模式!!!

英文:

as yasen said, it's impossible to have import directive.

finally what I have did is as follow: link to github repository

  1. create a template text file with 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"]

  1. and then create a python script
#!/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)

then in the python script you can replace your patterns !!!

huangapple
  • 本文由 发表于 2021年9月18日 20:59:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/69234878.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定