系统城装机大师 - 固镇县祥瑞电脑科技销售部宣传站!

当前位置:首页 > server > anz > 详细页面

Docker中使用Nginx代理多个应用站点的方法

时间:2019-12-22来源:系统城作者:电脑系统城

 前言

代理的作用是什么?
- 多个域名解析到同一个服务器

- 方便一台服务器多个应用只对外开放一个端口

- 访问应用不需要带着烦人的端口,直接域名访问

- 应用隔离

- 降低耦合度

- ...

总的来说就是方便维护,并且在维护一个应用的时候,不影响其他应用。

如何代理 (容器间如何通信)?

直接使用 nginx 的代理功能即可 (相关能力另行查阅),这里麻烦的就是 docker 容器间的通信。

Docker 容器间通信的主要方式有以下 4 种:

- 通过容器 IP 访问:容器重启后,IP 会发生变化。

- 通过宿主机的 ip:port 的方式访问:如果宿主机 IP 改变,就得每个应用都得改一遍,并且还要绑定端口,麻烦。

- 通过 link 建立链接:相互依赖的太紧,不利于维护。

- 自定义 network: 在同一个桥接网络中的容器可以相互访问。

很明显,会选择 自定义 network 的方式,让相关应用链接到同一个网络,这样应用与应用、代理与被代理之间其实就没什么依赖,不仅维护方便,而且迁移也方便。配置也不麻烦,只需要将常规的 IP 或域名换成相应的容器名即可。

一、统一网络

那么,首先需要创建一个共用的桥接网络:


 
  1. docker network create proxy-network
  2.  
  3. # 查看
  4. docker network ls
  5.  

 二、代理服务容器

创建一个专门用来代理的 nginx 服务容器,取名:proxy-nginx,这里使用 docker-compose 构建,其目录结构最终如下:


 
  1. proxy-nginx
  2. ├── docker-compose.yml
  3. ├── logs # 日志
  4. │ └── error.log
  5. ├── nginx
  6. │ ├── Dockerfile
  7. │ ├── nginx.conf
  8. │ └── startup.sh
  9. ├── sites # 被代理站点配置
  10. │ ├── baipiaoquan.com.conf
  11. │ └── chaohuahui.com.conf
  12. └── ssl # 证书文件
  13. └── baipiaoquan.com.pem

有些文件是在后续的运行过程产生的,配置时,只需要把必要的文件和目录创建好就行。

 docker-compose.yml


 
  1. version: "3"
  2.  
  3. networks:
  4. default:
  5. external:
  6. name: proxy-network
  7.  
  8. services:
  9. nginx:
  10. build:
  11. context: ./nginx
  12. volumes:
  13. - ./logs:/var/log/nginx
  14. - ./sites:/etc/nginx/sites-available
  15. - ./ssl:/etc/nginx/ssl
  16. ports:
  17. - "80:80"
  18. - "443:443"
  19.  

把对外的 80、443 的端口绑定到代理服务器,所有的应用都可以从这里进来。

 Dockerfile


 
  1. FROM nginx:alpine
  2.  
  3. LABEL maintainer="chuoke"
  4.  
  5. COPY nginx.conf /etc/nginx/
  6.  
  7. RUN apk update
  8. && apk upgrade
  9. && apk add --no-cache openssl
  10. && apk add --no-cache bash
  11.  
  12. RUN set -x ;
  13. addgroup -g 82 -S www-data ;
  14. adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1
  15.  
  16. ADD ./startup.sh /opt/startup.sh
  17.  
  18. RUN sed -i 's/.//g' /opt/startup.sh
  19.  
  20. CMD ["/bin/bash", "/opt/startup.sh"]
  21.  
  22. EXPOSE 80 443
  23.  

