{"id":16467375,"url":"https://github.com/flandredaisuki/traefik-nginx-php-note","last_synced_at":"2026-05-05T14:32:32.538Z","repository":{"id":91801911,"uuid":"175355468","full_name":"FlandreDaisuki/traefik-nginx-php-note","owner":"FlandreDaisuki","description":"(traefik + nginx + php) with docker","archived":false,"fork":false,"pushed_at":"2019-03-14T10:17:20.000Z","size":675,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-22T20:38:35.419Z","etag":null,"topics":["docker","docker-compose","nginx","php","traefik"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FlandreDaisuki.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-13T05:54:32.000Z","updated_at":"2020-04-30T06:07:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"71b406a2-bc72-436c-804a-30c30a5ec290","html_url":"https://github.com/FlandreDaisuki/traefik-nginx-php-note","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/FlandreDaisuki/traefik-nginx-php-note","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlandreDaisuki%2Ftraefik-nginx-php-note","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlandreDaisuki%2Ftraefik-nginx-php-note/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlandreDaisuki%2Ftraefik-nginx-php-note/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlandreDaisuki%2Ftraefik-nginx-php-note/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FlandreDaisuki","download_url":"https://codeload.github.com/FlandreDaisuki/traefik-nginx-php-note/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlandreDaisuki%2Ftraefik-nginx-php-note/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32653538,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-05T11:29:49.557Z","status":"ssl_error","status_checked_at":"2026-05-05T11:29:48.587Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","nginx","php","traefik"],"created_at":"2024-10-11T11:47:10.167Z","updated_at":"2026-05-05T14:32:32.521Z","avatar_url":"https://github.com/FlandreDaisuki.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# traefik-nginx-php-note\n\n因為想架的服務大家都想要 :80 跟 :443，但我只有單機電腦，所以必須架一層 proxy manager 來根據 path 來轉到各種服務\n\n[DevOps 台灣](https://t.me/devopstw)推薦了 [traefik](https://traefik.io/) 這個工具覺得不錯\n\n- [traefik-nginx-php-note](#traefik-nginx-php-note)\n  - [需求前提](#需求前提)\n  - [安裝 traefik](#安裝-traefik)\n  - [設置 traefik](#設置-traefik)\n  - [安裝 nginx \u0026 php](#安裝-nginx--php)\n  - [設置 nginx](#設置-nginx)\n  - [部屬伺服器](#部屬伺服器)\n  - [實驗驗證](#實驗驗證)\n  - [Q\u0026A](#qa)\n\n## 需求前提\n\n- 使用 Docker \u0026 Compose\n- 單機服務(非 cloud)\n- 很多服務都想要 :80 :443，而且有很多個 docker-compose.yml (不寫在一起)\n\n## 安裝 traefik\n\n先用 traefik 官方文件的兩張圖來介紹和解釋 traefik 做了什麼\n\n![traefik architecture](traefik-architecture.png)\n\n![traefik internal](traefik-internal.png)\n\n對外讓 :80 :443 接到 traefik，traefik 根據 hostname/path 跟內部 port 接到各個服務\n\n而安裝 traefik 就一行指令：\n\n```sh\n$ docker pull traefik\n```\n\n## 設置 traefik\n\n可以先看 [appleboy 大大的文章](https://blog.wu-boy.com/2019/01/deploy-service-using-traefik-and-docker/)和[官方文件](https://docs.traefik.io/user-guide/docker-and-lets-encrypt/)知道大概做了什麼\n\n我的設定是偏向官方文件，但我放在 ~/traefik 底下：\n\n```sh\n~/traefik\n├── acme.json\n├── docker-compose.yml\n└── traefik.toml\n```\n\n因為改了路徑，所以 docker-compose.yml 的 volumes 必須改掉。\n\n```yml\nservices:\n  traefik:\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock\n      - ./traefik.toml:/traefik.toml\n      - ./acme.json:/acme.json\n```\n\ntraefik.toml 則是把 email 改成自己的\n\n```toml\n[docker]\nendpoint = \"unix:///var/run/docker.sock\"\nwatch = true\nexposedByDefault = false\n\n[acme]\nemail = \"acme@mail.flandre.tw\" # 你的信箱，這邊用我的假信箱舉例\nstorage = \"acme.json\"\nentryPoint = \"https\"\nonHostRule = true\n```\n\n最後把 acme.json 權限改成 600 即可\n\n```sh\n~/traefik $ chmod 600 acme.json\n~/traefik $ docker network create web # 這裡的 web 對應 docker-compose.yml 的 networks，只有第一次需要\n~/traefik $ docker-compose up -d\n```\n\n## 安裝 nginx \u0026 php\n\n這個網路上已經一堆教學了不多做介紹\n\n```sh\n$ docker pull nginx:alpine\n$ docker pull php:fpm-alpine\n```\n\n## 設置 nginx\n\n因為我的硬碟是 mount 上去的，比較大，故我選擇在這邊設定 (假設 mount 在 `/media/3TB`)\n\n這邊先創三個資料夾\n\n```sh\n/media/3TB $ mkdir -p ./web/nginx/conf.d ./web/nginx/logs ./web/www\n\n/media/3TB $ tree web\nweb # 伺服器設定和部屬的資料夾\n├── nginx # 一些 nginx 的設定檔和日誌\n│   ├── conf.d\n│   └── logs\n└── www # 伺服器服務的根\n```\n\n創兩個設定檔 web/.env 和 web/docker-compose.yml 給 docker\n\n```env\nDOMAIN=flandre.tw\nLOCAL_VOLUME=./www/flandre.tw\n```\n\n```yml\nversion: \"3.6\"\n\nservices:\n  nginx:\n    image: nginx:alpine\n    container_name: web-nginx\n    restart: unless-stopped\n    networks:\n      - web # 跟 traefik 同一個，traefik 會幫你做事\n      - net-nginx-php # 下面解釋\n    depends_on:\n      - php\n    volumes:\n      - \"./nginx/conf.d:/etc/nginx/conf.d\" # 這邊讓設定檔可以被放進去\n      - \"./nginx/logs/$DOMAIN:/etc/nginx/logs/$DOMAIN\" # 這邊是 domain 的 logs\n      - \"./nginx/logs:/var/log/nginx/logs\" # 這個是 nginx 本身的 logs\n      - \"$LOCAL_VOLUME:/var/www/$DOMAIN\" # 這個是伺服器服務的根，為了讓 nginx 看得到檔案\n    labels:\n      - \"traefik.docker.network=web\" # 這個 web 對應上面 create 的名字\n      - \"traefik.enable=true\"\n      - \"traefik.basic.frontend.rule=Host:$DOMAIN\" # 你的 domain\n      - \"traefik.basic.port=80\" # 這邊對應伺服器預設的 port，nginx 是 80\n      # 可參考 https://github.com/nginxinc/docker-nginx/blob/master/mainline/alpine/Dockerfile#L142\n      - \"traefik.basic.protocol=http\"\n  php:\n    image: php:fpm-alpine\n    container_name: web-php\n    networks:\n      - net-nginx-php # 下面解釋\n    expose:\n      - \"9000\" # nginx 會用 :9000 呼叫 php 的 fastcgi\n      # 可參考 https://github.com/docker-library/php/blob/master/7.3/alpine3.9/fpm/Dockerfile#L226\n    volumes:\n      - \"$LOCAL_VOLUME:/var/www/$DOMAIN\" # 這個是伺服器服務的根，為了讓 php 看得到檔案\n\nnetworks:\n  web:\n    external: true\n  net-nginx-php: # 這個網路只存在在 docker 內部，用來溝通 nginx 和 php\n    name: net-nginx-php\n```\n\n和另外一個設定檔 web/nginx/conf.d/flandre.tw.conf (這邊叫什麼 .conf 都可以) 給 nginx\n\n```conf\nserver {\n    index index.php index.html;\n    server_name flandre.tw; # 你的 domain\n\n    charset utf-8;\n\n    # 下面兩個對應伺服器 docker-compose.yml 的 services.nginx.volumes 的第二項\n    error_log  /etc/nginx/logs/flandre.tw/error.log;\n    access_log /etc/nginx/logs/flandre.tw/access.log;\n\n    # 下面這個對應伺服器 docker-compose.yml 的 services.nginx.volumes 的第四項\n    root /var/www/flandre.tw;\n\n    location ~ \\.php$ {\n        try_files $uri =404;\n        fastcgi_split_path_info ^(.+\\.php)(/.+)$;\n        fastcgi_pass php:9000; # 這邊就是上面說呼叫 fastcgi 的界面\n        fastcgi_index index.php;\n        include fastcgi_params;\n        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n        fastcgi_param PATH_INFO $fastcgi_path_info;\n    }\n}\n```\n\n最後放個測試頁面 web/www/flandre.tw/index.php\n\n```php\n\u003c?php\nprint \"200 ok\\n\";\n?\u003e\n```\n\n最後資料夾結構會是這樣：\n\n```sh\n/media/3TB $ tree web\nweb\n├── docker-compose.yml\n├── .env\n├── nginx\n│   ├── conf.d\n│   │   └── flandre.tw.conf\n│   └── logs\n└── www\n    └── flandre.tw\n        └── index.php\n```\n\n## 部屬伺服器\n\n```sh\n/media/3TB/web $ docker-compose up -d\n/media/3TB/web $ curl https://flandre.tw/\n200 ok\n/media/3TB/web $\n```\n\n## 實驗驗證\n\n為了實驗是否可以讓另一個服務聽在 :80 並順利執行\n\n我寫了一個 Dockerfile 並 build 成 image：\n\n```dockerfile\nFROM python:3.7-alpine\n\nWORKDIR /root\n\nEXPOSE 80\n\nVOLUME [\"/root\"]\n\nCMD [\"python\", \"-m\", \"http.server\", \"80\"]\n```\n\n```sh\n$ docker build . -t python-http-server\n```\n\n另外創個資料夾 /media/3TB/web/w2 寫了個 docker-compose.yml 來起伺服器\n\n```yml\nversion: \"3.6\"\n\nservices:\n  py3-http-server:\n    image: py3-http-server\n    container_name: py3-http-server\n    restart: unless-stopped\n    networks:\n      - web # 跟 traefik 同一個\n    volumes:\n      - \".:/root\"\n    labels:\n      - \"traefik.docker.network=web\"\n      - \"traefik.enable=true\"\n      - \"traefik.basic.frontend.rule=Host:www.flandre.tw\" # 另一個 domain，用 CNAME 指到同一個主機\n      - \"traefik.basic.port=80\" # image 聽 80\n      - \"traefik.basic.protocol=http\"\n\nnetworks:\n  web:\n    external: true\n```\n\n並寫個 index.html 來區別這個 domain 的服務\n\n```html\n418 I'm a teapot\n```\n\n完成後資料夾結構會是這樣：\n\n```sh\n/media/3TB/web\n├── docker-compose.yml # ← nginx\n├── nginx\n│   ├── conf.d\n│   │   └── flandre.tw.conf\n│   └── logs\n├── w2\n│   ├── docker-compose.yml # ← python-http-server\n│   └── index.html # ← 418\n└── www\n    └── flandre.tw # ← nginx root\n        └── index.php # ← 200\n```\n\n最後在 web/w2 部屬這個小伺服器\n\n```sh\n/media/3TB/web/w2 $ docker-compose up -d\n```\n\n用 curl 驗證一下\n\n```sh\n$ curl -L flandre.tw\n200 ok\n$ curl -L www.flandre.tw\n418 I'm a teapot\n```\n\n## Q\u0026A\n\nQ: 為什麼不全部放在 /media/3TB 裡面，要另外把 traefik 的設定放在 ~/traefik ？\n\n```txt\n因為我的硬碟是 NTFS，他不給我 chmod，而 acme.json 權限必須是 600\n(´・ω・`)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflandredaisuki%2Ftraefik-nginx-php-note","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflandredaisuki%2Ftraefik-nginx-php-note","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflandredaisuki%2Ftraefik-nginx-php-note/lists"}