Проблема с многоэтапными сборками Docker

У меня есть проблема с многоэтапной сборкой, когда двоичный файл, который создается на первом этапе, правильно копируется на этап 2, но когда вы пытаетесь запустить его, исполняемый файл не может быть найден.

Докерфайл это:

FROM golang as goimage
ENV SRC=/go/src/
RUN mkdir -p /go/src/
WORKDIR /go/src/go_docker
RUN git clone https://github.com/bryonbaker/simple-microservice.git /go/src/go_docker/ \
&& CGO_ENABLED=0 GOOS=linux GOARCH=amd64
RUN go get github.com/gorilla/mux
RUN go build -o bin/go_docker

FROM alpine:latest AS microservice
RUN apk --no-cache add bash
ENV WORK_DIR=/docker/bin
WORKDIR $WORK_DIR
COPY --from=goimage /go/src/go_docker/bin/ ./

# Put a container-image version identifier in the root directory.
ARG VERSION=1.0
RUN echo $VERSION > image_version

EXPOSE 10000
#CMD ["go_docker"]

Результат:

$ docker run -ti -p 80:10000 go-docker:latest
/docker/bin # ls

go_docker image_version
/docker/bin # ./go_docker /bin/sh: ./go_docker: not found
/docker/bin #

Если я запускаю двоичный файл из созданного промежуточного контейнера goimage, он работает нормально. Размеры файлов совпадают...

ПРИМЕЧАНИЕ. В этом файле докеров я закомментировал CMD и тестирую через оболочку. Если вы раскомментируете CMD, вы получите ту же проблему:

docker run go-docker:latest docker: Error response from daemon: OCI runtime create failed: container_linux.go:344: starting container process caused "exec: \"go_docker\": executable file not found in $PATH": unknown. ERRO[0001] error waiting for container: context canceled

Я сделал тестовый код общедоступным в репозитории git, если вы хотите его посмотреть.

заранее спасибо

Не могли бы вы включить команду, которую вы используете для создания этого образа?

ctt 09.05.2019 13:00

Могу ли я предложить более конкретное название? например «Программа go отсутствует в многоэтапной сборке dockerfile»

kristianp 06.08.2019 04:15
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Kubernetes - это портативная, расширяемая платформа с открытым исходным кодом для управления контейнерными рабочими нагрузками и сервисами, которая...
Как создать PHP Image с нуля
Как создать PHP Image с нуля
Сегодня мы создадим PHP Image from Scratch для того, чтобы легко развернуть базовые PHP-приложения. Пожалуйста, имейте в виду, что это разработка для...
2
2
2 265
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы получите эту ошибку почти повсеместно в Linux, если общие библиотеки двоичного файла недоступны. (В отладочной оболочке попробуйте запустить ldd /docker/bin/go_docker.)

Вы, вероятно, не ожидаете динамически связанный двоичный файл, но вы его получите, потому что переменные оболочки и среды не переносятся между RUN командами. Когда вы устанавливаете CGO_ENABLED=0 в конце шага RUN, это значение теряется, когда фактическое go build выполняется двумя шагами позже.

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

Это оставляет нам:

FROM golang as goimage

# Use standard $GOPATH layout?
# WORKDIR /go/src/github.com/byronbaker/simple-microservice
# COPY . .
# RUN go get .
# RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install .

# !!! Docker layer caching will not repeat this step if the repo changes
# !!! You won't be able to build a test copy of your uncommitted code
RUN git clone https://github.com/bryonbaker/simple-microservice.git /go/src/go_docker
RUN go get github.com/gorilla/mux

# vvv Put magic environment variables in this line
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install go_docker
# ^^^

# Runtime image
FROM alpine:latest
COPY --from=goimage /go/bin/go_docker /bin/go_docker
ARG VERSION=1.0
RUN echo $VERSION > /image_version
EXPOSE 10000
CMD ["go_docker"]

Хороший! Я совсем забыл про "установить". Можете ли вы объяснить, почему установка переменных среды позже теряется? Я думал, что эта проблема возникла только после FROM.

Bryon 09.05.2019 13:15

Каждая команда RUN запускается в новой оболочке в новом контейнере. Вы можете поиграть с такими вещами, как RUN export ..., и увидеть, что это не имеет никакого эффекта. ENV будет сохраняться между слоями и отображаться в средах RUN команд (и будет сбрасываться при запуске FROM нового изображения).

David Maze 09.05.2019 13:33

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