Управление локальными / частными пакетами и модулями 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
. Думаю, это не тебе.
В соответствии с приведенным здесь примером я обновил свое репо здесь. Вы можете попробовать собрать код внутри контейнера докеров. Он может быть собран успешно, но вам следует изменить имя пакета.