您的位置:首页 > 技术中心 > 运维 >

Docker中如何使用Nginx代理多个应用站点

时间:2023-05-13 22:02

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

直接使用 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: ./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: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.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# 这个是抄的 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 443

php-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 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 是一样的。

以上就是Docker中如何使用Nginx代理多个应用站点的详细内容,更多请关注Gxl网其它相关文章!

热门排行

今日推荐

热门手游