docker - 用户应该拥有哪些权限才能公开 docker 容器端口?
问题描述
我在 docker 容器上设置 puppeteer。尝试根据他们的故障排除页面https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#running-on-alpine进行操作。
但是在创建和使用新用户(pptruser)后,服务器无法公开端口 80,因为用户没有权限Error: listen EACCES 0.0.0.0:80
。
找不到关于我应该添加给该用户的权限的明确文档,以便用户可以 EXPOSE $PORT
尝试将用户添加到 sudo 并没有奏效,但另一方面,即使这有效,我认为这是一个错误,因为它存在安全风险。
在开始使用新用户之前尝试公开端口,这也失败了。
Dockerfile
FROM node
# Installs latest Chromium (72) package.
RUN apk update && apk upgrade && \
echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories && \
echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories && \
apk add --no-cache \
chromium@edge \
nss@edge \
freetype@edge \
harfbuzz@edge \
ttf-freefont@edge \
udev
RUN mkdir -p /app
WORKDIR /app
# Tell Puppeteer to skip installing Chrome. We'll be using the installed package.
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
# Add user so we don't need --no-sandbox.
RUN addgroup -S pptruser && adduser -S -g pptruser pptruser \
&& mkdir -p /home/pptruser/Downloads \
&& chown -R pptruser:pptruser /home/pptruser \
&& chown -R pptruser:pptruser /app
ENV PORT 80
ENV HTTP_PORT $PORT
ENV HTTPS_PORT 443
EXPOSE $HTTP_PORT
EXPOSE $HTTPS_PORT
USER pptruser
CMD [ "run.sh" ]
运行.sh
#!/bin/sh
PORT="${HTTP_PORT:-80}"
node "app/bin/server.js"
日志中的错误
Error: listen EACCES 0.0.0.0:80
at Object.exports._errnoException (util.js:1020:11)
at exports._exceptionWithHostPort (util.js:1043:20)
at Server._listen2 (net.js:1258:19)
at listen (net.js:1307:10)
at Server.listen (net.js:1403:5)
at appServer.app.then.then.then (/app/bin/server.js:69:12)
任何帮助表示赞赏
解决方案
传统上 [1],只有root
用户可以绑定 1024 下的端口。但是,我认为您会发现这对于您的特定用例并不重要。服务在容器内侦听的端口与远程客户端连接到它的端口没有任何关系。“主机上暴露的端口”到“容器内监听的端口”的映射是通过 Docker 的端口发布机制来控制的。
对于您的示例,您可以将服务配置为侦听端口 80 以外的其他内容...就本示例而言,假设您将其配置为侦听端口 8080。
运行容器时,将主机上的端口 80 映射到容器内的端口 8080:
docker run -p 80:8080 ...
现在您可以在主机上的端口 80 访问您的服务。您可以以相同的方式处理端口 443。
另请注意,EXPOSE
Dockerfile 中的关键字在很大程度上是不必要的。在典型的 Docker 环境中,这是一个无操作且仅提供信息的环境。无论是否已经EXPOSE
d,您都可以发布端口。
[1] 这种情况实际上在 Linux 下更加微妙。
推荐阅读
- javascript - javascirpt 书签启用页面和文本框上所有禁用的按钮
- swiftui - SwiftUI 使用自定义模式填充形状
- python - Apache Airflow initdb 无法在 AWS EC2 上运行
- python - 拆分 Python 字符串
- angular - 是否可以完全删除 css .ng-invalid,同时使用 MatFormFields 保留验证器?
- java - java.awt.Desktop.isDesktopSupported 在 javafx 应用程序中返回 false
- c# - 向sql插入值时从字符串转换为uniqueidentifier时转换失败
- python - 如果管道中的条件为 True ,如何在蜘蛛中增加计数器?[SCRAPY-Python]
- apache-kafka - PySpark 结构化 Streaming + Kafka 错误(由:java.lang.ClassNotFoundException:org.apache.spark.sql.sources.v2.StreamWriteSupport 引起)
- postgresql - 使用 AWS Glue JOB 加载时将字符串转换为 Postgres 的 JSON 类型