这里将会创建运行用户组和用户 www-data,方便配置和控制,这个名字会用在 nginx 的配置中。

 nginx.conf


 
  1. user www-data;
  2. worker_processes 4;
  3. pid /run/nginx.pid;
  4. daemon off;
  5.  
  6. events {
  7. worker_connections 2048;
  8. multi_accept on;
  9. use epoll;
  10. }
  11.  
  12. http {
  13. server_tokens off;
  14. sendfile on;
  15. tcp_nopush on;
  16. tcp_nodelay on;
  17. keepalive_timeout 15;
  18. types_hash_max_size 2048;
  19. client_max_body_size 20M;
  20. include /etc/nginx/mime.types;
  21. default_type application/octet-stream;
  22. access_log /dev/stdout;
  23. error_log /dev/stderr;
  24.  
  25. gzip on;
  26. gzip_disable "msie6";
  27.  
  28. ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  29. 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';
  30.  
  31. include /etc/nginx/conf.d/*.conf;
  32. include /etc/nginx/sites-available/*.conf;
  33.  
  34. open_file_cache off; # Disabled for issue 619
  35. charset UTF-8;
  36. }
  37.  

这个的内容拷贝 nginx 的默认就行,需要改的就是运行用户名,注意用户名要和前面的设置的保持一致。

 startup.sh


 
  1. #!/bin/bash
  2.  
  3. # Start crond in background
  4. crond -l 2 -b
  5.  
  6. # Start nginx in foreground
  7. nginx
  8.  

这个是用来启动 nginx 程序用的,内容目前比较少,主要是为以后扩充内容方便。

 启动代理服务容器


 
  1. docker-compose up -d nginx

 查看启动是否正常 docker-compose ps ,如果不正常,检查下配置是否有错误。

这个就这样,先放着,去创建应用。

 三、添加应用

添加一个站点 https://baipiaoquan.com/。

 配置应用容器

同样使用 docker-compose 创建应用。

这是一个 php 项目,所以这个应用里至少需要 nginx 和 php-fpm 两个服务容器,项目目录结构如下:


 
  1. baipiaoquan/
  2. ├── docker-compose.yml
  3. ├── log
  4. │ └── nginx
  5. │ └── error.log
  6. ├── nginx
  7. │ ├── Dockerfile
  8. │ ├── log
  9. │ ├── nginx.conf
  10. │ ├── sites
  11. │ │ └── baipiaoquan.com.conf
  12. │ ├── ssl
  13. │ │ ├── baipiaoquan.com.key
  14. │ │ ├── baipiaoquan.com.pem
  15. │ └── startup.sh
  16. └── php-fpm
  17. ├── Dockerfile
  18. └── php.ini

docker-compose.yml


 
  1. version: '3'
  2.  
  3. networks:
  4. proxy:
  5. external:
  6. name: ${PROXY_NETWORK_NAME}
  7. backend:
  8. driver: ${NETWORKS_DRIVER}
  9.  
  10. services:
  11. php-fpm:
  12. build:
  13. context: ./php-fpm
  14. volumes:
  15. - ./php-fpm/php.ini:/usr/local/etc/php/php.ini
  16. -${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER}${APP_CODE_CONTAINER_FLAG}
  17. networks:
  18. - backend
  19.  
  20. nginx:
  21. build:
  22. context: ./nginx
  23. args:
  24. - PHP_UPSTREAM_CONTAINER=${NGINX_PHP_UPSTREAM_CONTAINER}
  25. - PHP_UPSTREAM_PORT=${NGINX_PHP_UPSTREAM_PORT}
  26. volumes:
  27. -${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER}${APP_CODE_CONTAINER_FLAG}
  28. - ./log:/var/log/nginx
  29. - ./sites:/etc/nginx/sites-available
  30. - ./ssl:/etc/nginx/ssl
  31. container_name: ${COMPOSE_PROJECT_NAME}_nginx
  32. depends_on:
  33. - php-fpm
  34. networks:
  35. - proxy
  36. - backend
  37.  

为了方便调整,这里使用了环境变量。

注意 nginx 的容器名称 container_name: ${COMPOSE_PROJECT_NAME}_nginx,这个值很关键并且会在后续代理中用到。

.env


 
  1. # 宿主机中代码的位置
  2. APP_CODE_PATH_HOST=../
  3.  
  4. # 容器中代码的位置
  5. APP_CODE_PATH_CONTAINER=/var/www
  6.  
  7. # 这个是抄的 laradock
  8. APP_CODE_CONTAINER_FLAG=:cached
  9.  
  10. # 选择机器上的存储路径。适用于所有储存系统
  11. DATA_PATH_HOST=~/.baipiaoquan/data
  12.  
  13. ### Drivers ################################################
  14.  
  15. # All volumes driver
  16. VOLUMES_DRIVER=local
  17.  
  18. # 网络驱动
  19. NETWORKS_DRIVER=bridge
  20.  
  21. # 代理网络名称,这是前面创建的
  22. PROXY_NETWORK_NAME=proxy-network
  23.  
  24. ### Docker compose files ##################################
  25. #
  26. COMPOSE_FILE=docker-compose.yml
  27.  
  28. # Change the separator from : to ; on Windows
  29. COMPOSE_PATH_SEPARATOR=:
  30.  
  31. # 项目名称
  32. COMPOSE_PROJECT_NAME=baipiaoquan
  33.  

使用的代理网络名称是:proxy-network,这是在前面创建的;
nginx 的容器名称会是:baipiaoquan_nginx。

nginx 的 Dockerfile

这个文件可以把前面的那个直接拿来,然后加上关于 php 相关的就行了。


 
  1. FROM nginx:alpine
  2.  
  3. COPY nginx.conf /etc/nginx/
  4.  
  5. RUN apk update
  6. && apk upgrade
  7. && apk --update add logrotate
  8. && apk add --no-cache openssl
  9. && apk add --no-cache bash
  10.  
  11. RUN set -x ;
  12. addgroup -g 82 -S www-data ;
  13. adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1
  14.  
  15. ARG PHP_UPSTREAM_CONTAINER=php-fpm
  16. ARG PHP_UPSTREAM_PORT=9000
  17.  
  18. # Set upstream conf and remove the default conf
  19. RUN echo "upstream php-upstream { server ${PHP_UPSTREAM_CONTAINER}:${PHP_UPSTREAM_PORT}; }" >/etc/nginx/conf.d/upstream.conf
  20. && rm /etc/nginx/conf.d/default.conf
  21.  
  22. ADD ./startup.sh /opt/startup.sh
  23. RUN sed -i 's/.//g' /opt/startup.sh
  24.  
  25. CMD ["/bin/bash", "/opt/startup.sh"]
  26.  
  27. EXPOSE 80 443

php-fpm 的 Dockerfile


 
  1. FROM php:7.3-fpm
  2.  
  3. ARG PUID=1000
  4.  
  5. ENV PUID ${PUID}
  6.  
  7. ARG PGID=1000
  8.  
  9. ENV PGID ${PGID}
  10.  
  11. RUN groupmod -o -g ${PGID} www-data &&
  12. usermod -o -u ${PUID} -g www-data www-data
  13.  
  14. EXPOSE 9000
  15.  
  16. WORKDIR /var/www
  17.  
  18. CMD ["php-fpm"]
  19.  

别忘了 php.ini 文件,也可以使用它默认的,那就要把这个相关的配置删掉。

 服务 baipiaoquan.com.conf 的配置


 
  1. server {
  2.  
  3. listen 80 default_server;
  4.  
  5. # For https
  6. listen 443 ssl default_server;
  7. ssl_certificate /etc/nginx/ssl/3243258_baipiaoquan.com.pem;
  8. ssl_certificate_key /etc/nginx/ssl/3243258_baipiaoquan.com.key;
  9. ssl_session_timeout 5m;
  10. ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  11. ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  12. ssl_prefer_server_ciphers on;
  13.  
  14. add_header X-Frame-Options "SAMEORIGIN";
  15. add_header X-XSS-Protection "1; mode=block";
  16. add_header X-Content-Type-Options "nosniff";
  17.  
  18. # localhost 一定要
  19. server_name localhost baipiaoquan.com www.baipiaoquan.com;
  20. root /var/www/; # 这个和前面的配置保持一致
  21. index index.php index.html index.htm;
  22.  
  23. location / {
  24. try_files $uri $uri/ /index.php$is_args$args;
  25. }
  26.  
  27. location ~ .php$ {
  28. try_files $uri /index.php =404;
  29. fastcgi_pass php-upstream; # 这个是 nginx Dockerfile 里配置的
  30. fastcgi_index index.php;
  31. fastcgi_buffers 16 16k;
  32. fastcgi_buffer_size 32k;
  33. fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  34. #fixes timeouts
  35. fastcgi_read_timeout 600;
  36. include fastcgi_params;
  37. }
  38.  
  39. location ~ /.ht {
  40. deny all;
  41. }
  42.  
  43. location /.well-known/acme-challenge/ {
  44. root /var/www/letsencrypt/;
  45. log_not_found off;
  46. }
  47. }
  48.  

我这里算是配全了,其实可以精简,只需要配置需要的即可。

 启动应用

此时,已经可以启动 baipiaoquan.com 的服务了,在 baipiaoquan 的目录下运行:


 
  1. docker-compose up -d nginx

如果没有意外,应用应该启动并可以接收服务。亦可以测试下,进入容器访问下 localhost,看看结果是不是想要的。我是这样测试的:


 
  1. docker-compose exec nginx wget localhost

然后产看返回的数据大小,根据情况判断是不是成功了。
可以通过下面的命令查看该应用是否成功连接到 proxy-network:


 
  1. docker network inspect proxy-network

接下来要让全世界的人都能访问到这个应用。

添加代理配置到 nginx-proxy

注意:要先启动应用,然后再开始代理,不然会出现 nginx 找不到 upstream 报错。

存放位置:proxy-nginx/sites/baipiaoquan.com.conf,只需要把上面的配置拷贝下来,改几个地方就行,最终配置如下:


 
  1. # 我这配的仅支持 https,如果没要求,这个就不需要
  2.  
  3. server {
  4. listen 80;
  5. server_name baipiaoquan.com www.baipiaoquan.com;
  6. return 301 https://$host$request_uri;
  7. }
  8.  
  9. server {
  10.  
  11. # 如果是 http 就配置这个
  12. # listen 80 default_server;
  13.  
  14. # 如果是 https 就配置这个
  15. listen 443 ssl;
  16. ssl_certificate /etc/nginx/ssl/3243258_baipiaoquan.com.pem;
  17. ssl_certificate_key /etc/nginx/ssl/3243258_baipiaoquan.com.key;
  18. ssl_session_timeout 5m;
  19. ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  20. ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  21. ssl_prefer_server_ciphers on;
  22.  
  23. server_name baipiaoquan.com www.baipiaoquan.com;
  24.  
  25. add_header X-Frame-Options "SAMEORIGIN";
  26. add_header X-XSS-Protection "1; mode=block";
  27. add_header X-Content-Type-Options "nosniff";
  28.  
  29. location / {
  30. proxy_set_header Host $host;
  31. proxy_set_header X-Real-IP $remote_addr;
  32. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  33. proxy_set_header X-Forwarded-Proto $scheme;
  34. proxy_set_header X-Forwarded-Host $host;
  35. proxy_set_header X-Forwarded-Port $server_port;
  36. proxy_pass http://baipiaoquan_nginx/; # 这个值就是应用 nginx 的容器名称
  37. }
  38. }

重新加载代理服务器的配置,在 nginx-proxy 目录下运行:


 
  1. # 先测试下配置文件,这步一定要执行成功
  2. docker-compose exec nginx nginx -t
  3.  
  4. # 如果提示成功,则重新加载,否则就按提示检查修改配置文件
  5. docker-compose exec nginx nginx -s reload
  6.  

稍等片刻,如果一切顺利,那么现在全世界的人应该能访问到这个 https://baipiaoquan.com/ 网站了。 

如果还需要添加其他应用,是一样的逻辑,流程照搬。例如我又加了一个应用:https://chaohuahui.com/ ,可以 ping 一下他们的 IP 是一样的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

分享到:

相关信息

系统教程栏目

栏目热门教程

人气教程排行

站长推荐

热门系统下载