在 docker 容器内使用带有 ssl 的自托管(Jetty)配置数据库时出错

问题描述 投票:0回答:3

我正在尝试在启用了 ssl 的 Docker 容器内设置一个自托管(Jetty)元数据库。

首先,我使用

certbot
创建了
fullchain.pem
privkey.pem,然后使用
this gist
转换为 keystore.jks

然后创建一个 .env 文件,用于

--env-file
docker 标志:

MB_DB_FILE=/metabase/metabase.db
MB_JETTY_SSL=true
MB_JETTY_SSL_PORT=443
MB_JETTY_SSL_KEYSTORE=./keystore.jks
MB_JETTY_SSL_KEYSTORE_PASSWORD=my-pass

并尝试运行:

docker run -p 80:3000 -v ~/metabase:/metabase --env-file "./prod.env" --name metabase metabase/metabase

但是我收到以下错误:

ERROR metabase.core :: Metabase Initialization FAILED
java.net.SocketException: Permission denied
    at sun.nio.ch.Net.bind0(Native Method) ~[?:?]
    at sun.nio.ch.Net.bind(Unknown Source) ~[?:?]
    at sun.nio.ch.Net.bind(Unknown Source) ~[?:?]
    at sun.nio.ch.ServerSocketChannelImpl.bind(Unknown Source) ~[?:?]
    at sun.nio.ch.ServerSocketAdaptor.bind(Unknown Source) ~[?:?]
    at org.eclipse.jetty.server.ServerConnector.openAcceptChannel(ServerConnector.java:345) ~[metabase.jar:?]
    at org.eclipse.jetty.server.ServerConnector.open(ServerConnector.java:310) ~[metabase.jar:?]
    at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:80) ~[metabase.jar:?]

通过将 SSL_PORT 更改为 8443 来解决,因此新的 env 文件如下所示:

MB_DB_FILE=/metabase/metabase.db
MB_JETTY_SSL=true
MB_JETTY_SSL_PORT=8443
MB_JETTY_SSL_KEYSTORE=./keystore.jks
MB_JETTY_SSL_KEYSTORE_PASSWORD=my-pass

删除了旧容器并使用上面的 env 文件启动了一个新容器,但现在我陷入了这个错误:

ERROR metabase.core :: Metabase Initialization FAILED
java.lang.IllegalStateException: /"./keystore.jks" is not a valid keystore

我已经使用 this 仔细检查了我的 .jks 文件是否有效。确实如此。

我的问题是:

  1. 为什么我无法在443上运行
  2. 为什么我的密钥库无效?

编辑1:

跟进 Joakim 的建议:

改成绝对路径

MB_DB_FILE=/metabase-prod-data/metabase.db
MB_JETTY_SSL=true
MB_JETTY_SSL_PORT=8443
MB_JETTY_SSL_KEYSTORE=/root/services/metabase/setup/keystore.jks
MB_JETTY_SSL_KEYSTORE_PASSWORD=my-pass

出现此错误:

ERROR metabase.core :: Metabase Initialization FAILED
java.lang.IllegalStateException: /root/services/metabase/setup/keystore.jks is not a valid keystore
java docker ssl jetty metabase
3个回答
1
投票

@Joakim 回答了为什么不使用 443 端口

我也遇到了元数据库初始化的问题。 我遇到的错误是主机上的密钥库文件在 docker 容器内无法访问。

我使用了 docker-compose yml 文件。您也可以搜索基于终端的方式。

我通过使用卷属性在具有证书的主机上添加文件夹来使其可访问。

metabase:
   ...
    env_file:
      - ./config/metabase.env
    volumes:
      - <LOCAL_PATH>:<CONTAINER_PATH>

环境路径内:

MB_JETTY_SSL_KEYSTORE:<CONTAINER_PATH>/keystore.jks


1
投票

443 是大多数操作系统上的受限端口,需要 root/超级用户/管理员权限才能绑定到它。

找不到您的密钥库,该路径无效。
这个错误只是令人困惑。

您的配置

MB_JETTY_SSL_KEYSTORE=./keystore.jks

尝试将其设为绝对路径,因为元数据库显然只是将您提供的内容附加到其他路径的末尾

