首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使用sdkman构建dockerfile

无法使用sdkman构建dockerfile
EN

Stack Overflow用户
提问于 2020-06-04 06:57:26
回答 3查看 2.2K关注 0票数 1

我对码头工人的概念完全陌生。我正在创建以下Dockerfile作为练习。

代码语言:javascript
复制
FROM ubuntu:latest

MAINTAINER kesarling

RUN apt update && apt upgrade -y
RUN apt install nginx curl zip unzip -y
RUN apt install openjdk-14-jdk python3 python3-doc clang golang-go gcc g++ -y
RUN curl -s "https://get.sdkman.io" | bash
RUN bash /root/.sdkman/bin/sdkman-init.sh
RUN sdk version
RUN yes | bash -c 'sdk install kotlin'

CMD [ "echo","The development environment has now been fully setup with C, C++, JAVA, Python3, Go and Kotlin" ]

我正在使用SDKMAN!安装Kotlin。最初的问题是,我没有使用RUN bash /root/.sdkman/bin/sdkman-init.sh,而是使用了RUN source /root/.sdkman/bin/sdkman-init.sh。但是,它给出了说未找到的错误。所以,我试着使用RUN . /root/.sdkman/bin/sdkman-init.sh,它是不管用。但是,RUN bash /root/.sdkman/bin/sdkman-init.sh 看起来 to工作,如in不给出任何错误,并试图运行下一个命令。然而,对接者却给出了错误,说sdk: not found

我哪里出问题了?

应该注意的是,这些步骤对于我的主机发行版(我正在运行docker的版本)来说就像魅力一样,它是Pop!_OS 20.04

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-06-04 07:26:26

实际上,脚本/root/.sdkman/bin/sdkman-init.sh来源于sdk

源是内置的bash,而不是文件系统上的二进制文件。

源命令执行当前shell中的文件。

每个RUN指令将在当前映像之上的一个新层中执行任何命令,并提交结果。

生成的提交的映像将用于Dockerfile的下一步。

试试这个:

代码语言:javascript
复制
FROM ubuntu:latest

MAINTAINER kesarling

RUN apt update && apt upgrade -y
RUN apt install nginx curl zip unzip -y
RUN apt install openjdk-14-jdk python3 python3-doc clang golang-go gcc g++ -y
RUN curl -s "https://get.sdkman.io" | bash
RUN /bin/bash -c "source /root/.sdkman/bin/sdkman-init.sh; sdk version; sdk install kotlin"

CMD [ "echo","The development environment has now been fully setup with C, C++, JAVA, Python3, Go and Kotlin" ]
票数 9
EN

Stack Overflow用户

发布于 2020-11-10 02:29:30

Ubuntu Dockerfile中的SDKMAN

tl;dr

  1. sdk命令不是二进制的,而是加载到内存中的bash脚本。
  2. Shell会话是一个“进程”,这意味着环境变量和声明的shell函数仅在shell会话存在的时间内存在;它只在RUN命令存在时才存在。
  3. 手动调整PATH
代码语言:javascript
复制
RUN apt-get update && apt-get install curl bash unzip zip -y
RUN curl -s "https://get.sdkman.io" | bash

RUN source "$HOME/.sdkman/bin/sdkman-init.sh" \
    && sdk install java 8.0.275-amzn \
    && sdk install sbt 1.4.2 \
    && sdk install scala 2.12.12

ENV PATH=/root/.sdkman/candidates/java/current/bin:$PATH
ENV PATH=/root/.sdkman/candidates/scala/current/bin:$PATH
ENV PATH=/root/.sdkman/candidates/sbt/current/bin:$PATH

全版

哦,哇,这是一次想办法弄清楚的旅程。在每一行下面都有关于为什么运行某些命令的注释。

我学到了很多关于unix是如何工作的,sdkman是如何工作的,以及docker是如何工作的,以及为什么这三者的交集会产生非常不寻常的行为。

代码语言:javascript
复制
# I am using a multi-stage build so I am just copying the built artifacts
# from this stage to keep final image small.
FROM ubuntu:latest as ScalaBuild

# Switch from `sh -c` to `bash -c` as the shell behind a `RUN` command.
SHELL ["/bin/bash", "-c"]

# Usual updates
RUN apt-get update && apt-get upgrade -y
# Dependencies for sdkman installation
RUN apt-get install curl bash unzip zip -y

#Install sdkman
RUN curl -s "https://get.sdkman.io" | bash

# FUN FACTS:
# 1) the `sdk` command is not a binary but a bash script loaded into memory
# 2) Shell sessions are a "process", which means environment variables
#    and declared shell function only exist for 
#    the duration that shell session exists
RUN source "$HOME/.sdkman/bin/sdkman-init.sh" \
    && sdk install java 8.0.275-amzn \
    && sdk install sbt 1.4.2 \
    && sdk install scala 2.12.12

# Once the real binaries exist these are 
# the symlinked paths that need to exist on PATH
ENV PATH=/root/.sdkman/candidates/java/current/bin:$PATH
ENV PATH=/root/.sdkman/candidates/scala/current/bin:$PATH
ENV PATH=/root/.sdkman/candidates/sbt/current/bin:$PATH

# This is specific to running a minimal empty Scala project and packaging it
RUN touch build.sbt
RUN sbt compile
RUN sbt package


FROM alpine AS production

# setup production environment image here

COPY --from=ScalaBuild /root/target/scala-2.12/ $INSTALL_PATH

ENTRYPOINT ["java", "-cp", "$INSTALL_PATH", "your.main.classfile"]
票数 6
EN

Stack Overflow用户

发布于 2020-06-04 11:29:09

通常,您希望避免在Docker中使用“版本管理器”类型工具;最好安装所需编译器或运行时的特定版本。

对于Kotlin来说,它是一个JVM应用程序作为压缩文件分发,所以安装起来应该相当容易:

代码语言:javascript
复制
FROM openjdk:15-slim
ARG KOTLIN_VERSION=1.3.72

# Get OS-level updates:
RUN apt-get update \
 && apt-get install --no-install-recommends --assume-yes \
      curl \
      unzip
# and if you need C/Python dependencies, those too

# Download and unpack Kotlin
RUN cd /opt \
 && curl -LO https://github.com/JetBrains/kotlin/releases/download/v${KOTLIN_VERSION}/kotlin-compiler-${KOTLIN_VERSION}.zip \
 && unzip kotlin-compiler-${KOTLIN_VERSION}.zip \
 && rm kotlin-compiler-${KOTLIN_VERSION}.zip

# Add its directory to $PATH
ENV PATH=/opt/kotlinc/bin:$PATH

版本管理器的真正问题在于它们严重依赖于工具设置环境变量。正如@JeevanRao在他们的回答中所指出的,每个Dockerfile RUN命令都在单独的容器中运行在单独的shell中,该命令中的任何环境变量设置都会在下一个命令中丢失。

代码语言:javascript
复制
# Does absolutely nothing: environment variables do not stay set
RUN . /root/.sdkman/bin/sdkman-init.sh

由于映像通常只包含一个应用程序及其运行时,因此不需要更改所使用的运行时或编译器的版本。我的Dockerfile示例将其作为ARG传递,因此您可以在Dockerfile中更改它,或者传递一个docker build --build-arg KOTLIN_VERSION=...选项以使用不同的版本。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62188599

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档