在一台服务器上用一个域名部署多个项目
写在前面
当你学一个新的技术的时候一直听别人讲,是学不会的。
一定要每学一个东西就自己去动手做点什么。脑子里有一个自己的想法,然后不停的去百度,你在解决这个问题的时候,碰踩过的坑,遇到和遇到的过程都会让你对这个知识本身理解的更加透彻。
所以一篇厉害的小作文并不能教会你什么,他只是告诉你一个方向,至于最后能不能做出来是需要你自己去不断尝试的。写好项目只有一个方法,多动手多百度。
如果对项目换自己域名不熟悉的同学可以参考:
大佬空间:
==在此感谢先行者们的分享,能让我们站在巨人的肩膀上更快的解决问题==
由于有很多同学在尝试,也遇到了许多我之前没有遇到的问题,有的我也无法解决,实在是能力有限
这里我也收集了其他同学尝试了我的方法,成功之后写的博客,如果有什么问题,大家也可以参考
其他同学解决问题的优秀博客
需要准备的东西
硬件
- 云服务器一台
- 域名一个(已经完成备案的)
软件
- docker
- nginx
最好全程在root用户下完成
下载docker
y总讲过,这里不写
下载nginx
为了加速下载,还可以配置阿里云容器镜像加速,方法:自己百度
apt-get update
apt-get install nginx
为什么要用nginx
==是因为你购买域名之后,会发现:DNS无法解析 IP地址加端口号
这一格式的地址。==
计算机或者服务器的每一个服务或者进程都是对应一个端口号的。我们在一个服务器想部署多个项目,本质上就是把不同的服务运行在不同的端口,然后用域名的不同二级域名去解析每一个项目。但是DNS无法直接做到这一点,那么就需要一个,帮你把不同网址发来的请求去转发到不同端口上的一层代理。他就是nginx
其实nginx
的主要作用是把实现负载均衡把一个项目分布到不同服务器上,来降低服务器的负载压力。这里用它来部署多个项目,其实是杀鸡用牛刀
。
用nginx部署y总项目前的一个天坑
这个坑当时困扰了我好几周,大家一定要认真阅读
首先nginx
是默认运行在80端口的。
但是回想y总的容器会发现,y总把80端口映射在了80端口,443端口,443端口映射在了443端口,那么会导致一个问题,如果你想在你服务器上配置一个nginx
那么80端口已经被y总容器内的nginx
占用。你在你的服务器上nginx
就无法运行。
解决方法1
当然我一开始没有想到一个好的解决办法,只能退而求其次。就是将y总容器内部的nginx
作为控制所有项目的大脑
。即用容器内部的去转发所有的请求,配置你服务器上的多个项目。
但这又带来了一个新的问题,就是其他项目的容器和y总项目的容器耦合性太高。一旦y总项目的容器重启或者停止,那么y总容器里的nginx
服务也停止,这样你的其他的所有项目就都无法正确解析。
本来这个问题就这样以一个将就的方式解决了。但是在之前的课设中,我需要同时展示y总的项目和我的Java项目和docker的作用,这就要求我必须
将所有项目的容器解耦
,于是我再次直面了这个问题。在看完的b站3个nginx的教程,和大量百度后。我开始研究如何改动y总项目内部nginx
的配置文件
解决方法二:将所有nginx配置写在一个nginx中
这个方法也比较合理,但坏处就是你需要对每个项目的nginx配置文件进行大修改,同时项目也不方便迁移
解决方法3:两层nginx代理
实际上,每一个项目都有自己独立的nginx配置,想要做到真正解耦,方法3显然是更合理的
改造y总容器
如果对项目换自己域名不熟悉的同学可以参考:
大佬空间:
==在此感谢先行者们的分享,能让我们站在巨人的肩膀上更快的解决问题==
下面所有操作建议在服务器的root用户下运行
1.解除容器对80端口的占用
因为nginx是默认运行在80端口,不同的两个nginx
服务不能同时监听80端口。所以要将容器内的nginx
的80端口映射到主机的其他端口上。443端口同理。因为这里我并没有准备给所有的项目配置SSL。所以我只解除了80端口的占用,没有改443的。
docker不删除容器改端口号的方法
-
先用
docker ps -a
查看并记住你要改容器的id -
停止docker服务
systemctl stop docker
- 更改端口映射
1.这里的容器id就是以你第一步记住的id开头的一个长字符串
2.编辑/var/lib/docker/containers/容器id/hostconfig.json
,容器id就是以上面那个字符串为前缀的字符串在里面就能修改端口映射
- 启动docker服务
systemctl start docker
- 启动
所有
docker容器
docker start `docker ps -aq`
改完端口映射后一定要检查是否已经修改成功!
2.进入y总容器,修改配置文件nginx.conf
1.先进入y总容器,并切换为root用户
2.修改配置文件
vim /etc/nginx/nginx.conf
如何修改
我把一个详细的案例单独写在了下面这篇文章中
nginx快速配置多个项目上手(含一个详细案例) - AcWing
修改的关键
现在思考2个问题:
- nginx的作用是什么
- 对于每个项目中的nginx(第二层的nginx)来说,第一层的nginx的
地址
是什么?
nginx是一个请求代理服务
,它会监听和拦截某个端口的所有请求,实现控制转发和重定向
对所有第二层的nginx来说,第一层nginx的地址是localhost
!!!!
明白了关键道理,一切就变的容易起来!!
修改配置文件nginx.conf
改完以后要记得重新加载配置文件
sudo nginx -s reload
就是这么简单!!
配置服务器上的第一层nginx
nginx快速配置多个项目上手(含一个详细案例) - AcWing
看完案例,这一步就太简单了
1.先在服务器的root用户下下载nginx
为了加速下载,还可以配置阿里云容器镜像加速,方法:自己百度
apt-get update
apt-get install nginx
2.配置nginx.conf
进入nginx配置文件
vim /etc/nginx/nginx.conf
添加的配置
要添加配置,其实就是添加2个server
server {
listen 80;
server_name appxxx.acapp.acwing.com.cn #或者是你自己的域名
location / {
#这里的127.0.0.1指本机ip地址
proxy_pass http://127.0.0.1:8000; #要代理转发的端口号
}
}
#项目二
server {
listen 80;
server_name yyy.xxx.com; #你的第二个二级域名
location / {
proxy_pass http://127.0.0.1:8080;
}
}
就是这么简单
第一层完整的nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
server {
listen 80;
server_name appxxx.acapp.acwing.com.cn #或者是你自己的域名
location / {
#这里的127.0.0.1指本机ip地址
proxy_pass http://127.0.0.1:8000; #要代理转发的端口号
}
}
#项目二
server {
listen 80;
server_name yyy.xxx.com; #你的第二个二级域名
location / {
proxy_pass http://127.0.0.1:8080;
}
}
}
改完以后要记得重新加载配置文件
sudo nginx -s reload
详细项目与源码
首先说一下背景,我写了4个项目,买了一个域名,想让每个项目都能通过域名访问
这4个项目的docker配置
第一层(服务器上)的整个nginx配置文件
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
server {
listen 80;
server_name www.liuyutao666.top;
location / {
proxy_pass http://127.0.0.1:20022;
}
}
server {
listen 80;
server_name blog.liuyutao666.top;
location / {
proxy_pass http://127.0.0.1:20022;
}
}
server {
listen 80;
server_name hexo.liuyutao666.top;
location / {
proxy_pass http://127.0.0.1:20007;
}
}
server {
listen 80;
server_name dockers.liuyutao666.top;
location / {
proxy_pass http://127.0.0.1:20001;
}
}
server {
listen 80;
server_name ruoyi.liuyutao666.top;
location / {
proxy_pass http://127.0.0.1:20008;
}
}
server {
listen 80;
server_name webchat.liuyutao666.top;
location / {
proxy_pass http://127.0.0.1:20009;
}
}
server {
listen 80;
server_name game.liuyutao666.top;
location / {
proxy_pass http://127.0.0.1:20015;
}
}
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
y总docker内部的nginx配置文件
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
server {
listen 80;
server_name localhost;
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
server {
listen 443 ssl;
server_name localhost;
ssl_certificate cert/acapp.pem;
ssl_certificate_key cert/acapp.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
charset utf-8;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
client_max_body_size 10M;
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass 127.0.0.1:8000;
uwsgi_read_timeout 60;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://www.acwing.com';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Max-Age' 86400;
add_header 'Content-Type' 'text/html; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'PUT') {
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' 'https://www.acwing.com';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
location /static {
alias /home/doctao/acapp/static/;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://www.acwing.com';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Max-Age' 86400;
add_header 'Content-Type' 'text/html; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'PUT') {
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' 'https://www.acwing.com';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
location /media {
alias /home/doctao/acapp/media/;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://www.acwing.com';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Max-Age' 86400;
add_header 'Content-Type' 'text/html; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'PUT') {
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' 'https://www.acwing.com';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
location /wss {
proxy_pass http://127.0.0.1:5015;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
另一个后台管理项目的nginx配置文件
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /home/ruoyi/projects/ruoyi-ui;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/{
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://ruoyi-server:8080/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}# requirepass 123456
创作不宜,如要转载,请私聊作者个人空间 - AcWing
完结撒花~
所以如果只是放开了对80端口的监听分配,其他docker的都是支持http而不是https协议吗
执行uwsgi –ini scripts/uwsgi.ini命令时
出现realpath() of scripts/uwsgi.ini failed: No such file or directory [core/utils.c line 3662]
怎么解决
牛蛙牛蛙
棒!
前排资瓷