如何代理程式 (容器間如何通訊)?
直接使用 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 是一樣的。
以上是Docker中如何使用Nginx代理多個應用站點的詳細內容。更多資訊請關注PHP中文網其他相關文章!