前言
代理的作用是什么?
- 多個(gè)域名解析到同一個(gè)服務(wù)器
- 方便一臺(tái)服務(wù)器多個(gè)應(yīng)用只對(duì)外開(kāi)放一個(gè)端口
- 訪問(wèn)應(yīng)用不需要帶著煩人的端口,直接域名訪問(wèn)
- 應(yīng)用隔離
- 降低耦合度
- ...
總的來(lái)說(shuō)就是方便維護(hù),并且在維護(hù)一個(gè)應(yīng)用的時(shí)候,不影響其他應(yīng)用。
如何代理 (容器間如何通信)?
直接使用 nginx 的代理功能即可 (相關(guān)能力另行查閱),這里麻煩的就是 docker 容器間的通信。
Docker 容器間通信的主要方式有以下 4 種:
- 通過(guò)容器 IP 訪問(wèn):容器重啟后,IP 會(huì)發(fā)生變化。
- 通過(guò)宿主機(jī)的 ip:port 的方式訪問(wèn):如果宿主機(jī) IP 改變,就得每個(gè)應(yīng)用都得改一遍,并且還要綁定端口,麻煩。
- 通過(guò) link 建立鏈接:相互依賴的太緊,不利于維護(hù)。
- 自定義 network: 在同一個(gè)橋接網(wǎng)絡(luò)中的容器可以相互訪問(wèn)。
很明顯,會(huì)選擇 自定義 network 的方式,讓相關(guān)應(yīng)用鏈接到同一個(gè)網(wǎng)絡(luò),這樣應(yīng)用與應(yīng)用、代理與被代理之間其實(shí)就沒(méi)什么依賴,不僅維護(hù)方便,而且遷移也方便。配置也不麻煩,只需要將常規(guī)的 IP 或域名換成相應(yīng)的容器名即可。
一、統(tǒng)一網(wǎng)絡(luò)
那么,首先需要?jiǎng)?chuàng)建一個(gè)共用的橋接網(wǎng)絡(luò):
docker network create proxy-network
# 查看
docker network ls
二、代理服務(wù)容器
創(chuàng)建一個(gè)專門用來(lái)代理的 nginx 服務(wù)容器,取名:proxy-nginx,這里使用 docker-compose 構(gòu)建,其目錄結(jié)構(gòu)最終如下:
proxy-nginx
├── docker-compose.yml
├── logs # 日志
│ └── error.log
├── nginx
│ ├── Dockerfile
│ ├── nginx.conf
│ └── startup.sh
├── sites # 被代理站點(diǎn)配置
│ ├── baipiaoquan.com.conf
│ └── chaohuahui.com.conf
└── ssl # 證書(shū)文件
└── baipiaoquan.com.pem
有些文件是在后續(xù)的運(yùn)行過(guò)程產(chǎn)生的,配置時(shí),只需要把必要的文件和目錄創(chuàng)建好就行。
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"
把對(duì)外的 80、443 的端口綁定到代理服務(wù)器,所有的應(yīng)用都可以從這里進(jìn)來(lái)。
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
這里將會(huì)創(chuàng)建運(yùn)行用戶組和用戶 www-data,方便配置和控制,這個(gè)名字會(huì)用在 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;
}
這個(gè)的內(nèi)容拷貝 nginx 的默認(rèn)就行,需要改的就是運(yùn)行用戶名,注意用戶名要和前面的設(shè)置的保持一致。
startup.sh
#!/bin/bash
# Start crond in background
crond -l 2 -b
# Start nginx in foreground
nginx
這個(gè)是用來(lái)啟動(dòng) nginx 程序用的,內(nèi)容目前比較少,主要是為以后擴(kuò)充內(nèi)容方便。
啟動(dòng)代理服務(wù)容器
docker-compose up -d nginx
查看啟動(dòng)是否正常 docker-compose ps ,如果不正常,檢查下配置是否有錯(cuò)誤。
這個(gè)就這樣,先放著,去創(chuàng)建應(yīng)用。
三、添加應(yīng)用
添加一個(gè)站點(diǎn) https://baipiaoquan.com/。
配置應(yīng)用容器
同樣使用 docker-compose 創(chuàng)建應(yīng)用。
這是一個(gè) php 項(xiàng)目,所以這個(gè)應(yīng)用里至少需要 nginx 和 php-fpm 兩個(gè)服務(wù)容器,項(xiàng)目目錄結(jié)構(gòu)如下:
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
為了方便調(diào)整,這里使用了環(huán)境變量。
注意 nginx 的容器名稱 container_name: ${COMPOSE_PROJECT_NAME}_nginx,這個(gè)值很關(guān)鍵并且會(huì)在后續(xù)代理中用到。
.env
# 宿主機(jī)中代碼的位置
APP_CODE_PATH_HOST=../
# 容器中代碼的位置
APP_CODE_PATH_CONTAINER=/var/www
# 這個(gè)是抄的 laradock
APP_CODE_CONTAINER_FLAG=:cached
# 選擇機(jī)器上的存儲(chǔ)路徑。適用于所有儲(chǔ)存系統(tǒng)
DATA_PATH_HOST=~/.baipiaoquan/data
### Drivers ################################################
# All volumes driver
VOLUMES_DRIVER=local
# 網(wǎng)絡(luò)驅(qū)動(dòng)
NETWORKS_DRIVER=bridge
# 代理網(wǎng)絡(luò)名稱,這是前面創(chuàng)建的
PROXY_NETWORK_NAME=proxy-network
### Docker compose files ##################################
#
COMPOSE_FILE=docker-compose.yml
# Change the separator from : to ; on Windows
COMPOSE_PATH_SEPARATOR=:
# 項(xiàng)目名稱
COMPOSE_PROJECT_NAME=baipiaoquan
使用的代理網(wǎng)絡(luò)名稱是:proxy-network,這是在前面創(chuàng)建的;
nginx 的容器名稱會(huì)是:baipiaoquan_nginx。
nginx 的 Dockerfile
這個(gè)文件可以把前面的那個(gè)直接拿來(lái),然后加上關(guān)于 php 相關(guān)的就行了。
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 文件,也可以使用它默認(rèn)的,那就要把這個(gè)相關(guān)的配置刪掉。
服務(wù) 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/; # 這個(gè)和前面的配置保持一致
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; # 這個(gè)是 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;
}
}
我這里算是配全了,其實(shí)可以精簡(jiǎn),只需要配置需要的即可。
啟動(dòng)應(yīng)用
此時(shí),已經(jīng)可以啟動(dòng) baipiaoquan.com 的服務(wù)了,在 baipiaoquan 的目錄下運(yùn)行:
docker-compose up -d nginx
如果沒(méi)有意外,應(yīng)用應(yīng)該啟動(dòng)并可以接收服務(wù)。亦可以測(cè)試下,進(jìn)入容器訪問(wèn)下 localhost,看看結(jié)果是不是想要的。我是這樣測(cè)試的:
docker-compose exec nginx wget localhost
然后產(chǎn)看返回的數(shù)據(jù)大小,根據(jù)情況判斷是不是成功了。
可以通過(guò)下面的命令查看該應(yīng)用是否成功連接到 proxy-network:
docker network inspect proxy-network
接下來(lái)要讓全世界的人都能訪問(wèn)到這個(gè)應(yīng)用。
添加代理配置到 nginx-proxy
注意:要先啟動(dòng)應(yīng)用,然后再開(kāi)始代理,不然會(huì)出現(xiàn) nginx 找不到 upstream 報(bào)錯(cuò)。
存放位置:proxy-nginx/sites/baipiaoquan.com.conf,只需要把上面的配置拷貝下來(lái),改幾個(gè)地方就行,最終配置如下:
# 我這配的僅支持 https,如果沒(méi)要求,這個(gè)就不需要
server {
listen 80;
server_name baipiaoquan.com www.baipiaoquan.com;
return 301 https://$host$request_uri;
}
server {
# 如果是 http 就配置這個(gè)
# listen 80 default_server;
# 如果是 https 就配置這個(gè)
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/; # 這個(gè)值就是應(yīng)用 nginx 的容器名稱
}
}
重新加載代理服務(wù)器的配置,在 nginx-proxy 目錄下運(yùn)行:
# 先測(cè)試下配置文件,這步一定要執(zhí)行成功
docker-compose exec nginx nginx -t
# 如果提示成功,則重新加載,否則就按提示檢查修改配置文件
docker-compose exec nginx nginx -s reload
稍等片刻,如果一切順利,那么現(xiàn)在全世界的人應(yīng)該能訪問(wèn)到這個(gè) https://baipiaoquan.com/ 網(wǎng)站了。
如果還需要添加其他應(yīng)用,是一樣的邏輯,流程照搬。例如我又加了一個(gè)應(yīng)用:https://chaohuahui.com/ ,可以 ping 一下他們的 IP 是一樣的。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。