Управление локальными / частными пакетами и модулями Golang для сборок докеров

Я новичок в golang и docker, поэтому, просмотрев множество тем и интернет-ресурсов, я запутался в том, как мне все настроить.

Моя проблема в том, что я столкнулся с ошибкой сборки докеров приложения golang из-за не найденной локальной зависимости.

К вашему сведению (локальный компьютер): версия go1.13.4 linux / amd64

Вот контекст моей проблемы:

У меня есть репозиторий, в котором будут храниться исходные коды простых микросервисов (написанных на Go), которые будут работать в Kubernetes. Таким образом, каждая папка в репозитории представляет собой службу. У меня также есть папка «tools», в которой перегруппированы вспомогательные функции и ресурсы, общие для многих сервисов. Мой репозиторий не находится в каких-либо специальных путях Go, он находится в корне одного из моих дисков. Вот как выглядит мое репо:

.
├── service1
│   ├── main.go
│   ├── Dockerfile
│   ├── go.mod
│   └── go.sum
├── service2
├── service3
│   ...
├── serviceX
├── tools
│   ├── helpers.go
│   ├── ressources.go
│   ├── go.mod
└── └── go.sum

Таким образом, каждая папка / служба - это модуль go для независимой обработки своих зависимостей. Инструменты папки также являются модулем. Я инициализировал каждый модуль с помощью go mod init FOLDER_NAME

В сервисе service1 я ссылаюсь на модуль tools для использования некоторых функций. Вот как я это реализовал: (src of ./service1/main.go)

package main

import (
    "fmt"

    st "../tools"

    // other modules imports
)

func main() {
    st.ExecHelperFunc()
    // http server inits
}

Когда я локально запускаю service1's main.go или локально создаю его и затем запускаю двоичный файл, служба работает нормально.

Но когда я пытаюсь создать файл докеров service1, я получаю ошибку сборки golang: build _/go/src/app/tools: cannot find module for path _/go/src/app/tools

Вот мой файл докеров:

FROM golang:1.13 as builder
ENV GO111MODULE=on
WORKDIR /go/src/app
COPY ./tools ./tools
COPY ./service1 ./service1

WORKDIR /go/src/app/tools
RUN go mod download
WORKDIR /go/src/app/service1
RUN go mod download

WORKDIR /go/src/app

RUN go build -o server /go/src/app/service1/main.go

FROM centos:7
RUN yum -y update && yum clean all
COPY --from=builder /go/src/app/server .
EXPOSE 3000
CMD ["./server"]

Итак, я не понимаю, почему докеру не удается создать службу? По-видимому, он не может найти / идентифицировать инструменты модуля, но почему? Я пробовал много разных настроек для файла докеров, но так и не понял.

Спасибо заранее за вашу помощь.

ОБНОВЛЕНИЕ:

Как было предложено в ответе, изменение значения GO111MODULE в файле докеров с on на auto не исправило ошибку сборки, но принесло мне новую:

unexpected directory layout:
    import path: _/go/src/app/tools
    root: /go/src
    dir: /go/src/app/tools
    expand root: /go
    expand dir: /go/src/app/tools
    separator: /

person R.E.B Hernandez    schedule 30.12.2019    source источник


Ответы (2)


Вам следует изменить переменную среды GO111MODULE на auto.

Последний Dockerfile:

FROM golang:1.13 as builder
ENV GO111MODULE=auto
WORKDIR /go/src/app
COPY ./tools ./tools
COPY ./service1 ./service1

WORKDIR /go/src/app/tools
RUN go mod download
WORKDIR /go/src/app/service1
RUN go mod download

WORKDIR /go/src/app

RUN go build -o server /go/src/app/service1/main.go

FROM centos:7
RUN yum -y update && yum clean all
COPY --from=builder /go/src/app/server .
EXPOSE 3000
CMD ["./server"]

ОБНОВЛЕНИЕ

На мой взгляд, если GO111MODULE равно «auto», golang отключит функции модуля и найдет сторонний пакет в GOPATH. Перед компиляцией кода вы должны go get -u github.com/op/go-logging. Я думаю, что это не ты.

Согласно примеру, здесь, Я обновил свое репо, здесь. Вы можете попробовать собрать код внутри контейнера докеров. Сборка может завершиться успешно, но вам следует изменить имя пакета.

person Juxuny Wu    schedule 30.12.2019
comment
Привет ! Спасибо за ваш ответ. К сожалению, изменение GO111MODULE на auto не привело к успешной сборке докеров. Теперь у меня есть новая ошибка в строке сборки: unexpected directory layout: import path: _/go/src/app/tools root: /go/src dir: /go/src/app/tools expand root: /go expand dir: /go/src/app/tools separator: / - person R.E.B Hernandez; 30.12.2019
comment
Вы упускаете что-то важное? Здесь я создал демонстрацию. (github.com/juxuny/go-build-trial ). Просто войдите в корневой каталог и запустите docker build -t go-build-demo -f service1/Dockerfile . - person Juxuny Wu; 30.12.2019
comment
Спасибо за все ваши усилия и помощь! Я очень ценю это. Я клонировал ваше репо и смог построить файл докеров без ошибок. Но инструментальный модуль был голым, а тот, который я пытаюсь создать, на самом деле использует разные общедоступные модули. Поэтому я добавил простой модуль регистрации и снова попытался построить. Не удалось с той же ошибкой, что и у меня. Я выложу свои модификации в ветку, если вы позволите - person R.E.B Hernandez; 30.12.2019
comment
Хорошо, вы можете разместить свои модификации в ветке. Позвольте мне увидеть, что не так. - person Juxuny Wu; 30.12.2019
comment
Я раздвоил ваше репо, а затем создал PR, чтобы все было проще и понятнее;) - person R.E.B Hernandez; 30.12.2019
comment
Похоже, что скомпилировать невозможно. Поскольку вы установили переменную среды GOPATH, вы можете успешно построить код на локальном компьютере. - person Juxuny Wu; 30.12.2019
comment
Давайте продолжим это обсуждение в чате. - person Juxuny Wu; 30.12.2019

Для тех, кто сталкивается с подобной проблемой - я решил аналогичную проблему с помощью каталога vendor. По сути, вы загружаете зависимости на хост, запустив go mod vendor, и затем они будут автоматически скопированы в контейнер докера.

Из Dockerfile необходимо удалить RUN go mod download, а также изменить команду сборки с помощью флага -mod=vendor.

Чтобы создать образ докера, вам нужно запустить эти команды

go mod vendor
docker build . -t image-name

Надеюсь, это кому-то поможет. Я нашел это решение здесь: https://smartystreets.com/blog/2018/09/private-dependencies-in-docker-and-go/

person vecta    schedule 23.04.2021