Управление локальными / частными пакетами и модулями 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 я ссылаюсь на инструменты модуля , чтобы использовать некоторые функции. Вот как я это реализовал: (src of ./service1/main.go)

package main

import (
    "fmt"

    st "../tools"

    // other modules imports
)

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

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

Но когда я пытаюсь построить dockerfile из 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"]

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

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

ОБНОВИТЬ:

Как было предложено в ответе, изменение значения 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: /

2 ответа

Для тех, кто сталкивается с подобной проблемой - я решил аналогичную проблему с помощью 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/

Вы должны изменить свою переменную среды GO111MODULE как авто.

Последний 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. Думаю, это не тебе.

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

Другие вопросы по тегам