【问题标题】:How to give port number for docker container at run time?如何在运行时为 docker 容器提供端口号?
【发布时间】:2019-11-10 07:11:22
【问题描述】:

我已经编写了一个基于 Scala 和 Akka HTTP 的 REST API 并创建了 Dockerfile 来为这个 API 创建 Docker 映像。我的 Dockerfile 如下:

FROM maven:3.6.0-jdk-8-alpine AS MAVEN_TOOL_CHAIN
COPY pom.xml /tmp/parent/
COPY data-catalogue/pom.xml /tmp/parent/data-catalogue/
COPY data-catalogue/src /tmp/parent/data-catalogue/src/
WORKDIR /tmp/parent/data-catalogue/
RUN mvn package

FROM java:openjdk-8
COPY --from=MAVEN_TOOL_CHAIN /tmp/parent/data-catalogue/target/data-catalogue-1.0-SNAPSHOT.jar /opt/data-catalogue.jar

COPY data-catalogue/src/main/resources/logback.xml /opt/logback.xml

ENTRYPOINT ["java", "-Dlogging.config=/opt/logback.xml", "-jar", "/opt/data-catalogue.jar", "prod"]
CMD ["8080"]

到目前为止一切都很好。我可以使用此映像运行一个容器。

现在的要求是在同一个 Docker 主机上使用这个镜像运行两个容器。我已经修改了 REST API 主类,以便它将必须在其上运行的端口号作为命令行参数。如果没有提供命令行参数,那么它将监听 8080 端口上的请求。

我想知道如何在启动容器时向我的 REST API 提供命令行参数?

例如:

  1. REST API 的第一个实例应该在端口 5555 上启动/运行,因此这个 5555 参数应该到达 REST API 的主类
  2. REST API 的第二个实例应该在端口 1111 上启动/运行,因此这个 5555 参数应该到达 REST API 的主类

我已尝试为此使用ENTRYPOINTCMD,但我的命令行参数根本无法到达主类,并且 REST API 仅在 8080 端口上启动。

【问题讨论】:

  • 为什么不使用ARG
  • 我对 Docker 还很陌生,所以不知道这个 ARG。会尝试并让你知道。谢谢
  • 我给你加了一个例子
  • 你的意思是你的容器端口应该是5555和1111?您需要将它们映射到主机吗?
  • @deosha 是的。主机应该将 5555 上的请求转发到容器 5555 端口,并且我的 AKKA REST API 也应该开始监听 5555 端口

标签: scala rest docker containers akka-http


【解决方案1】:

Docker 端口映射是您的答案。

Docker 化您的 API 与为您的 API 提供您希望每次运行它的端口完全相反。这正是您在采用 Docker 方式时不想做的事情。

您的 API 应该能够通过您决定在 docker 映像上使用 EXPOSE 的任何端口来处理您的请求,然后,在运行时,您只需将您希望的任何端口从您的主机映射到内部端口您的 API (在其容器内,将始终关注相同的“内部”端口。

那么..它看起来怎么样?

docker run -d --name api-1 -p 5555:8080 my/api

然后……

docker run -d --name api-2 -p 1111:8080 my/api

现在两个实例都在您的主机上运行,​​您可以同时访问它们,每个都有不同的主机端口(即使它们在内部使用相同的端口号)

【讨论】:

  • 更多关于这个 binding / port-publish 功能here 以及更多关于基本 docker 容器网络的指导 here 享受 ;)
  • 非常感谢。这正是我一直在寻找的。不知何故,我假设两个 docker 容器将无法监听同一个端口。端口映射是答案的关键。
【解决方案2】:

通过环境变量

在 Dockerfile 中:

ENV PORT 8080 

您可以通过传递 -e 来覆盖 cmd 上的上述 env,例如

docker run -d my_image -e "PORT=5555"

在您的应用程序代码中使用env

所以例如如果您没有在 cmd 上提供 env,您的应用程序代码将收到 8080 作为 PORT 值。如果您确实覆盖了 cmd 上的 env,您的应用程序代码将收到 5555 作为 PORT 值

【讨论】:

    【解决方案3】:

    您可以将 ARG 设置为您的容器:

    ARG MYPORT
    

    然后像这样导出它:

    CMD [ $MYPORT ]
    

    然后像这样启动你的d​​ocker:

    export MYPORT=5000 ; docker run ....
    

    【讨论】:

    • 我认为您可以从 SYS ENV 读取 valur 或在使用 sed 构建映像时替换它
    • 好的。我认为从 SYS ENV 读取数据很好,但在构建过程中添加它不会有帮助,因为我不想创建单独的容器只是为了使用不同的端口。
    猜你喜欢
    • 2020-11-07
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-20
    • 1970-01-01
    相关资源
    最近更新 更多