前言
代理的作用是什么?
- 多个域名解析到同一个服务器
- 方便一台服务器多个应用只对外开放一个端口
- 访问应用不需要带着烦人的端口,直接域名访问
- 应用隔离
- 降低耦合度
- ...
总的来说就是方便维护,并且在维护一个应用的时候,不影响其他应用 。
如何代理 (容器间如何通信)?
直接使用 nginx 的代理功能即可 (相关能力另行查阅),这里麻烦的就是 docker 容器间的通信 。
Docker 容器间通信的主要方式有以下 4 种:
- 通过容器 IP 访问:容器重启后,IP 会发生变化 。
- 通过宿主机的 ip:port 的方式访问:如果宿主机 IP 改变,就得每个应用都得改一遍,并且还要绑定端口,麻烦 。
- 通过 link 建立链接:相互依赖的太紧,不利于维护 。
- 自定义 network: 在同一个桥接网络中的容器可以相互访问 。
很明显,会选择 自定义 network 的方式,让相关应用链接到同一个网络,这样应用与应用、代理与被代理之间其实就没什么依赖,不仅维护方便,而且迁移也方便 。配置也不麻烦,只需要将常规的 IP 或域名换成相应的容器名即可 。
一、统一网络
那么,首先需要创建一个共用的桥接网络:
docker network create proxy-network# 查看docker network ls 二、代理服务容器
创建一个专门用来代理的 nginx 服务容器,取名:proxy-nginx,这里使用 docker-compose 构建,其目录结构最终如下:
proxy-nginx├── docker-compose.yml├── logs # 日志│└── error.log├── nginx│├── Dockerfile│├── nginx.conf│└── startup.sh├── sites # 被代理站点配置│├── baipiaoquan.com.conf│└── chaohuahui.com.conf└── ssl # 证书文件└── baipiaoquan.com.pem有些文件是在后续的运行过程产生的,配置时,只需要把必要的文件和目录创建好就行 。
docker-compose.yml
version: "3"networks: default:external:name: proxy-networkservices: nginx:build:context: ./nginxvolumes:- ./logs:/var/log/nginx- ./sites:/etc/nginx/sites-available- ./ssl:/etc/nginx/sslports:- "80:80"- "443:443"把对外的 80、443 的端口绑定到代理服务器,所有的应用都可以从这里进来 。
Dockerfile
FROM nginx:alpineLABEL maintainer="chuoke"COPY nginx.conf /etc/nginx/RUN apk update&& apk upgrade&& apk add --no-cache openssl&& apk add --no-cache bashRUN set -x ;addgroup -g 82 -S www-data ;adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1ADD ./startup.sh /opt/startup.shRUN sed -i 's/.//g' /opt/startup.shCMD ["/bin/bash", "/opt/startup.sh"]EXPOSE 80 443这里将会创建运行用户组和用户 www-data,方便配置和控制,这个名字会用在 nginx 的配置中 。
nginx.conf
user www-data;worker_processes 4;pid /run/nginx.pid;daemon off;events { worker_connections 2048; multi_accept on; use epoll;}http { server_tokens off; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 15; types_hash_max_size 2048; client_max_body_size 20M; include /etc/nginx/mime.types; default_type application/octet-stream; access_log /dev/stdout; error_log /dev/stderr; gzip on; gzip_disable "msie6"; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-available/*.conf; open_file_cache off; # Disabled for issue 619 charset UTF-8;}这个的内容拷贝 nginx 的默认就行,需要改的就是运行用户名,注意用户名要和前面的设置的保持一致 。
startup.sh
#!/bin/bash# Start crond in backgroundcrond -l 2 -b# Start nginx in foregroundnginx这个是用来启动 nginx 程序用的,内容目前比较少,主要是为以后扩充内容方便 。
启动代理服务容器
docker-compose up -d nginx 查看启动是否正常 docker-compose ps,如果不正常,检查下配置是否有错误 。
这个就这样,先放着,去创建应用 。
三、添加应用
添加一个站点 https://baipiaoquan.com/ 。
配置应用容器
同样使用 docker-compose 创建应用 。
这是一个 php 项目,所以这个应用里至少需要 nginx 和 php-fpm 两个服务容器,项目目录结构如下:
baipiaoquan/├── docker-compose.yml├── log│└── nginx│└── error.log├── nginx│├── Dockerfile│├── log│├── nginx.conf│├── sites││└── baipiaoquan.com.conf│├── ssl││├── baipiaoquan.com.key││├── baipiaoquan.com.pem│└── startup.sh└── php-fpm├── Dockerfile└── php.inidocker-compose.yml
version: '3'networks: proxy:external:name: ${PROXY_NETWORK_NAME} backend:driver: ${NETWORKS_DRIVER}services: php-fpm:build:context: ./php-fpmvolumes:- ./php-fpm/php.ini:/usr/local/etc/php/php.ini- ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER}${APP_CODE_CONTAINER_FLAG}networks:- backend nginx:build:context: ./nginxargs:- PHP_UPSTREAM_CONTAINER=${NGINX_PHP_UPSTREAM_CONTAINER}- PHP_UPSTREAM_PORT=${NGINX_PHP_UPSTREAM_PORT}volumes:- ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER}${APP_CODE_CONTAINER_FLAG}- ./log:/var/log/nginx- ./sites:/etc/nginx/sites-available- ./ssl:/etc/nginx/sslcontainer_name: ${COMPOSE_PROJECT_NAME}_nginxdepends_on:- php-fpmnetworks:- proxy- backend为了方便调整,这里使用了环境变量 。
注意 nginx 的容器名称 container_name: ${COMPOSE_PROJECT_NAME}_nginx,这个值很关键并且会在后续代理中用到 。
.env
# 宿主机中代码的位置APP_CODE_PATH_HOST=../# 容器中代码的位置APP_CODE_PATH_CONTAINER=/var/www# 这个是抄的 laradockAPP_CODE_CONTAINER_FLAG=:cached# 选择机器上的存储路径 。适用于所有储存系统DATA_PATH_HOST=~/.baipiaoquan/data### Drivers ################################################# All volumes driver VOLUMES_DRIVER=local # 网络驱动 NETWORKS_DRIVER=bridge # 代理网络名称,这是前面创建的 PROXY_NETWORK_NAME=proxy-network### Docker compose files ################################### COMPOSE_FILE=docker-compose.yml# Change the separator from : to ; on WindowsCOMPOSE_PATH_SEPARATOR=:# 项目名称COMPOSE_PROJECT_NAME=baipiaoquan使用的代理网络名称是:proxy-network,这是在前面创建的;
nginx 的容器名称会是:baipiaoquan_nginx 。
nginx 的 Dockerfile
这个文件可以把前面的那个直接拿来,然后加上关于 php 相关的就行了 。
FROM nginx:alpineCOPY nginx.conf /etc/nginx/RUN apk update&& apk upgrade&& apk --update add logrotate&& apk add --no-cache openssl&& apk add --no-cache bashRUN set -x ;addgroup -g 82 -S www-data ;adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1ARG PHP_UPSTREAM_CONTAINER=php-fpmARG PHP_UPSTREAM_PORT=9000# Set upstream conf and remove the default confRUN echo "upstream php-upstream { server ${PHP_UPSTREAM_CONTAINER}:${PHP_UPSTREAM_PORT}; }" > /etc/nginx/conf.d/upstream.conf&& rm /etc/nginx/conf.d/default.confADD ./startup.sh /opt/startup.shRUN sed -i 's/.//g' /opt/startup.shCMD ["/bin/bash", "/opt/startup.sh"]EXPOSE 80 443php-fpm 的 Dockerfile
FROM php:7.3-fpmARG PUID=1000ENV PUID ${PUID}ARG PGID=1000ENV PGID ${PGID}RUN groupmod -o -g ${PGID} www-data &&usermod -o -u ${PUID} -g www-data www-dataEXPOSE 9000WORKDIR /var/wwwCMD ["php-fpm"]别忘了 php.ini 文件,也可以使用它默认的,那就要把这个相关的配置删掉 。
服务 baipiaoquan.com.conf 的配置
server {listen 80 default_server;# For httpslisten 443 ssl default_server;ssl_certificate /etc/nginx/ssl/3243258_baipiaoquan.com.pem;ssl_certificate_key /etc/nginx/ssl/3243258_baipiaoquan.com.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;add_header X-Frame-Options "SAMEORIGIN";add_header X-XSS-Protection "1; mode=block";add_header X-Content-Type-Options "nosniff";# localhost 一定要server_name localhost baipiaoquan.com www.baipiaoquan.com;root /var/www/; # 这个和前面的配置保持一致index index.php index.html index.htm;location / {try_files $uri $uri/ /index.php$is_args$args;}location ~ .php$ {try_files $uri /index.php =404;fastcgi_pass php-upstream; # 这个是 nginx Dockerfile 里配置的fastcgi_index index.php;fastcgi_buffers 16 16k;fastcgi_buffer_size 32k;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;#fixes timeoutsfastcgi_read_timeout 600;include fastcgi_params;}location ~ /.ht {deny all;}location /.well-known/acme-challenge/ {root /var/www/letsencrypt/;log_not_found off;}}我这里算是配全了,其实可以精简,只需要配置需要的即可 。
启动应用
此时,已经可以启动 baipiaoquan.com 的服务了,在 baipiaoquan 的目录下运行:
docker-compose up -d nginx如果没有意外,应用应该启动并可以接收服务 。亦可以测试下,进入容器访问下 localhost,看看结果是不是想要的 。我是这样测试的:
docker-compose exec nginx wget localhost然后产看返回的数据大小,根据情况判断是不是成功了 。
可以通过下面的命令查看该应用是否成功连接到 proxy-network:
docker network inspect proxy-network接下来要让全世界的人都能访问到这个应用 。
添加代理配置到 nginx-proxy
注意:要先启动应用,然后再开始代理,不然会出现 nginx 找不到 upstream 报错 。
存放位置:proxy-nginx/sites/baipiaoquan.com.conf,只需要把上面的配置拷贝下来,改几个地方就行,最终配置如下:
# 我这配的仅支持 https,如果没要求,这个就不需要 server {listen 80;server_name baipiaoquan.com www.baipiaoquan.com;return 301 https://$host$request_uri; }server {# 如果是 http 就配置这个# listen 80 default_server;# 如果是 https 就配置这个listen 443 ssl;ssl_certificate/etc/nginx/ssl/3243258_baipiaoquan.com.pem;ssl_certificate_key/etc/nginx/ssl/3243258_baipiaoquan.com.key;ssl_session_timeout5m;ssl_protocolsTLSv1 TLSv1.1 TLSv1.2;ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;ssl_prefer_server_ciphers on;server_name baipiaoquan.com www.baipiaoquan.com;add_header X-Frame-Options "SAMEORIGIN";add_header X-XSS-Protection "1; mode=block";add_header X-Content-Type-Options "nosniff";location / {proxy_set_header Host $host;proxy_set_header X-Real-IP$remote_addr;proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto$scheme;proxy_set_header X-Forwarded-Host$host;proxy_set_header X-Forwarded-Port$server_port;proxy_pass http://baipiaoquan_nginx/; # 这个值就是应用 nginx 的容器名称}}重新加载代理服务器的配置,在 nginx-proxy 目录下运行:
# 先测试下配置文件,这步一定要执行成功docker-compose exec nginx nginx -t# 如果提示成功,则重新加载,否则就按提示检查修改配置文件docker-compose exec nginx nginx -s reload稍等片刻,如果一切顺利,那么现在全世界的人应该能访问到这个 https://baipiaoquan.com/ 网站了 。
如果还需要添加其他应用,是一样的逻辑,流程照搬 。例如我又加了一个应用:https://chaohuahui.com/,可以 ping 一下他们的 IP 是一样的 。
【Docker中使用Nginx代理多个应用站点的方法】以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网 。
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
