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
├── l
├── logs # ⽇志
│└── error.log
├── nginx
│├── Dockerfile
│├── f
│└── startup.sh
├── sites # 被代理站点配置
│├── f
│└── f
└── ssl # 证书⽂件
└── baipiaoquan.pem
有些⽂件是在后续的运⾏过程产⽣的,配置时,只需要把必要的⽂件和⽬录创建好就⾏。
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"
f /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 的配置中。
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/pes;
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-A 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 ,如果不正常,检查下配置是否有错误。
这个就这样,先放着,去创建应⽤。
三、添加应⽤
配置应⽤容器
同样使⽤ docker-compose 创建应⽤。
这是⼀个 php 项⽬,所以这个应⽤⾥⾄少需要 nginx 和 php-fpm 两个服务容器,项⽬⽬录结构如下:
baipiaoquan/
├── l
├── log
│└── nginx
│└── error.log
├── nginx
│├── Dockerfile
│├── log
│├── f
│├── sites
││└── f
│├── ssl
││├── baipiaoquan.key
││├── baipiaoquan.pem
│└── startup.sh
└── php-fpm
├── Dockerfile
└── php.ini
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_l
# 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
f /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.f
&& rm /etc/nginx/conf.f
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 ⽂件,也可以使⽤它默认的,那就要把这个相关的配置删掉。
服务 f 的配置
server {
listen 80 default_server;
# For https
listen 443 ssl default_server;
ssl_certificate /etc/nginx/ssl/3243258_baipiaoquan.pem;
ssl_certificate_key /etc/nginx/ssl/3243258_baipiaoquan.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 www.baipiaoquan;
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 的服务了,在 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/f,只需要把上⾯的配置拷贝下来,改⼏个地⽅就⾏,最终配置如下:
# 我这配的仅⽀持 https,如果没要求,这个就不需要
server {
listen 80;
server_name baipiaoquan www.baipiaoquan;
return 301 $host$request_uri;
}
server {
# 如果是 http 就配置这个
# listen 80 default_server;
# 如果是 https 就配置这个
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/3243258_baipiaoquan.pem;
ssl_certificate_key /etc/nginx/ssl/3243258_baipiaoquan.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 www.baipiaoquan;
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 baipiaoquan_nginx/; # 这个值就是应⽤ nginx 的容器名称
}
}
重新加载代理服务器的配置,在 nginx-proxy ⽬录下运⾏:
docker进入容器
# 先测试下配置⽂件,这步⼀定要执⾏成功
docker-compose exec nginx nginx -t
# 如果提⽰成功,则重新加载,否则就按提⽰检查修改配置⽂件
docker-compose exec nginx nginx -s reload
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
如何使用Docker构建虚拟网络实验环境
下一篇 »
发表评论