• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Docker中使用Nginx代理多个应用站点的方法

     前言

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

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

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

    - 应用隔离

    - 降低耦合度

    - ...

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

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

    直接使用 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-network
    
    services:
     nginx:
      build:
       context: ./nginx
      volumes:
       - ./logs:/var/log/nginx
       - ./sites:/etc/nginx/sites-available
       - ./ssl:/etc/nginx/ssl
      ports:
       - "80:80"
       - "443:443"
    
    

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

     Dockerfile

    FROM nginx:alpine
    
    LABEL maintainer="chuoke"
    
    COPY nginx.conf /etc/nginx/
    
    RUN apk update
      && apk upgrade
      && apk add --no-cache openssl
      && apk add --no-cache bash
    
    RUN set -x ;
      addgroup -g 82 -S www-data ;
      adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1
    
    ADD ./startup.sh /opt/startup.sh
    
    RUN sed -i 's/.//g' /opt/startup.sh
    
    CMD ["/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 background
    crond -l 2 -b
    
    # Start nginx in foreground
    nginx
    
    

    这个是用来启动 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.ini
    

    docker-compose.yml

    version: '3'
    
    networks:
     proxy:
      external:
        name: ${PROXY_NETWORK_NAME}
     backend:
      driver: ${NETWORKS_DRIVER}
    
    services:
     php-fpm:
       build:
        context: ./php-fpm
       volumes:
        - ./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: ./nginx
        args:
         - 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/ssl
       container_name: ${COMPOSE_PROJECT_NAME}_nginx
       depends_on:
        - php-fpm
       networks:
        - proxy
        - backend
    
    

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

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

    .env

    # 宿主机中代码的位置
    APP_CODE_PATH_HOST=../
    
    # 容器中代码的位置
    APP_CODE_PATH_CONTAINER=/var/www
    
    # 这个是抄的 laradock
    APP_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 Windows
    COMPOSE_PATH_SEPARATOR=:
    
    # 项目名称
    COMPOSE_PROJECT_NAME=baipiaoquan
    
    

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

    nginx 的 Dockerfile

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

    FROM nginx:alpine
    
    COPY nginx.conf /etc/nginx/
    
    RUN apk update
      && apk upgrade
      && apk --update add logrotate
      && apk add --no-cache openssl
      && apk add --no-cache bash
    
    RUN set -x ;
      addgroup -g 82 -S www-data ;
      adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1
    
    ARG PHP_UPSTREAM_CONTAINER=php-fpm
    ARG PHP_UPSTREAM_PORT=9000
    
    # Set upstream conf and remove the default conf
    RUN echo "upstream php-upstream { server ${PHP_UPSTREAM_CONTAINER}:${PHP_UPSTREAM_PORT}; }" > /etc/nginx/conf.d/upstream.conf
      && rm /etc/nginx/conf.d/default.conf
    
    ADD ./startup.sh /opt/startup.sh
    RUN sed -i 's/.//g' /opt/startup.sh
    
    CMD ["/bin/bash", "/opt/startup.sh"]
    
    EXPOSE 80 443
    

    php-fpm 的 Dockerfile

    FROM php:7.3-fpm
    
    ARG PUID=1000
    
    ENV PUID ${PUID}
    
    ARG PGID=1000
    
    ENV PGID ${PGID}
    
    RUN groupmod -o -g ${PGID} www-data &&
      usermod -o -u ${PUID} -g www-data www-data
    
    EXPOSE 9000
    
    WORKDIR /var/www
    
    CMD ["php-fpm"]
    
    

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

     服务 baipiaoquan.com.conf 的配置

    server {
    
      listen 80 default_server;
    
      # For https
      listen 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 timeouts
        fastcgi_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_timeout    5m;
      ssl_protocols       TLSv1 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 是一样的。

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

    上一篇:CentOS下 安装 Nginx的方法
    下一篇:阿里云安全规则配置详解
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

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