Docker Compose 多專案共用 nginx 容器方案
在有限的資源下在同一台機器上面要跑不同專案時,如果統一在每個專案運行各自的nginx 就會造成port 80 重複使用而造成容器啟動失敗。
此時如果將nginx 抽離變成獨立的容器在透過 docker networks
進行關聯 即可完成統一由一個nginx proxy 代理全部對外容器,但如果有資源的話 可以透過 docker volumes
先對外進行掛載。
根據上述可以先定義 工作目錄 /data/htdocs/prj_?
之後就可以進行後續規劃,以下將會一步一步說明。
Step 1 創建docker networks
可以透過以下命令創建一個docker 內的共享網絡,方便後續用於連接各個容器。
docker network create shared-network
創建完成後可以透過 docker network ls
查詢。
Step 2 創建nginx-proxy
創建一個專門用來代理各個專案們的容器,並且記得將工作目錄映射進
# 如果有些配置檔案例如 ssl / *.conf 都可以設置上去
# 該範例僅為了展示如何實作多專案共用同一個nginx 所以沒有額外多加配置
name: tools
services:
nginx:
image: nginx
container_name: nginx
restart: always
volumes:
- /data/htdocs:/data/htdocs
ports:
- 80:80
- 443:443
networks:
shared-network:
networks:
shared-network:
external: true # 表示這個網路是外部創建的,不是由這個 compose 檔案創建
name: shared-network
Step 3 運行專案
該專案運行在 /data/htdocs/*
底下,透過 docker compose up -d
將檔案掛載進容器內,此時該http 也會自動掛載到 nginx 裡面。
而這份docker compose 主要關鍵是在於使用 和 nginx-proxy 共用同一個 docker networks。
name: a
services:
php:
image: docker.com/a/backend-php:test
pull_policy: always
container_name: ${COMPOSE_PROJECT_NAME}-php
working_dir: /app
volumes:
- ./http/static/upload:/app/http/static/upload
- ./http/static/assets:/app/http/static/assets
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- shared-network
web:
image: docker.com/a/frontend:test
pull_policy: always
container_name: ${COMPOSE_PROJECT_NAME}-web
working_dir: /app
environment:
- TZ=${TZ}
networks:
- shared-network
networks:
shared-network:
external: true
name: shared-network
Step 4 配置nginx-proxy *.conf
容器簡述:
web容器 : vue 編譯後的檔案放置於 /app 目錄, 已內建一個nginx 並且對80 開放。
php容器:檔案路徑也存放於 /app中,但唯一不太一樣的地方在於 /app/http/static 會存放一些生成的靜態資源需要保存,所以就映射到宿主機上。
server{
listen 80;
client_max_body_size 60M;
client_body_buffer_size 512k;
# 以下的配置 有將/data/htdocs 掛載進nginx 目錄
# 可以讀取掛載在宿主機上的資源 處理靜態資源訪問
location /static/assets/ {
alias /data/htdocs/a/http/static/assets/;
}
location /static/upload/ {
alias /data/htdocs/a/http/static/upload/;
}
# 前端反向代理
location / {
proxy_pass http://test-web;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
# 添�~J| CORS �~Y�| �
#add_header Access-Control-Allow-Origin *;
}
# 以下均為後端反向代理
# 而要注意的地方為 SCRIPT_FILENAME 要配置php 入口檔案
location ^~ /sale/ {
fastcgi_pass test-php:9000
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /app/http/sale.php;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_ROOT /app/http;
}
location ^~ /api/ {
fastcgi_pass test-php:9000;
include fastcgi.conf;
fastcgi_param SCRIPT_FILENAME /app/http/api.php;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_ROOT /app/http;
}
location /backend/ {
fastcgi_pass test-php:9000;
include fastcgi_params;
fastcgi_param DOCUMENT_ROOT /app/http;
fastcgi_param SCRIPT_FILENAME /app/http/backend.php;
fastcgi_param SCRIPT_NAME /backend.php;
fastcgi_param REQUEST_URI $request_uri;
}
}
Step 5 Nginx Reload
最後全部配置好且激活後,要記得將nginx 進行刷新 nginx -s reload
,往後若有其他專案 則可複製這個範本進行多次部署。
以下提供一個更新腳本,推送新的image時可以直接運行並且自動刷新nginx。
#!/bin/sh
DIR="$( cd "$( dirname "$0" )" && pwd )"
echo "--- 更新 docker compose ---"
docker-compose -f $DIR/docker-compose.yml up -d
echo "--- 刷新nginx ---"
docker exec nginx nginx -s reload