我试图找到一种方法来发布nginx,express,和letsencrypt的ssl一起使用坞-撰写。关于这方面有很多文档,所以我引用了这些文档并尝试进行自己的配置,成功地从这个nginx + ssl配置了https://medium.com/@pentacent/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71。
因此,现在我想把样例nodejs express应用程序放到nginx + ssl对接-撰写中。但我不知道为什么,我从nginx获得502 Bad Gateway,而不是express的初始页面。
我正在用左域名测试这个应用程序,并在aws ec2 ubuntu16上进行测试。我认为域dns和安全规则设置没有问题。所有80,443,3000个港口已经开放。当我在没有特快应用的情况下测试它时,它显示了很好的nginx默认页面。
nginx conf in /etc/nginx/conf.d
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com;
server_tokens off;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
ssl_certificate /etc/letsencrypt/live/sendpi.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sendpi.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}docker-compose.yml
version: '3'
services:
app:
container_name: express
restart: always
build: .
ports:
- '3000:3000'
nginx:
container_name: nginx
image: nginx:1.15-alpine
restart: unless-stopped
volumes:
- ./data/nginx:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
ports:
- "80:80"
- "443:443"
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
certbot:
image: certbot/certbot
restart: unless-stopped
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"特快文档
FROM node:12.2-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]我认为SSL运行良好,但express app和nginx之间存在一些问题。我怎么才能解决这个问题?
发布于 2019-09-01 04:20:58
proxy_pass http://localhost:3000正在将请求代理到运行nginx的容器上的3000端口。相反,您希望连接到运行express的容器的3000端口。为此,我们需要做两件事。
首先,我们让nginx容器在预定义的主机名下可见。我们可以将链接应用于船坞写作.
nginx:
links:
- "app:expressapp"或者,由于链接现在被认为是遗留特性,更好的方法是使用用户定义的网络。定义一个你自己的网络
docker network create my-network 然后通过在顶层添加以下内容,将容器连接到撰写文件中的网络:
networks:
default:
external:
name: my-network连接到用户定义网络的所有服务都可以通过名称相互访问,而无需显式设置链接。
然后在nginx.conf中,我们使用该主机名代理到快递容器:
location / {
proxy_pass http://app:3000
}发布于 2019-09-01 23:07:04
警告:
--link标志是Docker的遗留特性。它最终可能会被移除。除非您绝对需要继续使用它,否则我们建议您使用用户定义网络来方便两个容器之间的通信,而不是使用--link。
在docker-compose.yml中定义网络并使用适当的网络配置服务:
version: '3'
services:
app:
restart: always
build: .
networks:
- backend
expose:
- "3000"
nginx:
image: nginx:1.15-alpine
restart: unless-stopped
depends_on:
- app
volumes:
- ./data/nginx:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
networks:
- frontend
- backend
ports:
- "80:80"
- "443:443"
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
certbot:
image: certbot/certbot
restart: unless-stopped
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
networks:
frontend:
backend:注意事项:app服务不再将它的端口发布到主机,它只公开端口3000 (ref )。( 公开和发布端口),它仅适用于连接到backend网络的服务。nginx服务在backend和frontend网络中都有一只脚,可以接收来自frontend的传入流量,并代理到backend中的app连接(ref )。多主机联网)。
使用用户定义网络,您可以解析服务名称:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
upstream app {
server app:3000 max_fails=3;
}
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com;
server_tokens off;
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
ssl_certificate /etc/letsencrypt/live/sendpi.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sendpi.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
}从服务中删除container_name使规模服务成为可能:docker-compose up -d --scale nginx=1 app=3 - nginx将负载平衡循环中的流量转到3 app容器。
发布于 2019-09-01 04:47:24
我认为,这里的一个原因可能是"localhost“名称在docker-compose中运行的服务之间的行为方式。按照docker-组合您的容器的方式,每个容器都将自己理解为"localhost",因此"localhost“并不指主机(如果我没有弄错,那么运行在主机上的容器就无法访问主机端口上公开的服务,除了一些安全漏洞之外)。展示:
services:
app:
container_name: express
restart: always
build: .
ports:
- '2999:3000' # expose app's port on host's 2999重建
docker-compose build
docker-compose up告诉运行快递应用程序的容器在3000端口上使用它自己的运行服务:
$ docker-compose exec app /bin/bash -c "curl http://localhost:3000"
<!DOCTYPE html>
<html>
<head>
<title>Express</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1>Express</h1>
<p>Welcome to Express</p>
</body>
</html>告诉app尝试使用我们在主机上的端口2999上公开的服务:
$ docker-compose exec app /bin/bash -c "curl http://localhost:2999"
curl: (7) Failed to connect to localhost port 2999: Connection refused当然,在运行容器之间也会看到同样的行为,因此在您的设置中,nginx试图代理它在localhost上运行的自己的服务:3000(但正如您所知,没有一个)。
https://stackoverflow.com/questions/57743088
复制相似问题