在之前两篇文章《Docker初学到实战》和《Jenkins自动化部署》中,我腾讯云的微轻量服务器上安装的是CentOS(8.x版本)系统,在这个系统中安装了以Docker服务,并以容器化的方式搭建了网站《短链接转换 (freetiny.link)》,还通过Jenkins实现了CICD。
但是在之前的文章中,所有的服务都是用的IP地址访问,并没有用到域名,如果想要正式的把网站发布出去用,还需要完成域名的申请、域名的解析和SSL证书的配置。
所以我说一下我的前置条件和需求:
前置条件:
1.我已经开发并部署好了8个服务。
2.我已经申请好了两个域名(freetiny.link)和(flt.fit),原本只需要一个域名就够的,但是因为我网站的类容是短链接转换,所以转换出来的短链接域名越短越好,所以flt.fit域名作为转换后的域名,也就是我的后端API域名。freetiny.link作为网站域名,以及其他服务的域名(如阿波罗配置、Jenkins等等)。
我的需求:
因为我只有腾讯云上1台轻量服务器,我的所有服务都在这个上面,但是域名解析时http只能解析到80端口,https的访问只能解析到443端口,此时,我需要在不同域名访问时把不同的域名分发到不同的端口,这样才能指向我不同的服务。
我的分析:
首先,如果需要反向代理,域名分发那么使用nginx无疑是最好的方案。所以我需要先要搭建一个nginx的服务,并且根据在nginx上配置SLL证书,以及不同域名分发到不同端口进行访问。
但是,在我实践的过程中遇到了一个问题,nginx安装在何处比较简单方便?是用docker安装在容器中,还是直接安装在宿主机上面(也就是我的腾讯轻量服务器):
最终,结合我的环境,因为我只有一台服务器,在这服务器上装了docker,我的所有都是以容器化的方式运行在这个宿主机上的。因为以下种种原因,最后我还是决定把nginx安装在了宿主机上,以下是我的原因:
其实一开始我是把nginx以容器的方式运行在docker中的,与我的其他业务服务在同一个docker环境中。最终的结果就是,nginx监听80或443端口,然后分发到我的各个业务容器服务中,可因为nginx与其他服务是并列在docker的虚拟网络中的,所以分发时在nginx的配置文件中配置的地址和端口就是docker的虚拟网络IP和端口。好了,问题来了,因为docker容器在每次启动的时候IP地址是会动态变化的,那么就需要固定各个容器的IP地址,固定IP地址需要自己去在docker中建立一个自定义的network,如果是这样,那么会有一下几个不爽的地方:
1.因为我玩这个docker还不够熟练,不想冒然的去玩docker的network这个东西,而且据我同事说这事儿有时候还会出行一些莫名其妙的网络问题,比如容器中访问不到与宿主机平行的其他主机之类的。
2.在修改Nginx的配置文件时需要关注容服务的IP地址,排查问题时需要核对nginx的IP和容器IP。
3.如果docker服务挂掉,所有容器都将不能访问,那么客户访问网站时,连404页面都无法显示。
4.在安装nginx时还需要挂载目录,防止配置文件丢失,多一些操作步骤。
5.需要为之前的服务都手动分配一个IP,添加了容器的自定义network后,在新增容器时也是要注意是否需要选自定义的这个网络,需要的话还是得手动分配一个IP,如果忘记了就出问题了。
6.如果docker服务出问题了,网站就全面崩溃,连一个404页面都无法反馈给用户。
最终想到上面这堆麻烦的问题,拍拍手还是把Nginx安装在宿主机器上吧,如果这样,nginx转发时就不用关心IP地址了,容器也不用关心IP地址了,只需要关注端口就行。
两种方案的对比图如下:
(方案一:nginx以容器运行)
(方案二:nginx在宿主机运行)
当然两种方案都能实现,只是我选择了方便的方案二。
教程其实很简单,就是两步,先安装nginx然后修改nginx的配置文件,主要重点也在配置文件上,要弄明白配置文件的意思。
一、安装nginx到宿主机上
在centOS(8.x版本以上)上安装nginx比较简单,可以直接用yum命令安装:
sudo yum install nginx //安装ngxin
systemctl start nginx //启动nginx
systemctl status nginx //查询nginx服务当前状态
systemctl start nginx //把nginx加入开机启动
systemctl reload nginx //重启nginx,修改配置文件是需要使用到
如果centOS不是8版本以上的,安装要稍微复杂一些,可以参考其他资料。
二、修改nginx配置文件
我用的是WinSCP软件连接到宿主机上,然后找到配置文件的目录,默认安装目录在:/etc/nginx/nginx.conf
上图这段代码就是我的配置,大家可以参考一下(完整代码在最后),至于上图中SSL证书有很多的配置项,有一部分没有注释,那是因为我从腾讯云的教程手册中Copy过来的,我也不明白具体什么意思,不过从单词上可以大概了解。
配置上面的内容是,涉及到以下几个方面:
1.配置了SSL时,要把自己申请的对应域名的ssl证书文件拷贝到宿主机上,如下图:
2.域名解析时,因为我用了多个二级域名,在腾讯云上需要把每个二级域名都解析到宿主机:
3.在宿主机的防火墙设置中把以前用使用IP地址访问时的一些端口关闭掉,只开放nginx监听的80和443端口,当然我还保留了3306,方便我在本地连接数据库操作,如果考虑安全问题也可以关掉,只是管理数据库的时候就比较麻烦,需要在服务器上Web的数据库管理软件,通过Web登录之后来管理:
4.nginx的配置文件每次修改都需要重启服务才生效:
systemctl reload nginx
按照以上方式全部操作完成后,就大功告成,后续我只需要关心:
域名=>对应的宿主机端口=>对应的Docker容器
也就是我只需要记住nginx中配置文件里各个域名对应的宿主机端口,然后这个宿主机端口又对应的是哪个Docker中的容器,把这个3个地方的端口对应起来记住就OK了,不用去管什么IP地址之类的了。
完整配置代码如下
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
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;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 403;
}
server {
listen 80;
server_name xxxxx.freetiny.link;
location / {
proxy_pass http://127.0.0.1:9000;
}
}
server {
listen 80;
server_name xxxxx.freetiny.link;
location / {
proxy_pass http://127.0.0.1:8070;
}
}
server {
listen 80;
server_name xxxxx.freetiny.link;
location / {
proxy_pass http://127.0.0.1:8090;
}
}
server {
listen 80;
server_name xxxxx.freetiny.link;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
server {
listen 80;
server_name xxxxx.freetiny.link;
location / {
proxy_pass http://127.0.0.1:8000;
}
}
server {
listen 443 ssl;
server_name ftl.fit;
ssl_certificate "/etc/nginx/sslfile/1_ftl.fit_bundle.crt";
ssl_certificate_key "/etc/nginx/sslfile/2_ftl.fit.key";
ssl_session_cache shared:SSL:1m;
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;
location / {
proxy_pass http://127.0.0.1:81;
}
}
server {
listen 443 ssl;
server_name freetiny.link www.freetiny.link;
ssl_certificate "/etc/nginx/sslfile/1_freetiny.link_bundle.crt";
ssl_certificate_key "/etc/nginx/sslfile/2_freetiny.link.key";
ssl_session_cache shared:SSL:1m;
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;
location / {
proxy_pass http://127.0.0.1:82;
}
}
}