Docker安装Nginx进行反向代理80、443端口
Docker安装Nginx进行反向代理80、443端口
背景
我们在使用tomcat或者SpringBoot部署web项目的时候,一般端口都是8080。如果我们想在外网访问,要使用ip/域名+8080。但是在http协议中,80端口是默认的端口,可以通过输入ip/域名不需要输入端口直接访问。在https协议中,默认端口号为443端口。
一般我们使用nginx进行反向代理,那么如何在docker容器中进行代理呢?以下为本人记录使用Docker安装Nginx实现反向代理的过程。
以下默认已经安装过Docker,以及会使用Docker。
在Docker中安装nginx镜像
# pull一个最新的nginx镜像
[root@VM-12-16-centos ~]# docker pull nginx:latest
# 查看是否安装成功
[root@VM-12-16-centos ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
blog latest 7e027d1c164e 2 hours ago 677MB
nginx latest c919045c4c2b 2 weeks ago 142MB
centos latest 5d0da3dc9764 6 months ago 231MB
java 8 d23bdf5b1b1b 5 years ago 643MB
启动测试Docker容器
# 宿主机80端口映射到docker80端口,容器名字为test-nginx 使用的镜像是nginx
[root@VM-12-16-centos ~]# docker run -d -p 80:80 --name test-nginx nginx
78837a1792ae88ee460e1f4deba1d246c03de291c3ee36ce17cb28a75d8c8505
[root@VM-12-16-centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
78837a1792ae nginx "/docker-entrypoint.…" 8 seconds ago Up 7 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp test-nginx
# 在机器内部测试访问
[root@VM-12-16-centos ~]# curl cofel.cn
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
查看测试容器中nginx配置
首先,在linux中配置nginx的时候,我们需要去conf文件中进行配置,将8080端口代理到80端口或者443端口。
我们先去看看我们在docker中创建的nginx容器,配置文件中是怎么写的,以便于我们之后的配置。
# 首先,通过exec进入容器
[root@VM-12-16-centos nginx]# docker exec -it test-nginx /bin/bash
# 进入nginx配置文件目录中
root@cb1ae0e8816b:/# cd /etc/nginx/
root@cb1ae0e8816b:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
# 查看nginx.conf文件中的内容
root@cb1ae0e8816b:/etc/nginx# cat nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
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;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
# 进入/etc/nginx/conf.d文件夹下
root@cb1ae0e8816b:/etc/nginx/conf.d# ls
default.conf
我们发现,最后一段include /etc/nginx/conf.d/*.conf;
,nginx会把conf.d下的所有文件导入。
在这个文件夹下是各种conf配置文件,创建不同的配置文件就可以进行不同的反向代理。
因此,我们可以将容器中的/etc/nginx/conf.d文件夹,挂载到宿主机的一个位置,那么我们首先需要创建一个文件夹以便于与容器进行挂在绑定。
测试完毕,可以删除测试容器,进行下一步的nginx的配置。
# 查询id
[root@VM-12-16-centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
78837a1792ae nginx "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp test-nginx
# 关闭
[root@VM-12-16-centos ~]# docker stop 78837a1792ae
78837a1792ae
# 删除
[root@VM-12-16-centos ~]# docker rm 78837a1792ae
78837a1792ae
[root@VM-12-16-centos ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Nginx容器的创建与挂载
在配置文件之前,我们需要知道Springboot的ip地址,因为docker的每个容器都是隔开的,docker0会给每一个容器分配一个ip,我们首先先获取ip。
[root@VM-12-16-centos nginx]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
141697a12b04 blog "java -jar /app.jar" 3 hours ago Up 3 hours 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp blog
[root@VM-12-16-centos nginx]# docker exec -it 141697a12b04 /bin/bash
root@141697a12b04:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 141697a12b04
这里看到,ip为 172.17.0.2
那么我们接下来就要创建容器所要映射的宿主机配置文件的地址了。
[root@VM-12-16-centos nginx]# cd /usr/local/docker/nginx/
# 创建挂载Nginx的配置文件:nginx.conf
[root@VM-12-16-centos nginx]# touch nginx.conf
# 创建挂载Nginx的conf.d目录
[root@VM-12-16-centos nginx]# mkdir conf.d
# 创建挂载Nginx的证书目录
[root@VM-12-16-centos nginx]# mkdir cert
# 创建挂载Nginx的日志目录
[root@VM-12-16-centos nginx]# mkdir logs
[root@VM-12-16-centos nginx]# ls
cert conf.d logs nginx.conf
# 将容器中的nginx.conf复制至宿主机的/usr/local/docker/nginx下。
[root@VM-12-16-centos nginx]# docker cp 46c3499c15af:/etc/nginx/nginx.conf /usr/local/docker/nginx/
#将容器中conf.d下的default.conf复制到宿主机中。
[root@VM-12-16-centos nginx]# docker cp 46c3499c15af:/etc/nginx/conf.d/default.conf /usr/local/docker/nginx/conf.d/
注意:一定要将容器中的配置文件复制至宿主机一份,不然会报错,提示没有找到相关配置文件,无法启动容器。
如果复制后文件中没有内容,就自己手动复制一下,两者内容必须相同,不然无法启动容器。启动后内容就会同步了,文件夹中的文件也会同步。
如果启动不了的话,可以通过log查看
# 首先判断是否启动成功
[root@VM-12-16-centos nginx]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
61e912d3eb8b nginx "/docker-entrypoint.…" 4 minutes ago Up 2 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp blog_nginx
# 如果这里没有显示的话,输入-a查看详细内容可以看到。
[root@VM-12-16-centos conf.d]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
61e912d3eb8b nginx "/docker-entrypoint.…" 16 seconds ago Exited (1) 15 seconds ago blog_nginx
# 我这里就是由于文件中没有内容出现了错误。
# 使用docker的log指令可以查看出现了什么错误。
[root@VM-12-16-centos conf.d]# docker logs afd455958d24
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf is not a file or does not exist
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
nginx: [emerg] no "events" section in configuration
# 这里通过日志可以看出来,提示default.conf为空,没有"events"配置。
# 由于我这里nginx.conf中也是空的,所以提示"events"没有配置。
# 以下是nginx.conf/default.conf完整内容
# nginx.conf的
[root@VM-12-16-centos nginx]# cat nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
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;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
# defalut.conf的。
[root@VM-12-16-centos conf.d]# cat default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
接下来,创建nginx反向代理容器
# 在创建反向代理容器之前,一定要将之前的测试容器删掉,不然会报错,因为占用了80端口。
# 报错记录如下
[root@VM-12-16-centos nginx]# docker: Error response from daemon: driver failed programming external connectivity on endpoint blog_nginx (93c0d43cfad3ca92c64a121ec2ca2486e7f8c2ae68a20faccff3404c383e61dc): Bind for 0.0.0.0:80 failed: port is already allocated.
创建容器
# 创建nginx容器
[root@VM-12-16-centos nginx]# docker run -d -p 80:80 -p 443:443 --name blog_nginx -v /usr/local/docker/nginx/nginx.conf:/etc/nginx/nginx.conf -v /usr/local/docker/nginx/conf.d:/etc/nginx/conf.d -v /usr/local/docker/nginx/logs:/var/log/nginx -v /usr/local/docker/nginx/cert:/etc/nginx/cert nginx
afd455958d24e940c8ac77aed028244890fa3e73f6246a186a509f660495ccd1
# 解释挂载的东西是什么:
-v /usr/local/docker/nginx/nginx.conf:/etc/nginx/nginx.conf # 这个是Nginx的配置文件
-v /usr/local/docker/nginx/conf.d:/etc/nginx/conf.d # 这个是所有的配置文件目录
-v /usr/local/docker/nginx/logs:/var/log/nginx # 日志文件目录
-v /usr/local/docker/nginx/cert:/etc/nginx/cert # 证书文件目录
上传证书,进行文件配置
首先,我们先去下载证书,如果是阿里云就去阿里云申请免费的SSL证书,如果是腾讯云就去腾讯云申请。都有免费的SSL证书,申请后下载即可。
我这里是腾讯云,下载完之后解压会出现四个文件
文件夹名称:cloud.tencent.com_nginx
文件夹内容:
cloud.tencent.com_bundle.crt 证书文件
cloud.tencent.com_bundle.pem 证书文件(可忽略该文件)
cloud.tencent.com.key 私钥文件
cloud.tencent.com.csr CSR 文件
详细的使用教程官网介绍的非常清楚,这里贴一个官网的地址,跟着一步一步搞就行,文件直接复制粘贴略微修改即可。
https://cloud.tencent.com/document/product/400/35244
将证书放到/usr/local/docker/nginx/cert
中即可,由于与容器挂载了,所以文件会自动同步到容器中。
# 这里是我的配置,可以参考一下。
[root@VM-12-16-centos conf.d]# cat blog.conf
server {
listen 80;
server_name cofel.cn;
rewrite ^/(.*)$ https://cofel.cn:443/$1 permanent;
}
server {
listen 443 ssl;
server_name cofel.cn;
ssl_certificate /etc/nginx/cert/www.cofel.cn_bundle.crt;
ssl_certificate_key /etc/nginx/cert/www.cofel.cn.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://172.17.0.2:8080;
}
}
这里172.17.0.2:8080,是我的SpringBoot项目所在的容器ip,由于nginx和springboot都是在docker的不同容器中的,所以需要用内网ip才能进行访问。
如果学过docker中的网络,可以使用自定义网络Bridge进行操作,会更加的方便,我这里图省事,就不弄了。
配置完毕后重启即可
[root@VM-12-16-centos nginx]# docker restart blog_nginx
# 查看是否运行
[root@VM-12-16-centos images]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
61e912d3eb8b nginx "/docker-entrypoint.…" 7 minutes ago Up 4 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp blog_nginx
结语
至此,在Docker中使用Nginx进行反向代理80、443端口就完成了,启动还有很多优化方案,后续可能会再写一篇文章对优化进行总结。
--------------------END--------------------
评论