如何使用 jre-alpine 基础镜像创建 Scala Play 应用程序的 Docker 镜像
Posted
技术标签:
【中文标题】如何使用 jre-alpine 基础镜像创建 Scala Play 应用程序的 Docker 镜像【英文标题】:How to create a Docker image of a Scala Play application using jre-alpine base image 【发布时间】:2019-12-21 23:26:28 【问题描述】:我想利用jre-alpine
Docker 基础镜像来缩小我必须推送到我的 Docker 注册表的 docker 镜像的大小,但我经常遇到这个错误:
[info] Step 10/16 : RUN id -u demiourgos728 2> /dev/null || useradd --system --create-home --uid 1001 --gid 0 demiourgos728
[info] ---> Running in 696dcf40530a
[info] /bin/sh: useradd: not found
[info] Removing intermediate container 696dcf40530a
[error] The command '/bin/sh -c id -u demiourgos728 2> /dev/null || useradd --system --create-home --uid 1001 --gid 0 demiourgos728' returned a non-zero code: 127
[error] java.lang.RuntimeException: Nonzero exit value: 127
[error] at com.typesafe.sbt.packager.docker.DockerPlugin$.publishLocalDocker(DockerPlugin.scala:483)
[error] at com.typesafe.sbt.packager.docker.DockerPlugin$.$anonfun$projectSettings$33(DockerPlugin.scala:187)
[error] at com.typesafe.sbt.packager.docker.DockerPlugin$.$anonfun$projectSettings$33$adapted(DockerPlugin.scala:185)
[error] at scala.Function1.$anonfun$compose$1(Function1.scala:44)
[error] at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:40)
[error] at sbt.std.Transform$$anon$4.work(System.scala:67)
[error] at sbt.Execute.$anonfun$submit$2(Execute.scala:269)
[error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16)
[error] at sbt.Execute.work(Execute.scala:278)
[error] at sbt.Execute.$anonfun$submit$1(Execute.scala:269)
[error] at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:178)
[error] at sbt.CompletionService$$anon$2.call(CompletionService.scala:37)
[error] at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error] at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error] at java.lang.Thread.run(Thread.java:748)
[error] (Docker / publishLocal) Nonzero exit value: 127
涉及的版本:
播放 2.7.3 Scala 2.12.8 Docker 19.03.1 sbt 1.2.8在我的 build.sbt 中我添加了:
enablePlugins(AshScriptPlugin)
dockerBaseImage := "openjdk:jre-alpine"
按照此处提供的说明进行操作:https://www.scala-sbt.org/sbt-native-packager/formats/docker.html#busybox-ash-support
Play 尝试执行的 Docker 命令:
show dockerCommands
[info] Wrote /Users/xxxxx/projects/together/togrx/target/scala-2.12/together-rx_2.12-0.7.0-a.pom
[info] * Cmd(FROM,WrappedArray(openjdk:8-jre-alpine, as, stage0))
[info] * Cmd(WORKDIR,WrappedArray(/opt/docker))
[info] * Cmd(COPY,WrappedArray(opt /opt))
[info] * Cmd(USER,WrappedArray(root))
[info] * ExecCmd(RUN,List(chmod, -R, u=rX,g=rX, /opt/docker))
[info] * ExecCmd(RUN,List(chmod, u+x,g+x, /opt/docker/bin/together-rx))
[info] * DockerStageBreak
[info] * Cmd(FROM,WrappedArray(openjdk:8-jre-alpine))
[info] * Cmd(USER,WrappedArray(root))
[info] * Cmd(RUN,List(id, -u, demiourgos728, 2>, /dev/null, ||, useradd, --system, --create-home, --uid, 1001, --gid, 0, demiourgos728))
[info] * Cmd(WORKDIR,WrappedArray(/opt/docker))
[info] * Cmd(COPY,WrappedArray(--from=stage0 --chown=demiourgos728:root /opt/docker /opt/docker))
[info] * Cmd(EXPOSE,WrappedArray(4300 4301))
[info] * Cmd(USER,WrappedArray(1001))
[info] * ExecCmd(ENTRYPOINT,List(/opt/docker/bin/together-rx))
[info] * ExecCmd(CMD,List())
【问题讨论】:
【参考方案1】:alpine 镜像中没有useradd
命令,请改用adduser
,见下:
$ docker run -it openjdk:jre-alpine /bin/sh
Unable to find image 'openjdk:jre-alpine' locally
jre-alpine: Pulling from library/openjdk
[DEPRECATION NOTICE] registry v2 schema1 support will be removed in an upcoming release. Please contact admins of the docker.io registry NOW to avoid future disruption.
8e3ba11ec2a2: Pull complete
311ad0da4533: Pull complete
391a6a6b3651: Pull complete
Digest: sha256:016a7989474f1e685da966631ba6403cb349548621ebb8e4a6205f7c5fa88320
Status: Downloaded newer image for openjdk:jre-alpine
/ # useradd
/bin/sh: useradd: not found
/ # echo $?
127
/ # adduser
BusyBox v1.28.4 (2018-05-30 10:45:57 UTC) multi-call binary.
Usage: adduser [OPTIONS] USER [GROUP]
Create new user, or add USER to GROUP
-h DIR Home directory
-g GECOS GECOS field
-s SHELL Login shell
-G GRP Group
-S Create a system user
-D Don't assign a password
-H Don't create home directory
-u UID User id
-k SKEL Skeleton directory (/etc/skel)
/ #
因此,您需要修改build.sbt
或其他内容以确保使用adduser
而不是useradd
。
更新:
如你所说,useradd
是play framework生成的,那么我建议你自定义自己的图片添加useradd
,它在shadow包中,那么play framework就透明了,像下一个:
Dockerfile:
FROM openjdk:jre-alpine
RUN apk add shadow
在本地 docker 主机中构建映像:
docker build -t myimage .
最后,在 build.sbt 中:
dockerBaseImage := "myimage"
【讨论】:
你知道我应该如何修改那个命令吗?我猜有一个文件定义了这些命令。 这个项目不是你写的?grep -rn "useradd" *
找不到?我猜通常它在 build.sbt、Build.scala 等东西中。
我自己编写了应用程序,但该命令来自 Play 框架 2.7.3。
我正在尝试测试您的解决方案,但问题是我必须从头开始重写所有命令才能使用 dockerCommands += Cmd("RUN","apk add shadow")
在正确的位置添加“阴影”=> @987654322 @
不,你不需要那样做。您可以认为 myimage
是您构建之外的基础设施,与 scala 代码无关。你只需构建这个镜像,并在 build.sbt 中指定它dockerBaseImage := "myimage"
。我猜当你做dockerBaseImage := openjdk:jre-alpine
时,插件会从dockerhub下载openjdk:jre-alpine
,现在你只需使用你自己的图像,其中预装了useradd
。以上是关于如何使用 jre-alpine 基础镜像创建 Scala Play 应用程序的 Docker 镜像的主要内容,如果未能解决你的问题,请参考以下文章