gpt4 book ai didi

docker - 无法获取域的 ACME 证书 - 尝试在 docker 上的虚拟本地主机中设置 HTTPS

转载 作者:行者123 更新时间:2023-12-05 01:25:28 28 4
gpt4 key购买 nike

我正在尝试为虚拟主机 local.example.com 上本地运行的 React 应用程序设置证书。这必须只在 docker setup 上本地工作。在浏览了一些文章之后,我想到了这个 docker-compose.yml:

version: "3"
services:
mongo:
image: mongo
restart: always
ports:
- "27017:27017"
volumes:
- mongodbdata:/data/db
networks:
- proxy
mongo-express:
image: mongo-express
restart: always
ports:
- "8081:8081"
networks:
- proxy
react:
build:
context: ./client
dockerfile: ./Dockerfile
ports:
- "3001:3001"
stdin_open: true
volumes:
- ./client:/client
- /client/node_modules
labels:
# this enables traefik for your service
- "traefik.enable=true"
# this defines the url, traefik will get the ssl certificate for
- "traefik.http.routers.myapplication.rule=Host(`local.example.com`)"
# this tells traefik to use https to access the website
- "traefik.http.routers.myapplication.entrypoints=websecure"
# this tells traefik to use the certresolver, that we defined above for resolving tls (in our case letsencrypt)
- "traefik.http.routers.myapplication.tls.certresolver=myresolver"
# this let's us forward the port we set above. Change this to the port you expose in your application (3000, 4000, ...) or remove the line, if your application already exposes port 80/443
- "traefik.http.services.myapplication.loadbalancer.server.port=3000"
depends_on:
- "server"
networks:
- proxy
server:
build:
context: ./server
dockerfile: ./Dockerfile
ports:
- "5001:5001"
volumes:
- traefik.toml:/traefik.toml
- acme.json:/acme.json
- ./server:/server
- /server/node_modules
labels:
# this enables traefik for your service
- "traefik.enable=true"
# this defines the url, traefik will get the ssl certificate for
- "traefik.http.routers.myapplication.rule=Host(`local.example.com`)"
# this tells traefik to use https to access the website
- "traefik.http.routers.myapplication.entrypoints=websecure"
# this tells traefik to use the certresolver, that we defined above for resolving tls (in our case letsencrypt)
- "traefik.http.routers.myapplication.tls.certresolver=myresolver"
# this let's us forward the port we set above. Change this to the port you expose in your application (3000, 4000, ...) or remove the line, if your application already exposes port 80/443
- "traefik.http.services.myapplication.loadbalancer.server.port=5001"
depends_on:
- "mongo"
networks:
- proxy
whoami:
image: "containous/whoami"
container_name: "myapplication"
restart: unless-stopped
ports:
- "4000:4000"
networks:
- proxy

traefik:
image: "traefik:v2.2"
container_name: "traefik"
command:
# this can be uncommented to get more information, in case something doesn't work
- "--log.level=DEBUG"
# set this to true to get access to the traefik web interface unter http://YOURIP:8080
- "--api.insecure=false"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.httpchallenge=true"
- "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory" # uncomment this line to only test ssl generation first (to make sure you don't run into letsencrypt limits)
- "--certificatesresolvers.myresolver.acme.email=kamlekar.venkatesh@gmail.com"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
- "8080:8080" # this is used for the web interface, that let's you check and monitor traefik and your configuration. It's very nice for debugging your config - only available if "api.insecure" above is set to true
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- proxy
# The following is only necessary if you want to enforce https!
# if you don't need that, you can just remove the labels here
labels:
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"

networks:
proxy:
external: true

volumes:
mongodbdata:
traefik.toml:
acme.json:

在执行 docker-compose up 时,我在 traefik 服务中看到以下错误。此外,尽管 React 应用程序服务正在 docker 中运行,但我点击了 https://local.example.com:3001,但无法访问

