Динамически изменить цель сборки внутри Dockerfile - PullRequest
0 голосов
/ 04 октября 2019

Я работаю над проектом Go, который докеризован. Он находится внутри каталога src на моей GOPATH. Проект имеет следующую структуру:

project/
    Dockerfile
    go.mod
    cmd/
        cmd_pkg1/
            main.go
            go.mod
        cmd_pkg2/
            main.go
            go.mod
    internal/
        int_pkg1/
            source.go
        int_pkg2/
            source.go
    pkg/
        pkg1/
            source.go
        pkg2/
            source.go

project - это не настоящее имя, а имена файлов упрощены (существует несколько файлов, вложенных каталогов, ...). main.go указывает, что эти пакеты называются main (исполняемые файлы), а файлы source.go указывают, что они имеют имя, равное его каталогу (библиотекам). Файл project/go.mod содержит зависимости проекта, в то время как project/cmd/cmd_pkgX/go.mod содержит определенные зависимости пакета плюс директивы require project v0.0.0 и replace project => ../../.

Упрощенная версия файла Docker выглядит следующим образом:

ARG goversion=1.12.3
ARG goos
ARG goarch
ARG goarm=6
ARG cmd

FROM golang:${goversion}-stretch AS build-env
ENV CGO_ENABLED=0
ENV GO111MODULE=on
ENV GOOS=${goos}
ENV GOARCH=${goarch}
ENV GOARM=${goarm}
ENV COMMAND=${cmd}
ADD . /src/project
WORKDIR /src/project/cmd/cmd_pkg1
RUN go build -i -o /bin/app .

FROM scratch
COPY --from=build-env /bin/app /
ENTRYPOINT ["/app"]

Как видите, я объявляю некоторые аргументы, которые позволяют мне настраивать разные версии Go и выполнять кросс-компиляцию для любой поддерживаемой цели. Это многошаговый процесс. Первый шаг начинается с образа Go для конкретной версии, отключает cgo, включает модули для go 1.11 и 1.12 и передает аргументы как переменные среды. Затем он добавляет всю структуру проекта к /src/, устанавливает рабочий каталог и компилирует код. На втором этапе просто перетаскиваем исполняемый двоичный файл в чистое изображение и определяем его как точку входа.

Теперь я пытаюсь поделиться этим Dockerfile среди всех исполняемых пакетов (cmd/cmd_pkg1, cmd/cmd_pkg2, .. .) и для этого я пытался установить новый ARG cmd с именем исполняемого пакета (cmd_pkg1, cmd_pkg2, ...) и как-то передать его команде WORKDIR.

Я пробовал несколько вариантов для WORKDIR, и ни один из них не работает:

  • /src/package/cmd/${cmd}
  • /src/package/cmd/$COMMAND
  • "/src/package/cmd/$COMMAND"

Все они выдают следующую ошибку:

can't load package: package package/cmd: unknown import path "package/cmd": cannot find module providing package package/cmd

Кажется, он не распознает cmd_pkg1 dir ни в одной из предоставленных опций.

Я хочу сохранить Dockerfile там, где он есть, чтобы избежать дублирования Dockerfile и наличия единой точки входа для CI и так далее. Я также предпочел бы избегать автоматической генерации Dockerfile для каждого проекта из шаблона.

Есть идеи? Я совсем новичок в модулях go и не так много играл с go build, поскольку до сих пор он работал из коробки для всех моих проектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...