/
(在您的情况下)。


0
投票

我用头撞墙两个小时才意识到问题所在,TLDR:权限。

我正在使用安装在docker主机上的letencrypt,SSL证书由主机更新,然后有一个部署钩子可以生成密钥库文件并重新启动元数据库的docker。

我使用以下命令创建了 docker:

docker run -d -p 80:3000 -p 443:8443 \
  -v /etc/letsencrypt/:/etc/letsencrypt/ \
  -e "MB_DB_TYPE=postgres" \
  -e "MB_DB_DBNAME=metabase" \
  -e "MB_DB_PORT=5432" \
  -e "MB_DB_USER=metabase" \
  -e "MB_DB_PASS=dbpass" \
  -e "MB_DB_HOST=dbhost.com" \
  -e "MB_JETTY_SSL=true" \
  -e "MB_JETTY_SSL_PORT=8443" \
  -e "MB_JETTY_SSL_KEYSTORE=/etc/letsencrypt/live/somedomain.com/jetty.keystore" \
  -e "MB_JETTY_SSL_KEYSTORE_PASSWORD=somepass" \
  --restart always \
  --name metabase metabase/metabase

现在的问题是我也收到了“xxx不是有效的密钥库”错误,我最终意识到,这并不是密钥无效,也不是无法“找到”它,只是无法访问

我尝试从容器内运行的 shell 读取密钥库,并且成功了,所以我感到困惑。我终于意识到,在容器内,元数据库正在以名为“metabase”的用户运行,而不是“root”。这意味着即使可以使用容器内的 root 访问密钥文件,元数据库的进程也无法访问该密钥文件。

此外,简单地对密钥文件进行 chmoding 777 并没有帮助,这起初让我感到困惑,但我很快就记住,文件具有正确的权限是不够的,整个路径都需要具有正确的权限。所以,长话短说,要解决这个问题:

  1. 确保密钥库文件的权限设置为777,以便容器内的“metabase”用户可以直接读取。
  2. 将主机上的文件直接映射到容器的元数据库用户可以访问的目录。

例如:

docker run -d -p 80:3000 -p 443:8443 \
  -v /etc/letsencrypt/live/somedomain.com/jetty.keystore:/app/jetty.keystore \
  -e "MB_DB_TYPE=postgres" \
  -e "MB_DB_DBNAME=metabase" \
  -e "MB_DB_PORT=5432" \
  -e "MB_DB_USER=metabase" \
  -e "MB_DB_PASS=dbpass" \
  -e "MB_DB_HOST=dbhost.com" \
  -e "MB_JETTY_SSL=true" \
  -e "MB_JETTY_SSL_PORT=8443" \
  -e "MB_JETTY_SSL_KEYSTORE=/app/jetty.keystore" \
  -e "MB_JETTY_SSL_KEYSTORE_PASSWORD=somepass" \
  --restart always \
  --name metabase metabase/metabase

作为奖励,这个单行创建了一个部署钩子,在证书续订时,重新创建最新的密钥库文件,将其权限设置为 777 并重新启动容器:

sudo sh -c 'printf "#!/bin/sh\nexport KEYSTORE_PASSWORD=\"somepass\"\nrm /etc/letsencrypt/live/somedomain.com/jetty.keystore\nopenssl pkcs12 -export -inkey /etc/letsencrypt/live/somedomain.com/privkey.pem -in /etc/letsencrypt/live/somedomain.com/fullchain.pem -out /etc/letsencrypt/live/somedomain.com/jetty.pkcs12 -passout pass:p \nkeytool -importkeystore -noprompt -srckeystore /etc/letsencrypt/live/somedomain.com/jetty.pkcs12 -srcstoretype PKCS12 -srcstorepass p -destkeystore /etc/letsencrypt/live/somedomain.com/jetty.keystore -deststorepass \$KEYSTORE_PASSWORD\nrm /etc/letsencrypt/live/somedomain.com/jetty.pkcs12\nchmod 777 /etc/letsencrypt/live/somedomain.com/jetty.keystore\ndocker restart metabase\n" > /etc/letsencrypt/renewal-hooks/deploy/metabase.sh'

© www.soinside.com 2019 - 2024. All rights reserved.