time="2022-01-23T08:30:52Z" level=error msg="Unable to obtain ACME certificate for domains "local.example.com": unable to generate a certificate for the domains [local.example.com]: error: one or more domains had a problem:\n[local.example.com] acme: error: 400 :: urn:ietf:params:acme:error:dns :: DNS problem: NXDOMAIN looking up A for local.example.com - check that a DNS record exists for this domain; DNS problem: NXDOMAIN looking up AAAA for local.example.com - check that a DNS record exists for this domain, url: \n" providerName=myresolver.acme routerName=myapplication@docker rule="Host(local.example.com)"

这是 research notes我尝试到现在(这些笔记仅供个人理解,因此可能不详细)

你可以从这个 fiddle 开始:https://github.com/kamlekar/react-docker-ssl-virtualhost

最佳答案

您需要使用 TLS 进行本地设置。您需要证书的主机是 local.example.com。无法从 Letsencrypt 获得此名称的证书,因为您没有控制 example.com 域。 Letsencrypt 创建证书的方法之一是一个挑战 - 您通过创建 TXT DNS record 来证明您拥有该域.如果您拥有一个域,则可以这样做,但您的情况有所不同,因为您只需要将其用于本地开发。

但是,您可以只使用 openssl 为您想要的任何域名生成自签名证书。 This is a good reference on how to do this.您可以为生成的证书使用 local.example.com 域名。如果你成功了,你最终会得到证书和它的私钥。请注意保存这些文件的位置,因为您将需要它们。请记住,该证书是自签名的,因此您的浏览器会向您发出警告,除非您将此证书添加到操作系统的信任库中。

您的下一步是让 Traefik 在从您的应用程序提供内容时使用这些自签名证书。我想this answer有一个很好的例子。

有了这个之后,你只需要 edit your hosts file并将您的 localhost:8080(您的 Traefik 为您的应用程序提供服务的端口)重定向到 local.example.com

此外,Traefik 并不是您的案例的唯一解决方案。例如,您也可以使用 Nginx 实现相同的目的。选择满足您的用例的一个。我的建议是使用最容易配置的那个,因为它用于本地开发。 Here's the first result I got在搜索 nginx docker-compose 自签名证书 时。

更新
这是我上面描述的内容的一个简单示例。
首先生成证书:

openssl req -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -sha256 -days 1000 -subj '/CN=local.example.com'

您最终会在当前目录中得到两个文件(key.pemcert.pem)。现在创建 nginx.conf:

worker_processes 1;

events {
worker_connections 1024;
}

http {
server {
listen 443 ssl;
server_name local.example.com;

ssl_certificate cert.pem;
ssl_certificate_key key.pem;

ssl_session_timeout 5m;

location / {
proxy_pass http://myapp:8080;
proxy_set_header Host $host;
proxy_read_timeout 1800;
proxy_connect_timeout 1800;
}
}
}

现在 docker-compose.yaml 文件:

version: "3"

services:
nginx:
image: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./cert.pem:/etc/nginx/cert.pem
- ./key.pem:/etc/nginx/key.pem
ports:
- "443:443"
networks:
- local-dev-01

myapp:
image: your-react-app-image
command: "command-that-starts-your-app"
networks:
- local-dev-01

networks:
local-dev-01:

Docker 为您创建了一个名为 local-dev-01 的网络,它允许这两个服务能够通过它们的名称相互解析。这就是为什么我们在 nginx.conf 中有 myapp:8080。我们还为 local.example.com 安装配置和生成的证书和 key 。
最后一步是编辑您的 hosts 文件并添加以下行:

127.0.0.1      local.example.com

之后,您应该可以轻松地在您的机器上通过 https://local.example.com 访问您的应用程序。请记住,您的浏览器会不断警告您该证书是自签名的,因此您应该将其添加为异常(exception)。

关于docker - 无法获取域的 ACME 证书 - 尝试在 docker 上的虚拟本地主机中设置 HTTPS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70820375/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com